public boolean checkLicense() {
boolean licenseValidity = false;
if (this.isLicenseExpired()) {
this.displayMessage("This license has been expired. Please contact PE Biosystems Sales Representative.");
return false;
}
final String licenseString = this.readLicense();
if (licenseString != null) {
licenseValidity = this.checkLicense(licenseString);
}
if (!licenseValidity) {
final Frame aFrame = new Frame();
aFrame.setIconImage(this.iconImage);
final RegistrarView registrarView = new RegistrarView(aFrame, this);
registrarView.show();
if (this.license == null) {
return false;
}
if (!this.checkLicense(this.license)) {
this.displayMessage("The application could not start because the registration code is not valid.");
return false;
}
this.writeLicense();
licenseValidity = true;
}
if (this.validLicense == null) {
return false;
}
this.appNumber = this.validLicense.getAppNumber();
this.serialNumber = this.validLicense.getSerialNumber();
this.numUsers = this.validLicense.getNumUsers();
if (this.validLicense.isExceedsLegalLicenseCount(this.numUsers, this.license)) {
this.displayMessage("The maximum concurrent user number of this license has been reached.");
return false;
}
this.validLicense.startListening(this.license);
return true;
}
这个类调用另一个类进行注册码校验,这个类是 License.class,如下图所示:
其主要注册算法代码如下:
[Java] 纯文本查看复制代码
public boolean areLicenseDigitsValid() {
final byte[] digit = new byte[11];
this.appNumber = 0;
this.serialNumber = 0;
this.numUsers = 0;
final long scrambleCode = this.licenseDigits[9] * 16 + this.licenseDigits[10];
this.unscrambleDigits(this.licenseDigits, digit, scrambleCode);
final byte crc = this.getCRCDigits(digit, 8L);
final byte testCrc = digit[8];
boolean valid = crc == testCrc;
if (valid) {
final int testSerialNumber = digit[0] * 4096 + digit[1] * 256 + digit[2] * 16 + digit[3];
final int testAppNumber = digit[4] * 256 + digit[5] * 16 + digit[6] * 1;
final int testNumUsers = digit[7];
final int testScrambleCode = this.scrambleCode(testSerialNumber + testAppNumber + testNumUsers);
valid = (scrambleCode == testScrambleCode);
if (valid) {
this.licenseHasBeenValidated = true;
this.appNumber = (short)testAppNumber;
this.serialNumber = (short)testSerialNumber;
this.numUsers = (short)testNumUsers;
}
}
return valid;
}
private byte getNthRandomByte(final long num) {
final long kTwoToThe31MinusOne = 2147483647L;
final long kTwoToThe31MinusTwo = kTwoToThe31MinusOne - 1L;
final long kByteScaling = (kTwoToThe31MinusOne - 1L) / 256L;
final long kTwoToThe32Plus1 = kTwoToThe31MinusOne * 2L + 2L;
final long kSevenToThe5 = 16807L;
long r = 1L;
for (int k = 0; k < num + 12L; ++k) {
r *= kSevenToThe5;
r = (int)r;
if (r < 0L) {
r += kTwoToThe32Plus1;
}
r %= kTwoToThe31MinusOne;
}
final byte b = (byte)(r / kByteScaling);
return b;
}
private void unscrambleDigits(final byte[] scramDigits, final byte[] clearDigits, final long scrambleCode) {
for (int k = 0; k < 9; ++k) {
final long scramblebyte = 9L * scrambleCode + k;
final byte nthrandombyte = this.getNthRandomByte(scramblebyte);
clearDigits[k] = (byte)(scramDigits[k] - nthrandombyte & 0xF);
}
}
private byte getCRCDigits(final byte[] digit, final long numToCRC) {
long crc = 0L;
for (int k = 0; k < (int)numToCRC; ++k) {
crc <<= 1;
if (crc > 15L) {
crc |= 0x1L;
}
crc += digit[k];
crc &= 0xFL;
}
return (byte)crc;
}
private short scrambleCode(final long number) {
short key = 0;
final int scrambleCase = (int)number % 451;
switch (scrambleCase) {
case 0: {
key = 90;
break;
}
case 1: {
key = 181;
break;
}
//这里省略了400多个分支,可自己去反编译看源码
case 449: {
key = 101;
break;
}
case 450: {
key = 231;
break;
}
}
return key;
}