[Delphi] 纯文本查看 复制代码
program O10EditorKeygen;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Character;
const
TYPE_BYTE = $9C;
VERSION_ARG = 17;
TABLE_RAW_HEX =
'b844cb39674f75231172015fda24bb3ec60717354b77f9638872821721480f0f' +
'0f675f5be85a314869775b7847157a2b9212d138321ba14244223335607b4377' +
'103bab1e00008153ae12021da877036f9230c0438e0a3c2dbf0c9562fa6ff030' +
'e010f734fb17f428952f0d355a1d365a0b06cc15cc13fd0acf3b60286b067133' +
'e414cd30673a5d17136ad66df909342d827b1e58996b527688518d5c7179852c' +
'c01ff515110dcc685c5ef54964435e27bc0d1e2de37cee4c40585532082e2e11' +
'5a06786906149272e7784531b7215617bf1d7740d638c23f8a12314a6e03ad2d' +
'd669a041920140256746dd004f1ffc6ace401057df66fe623e4bdb411f238235' +
'9a07f6554406a71cd243161bc928723f7010145fab74143e6e254b44d9507053' +
'4b09420fe620d82f5e2e8b77026d1771697aea7f2846b55b716cba19993a7639' +
'cd548d17886e24017e531333172d8e2bbe103d2a8205d159db63a1379a48d630' +
'465c216a767a1c0ee760c71f650cb879b459f42726739a798217ba505c6d112a' +
'1b6e86633c0e923f903402558960b555d11f392cc235802f7a2bfd649a75e84c' +
'f0048551a8019579ad2c5b3f6001e638d8417663422a3533192ca25151585c08' +
'ab172903c70a772bb377ac300719ec2bd0025203d333a90ff35d2561bf06ad22' +
'7169b858e50dca5f56640d70db73a956fd59b75ae20b0e33dd0d3c5b603c5d49' +
'a659bd53916d5e4c8d31d94979503d10e342ce611d12d57eed60e114f24e2d21' +
'f0330127965a43628b5ea71fbe2f096f490d004a701cae5777244e00727e1e56' +
'33008c460224cc5dc67a5078c724af58342df60d08478a35111efb3c1c45712b' +
'9552a77721078956f375ef0ff1240f12e70a990152449c338e5ba1276d27a70b' +
'7b1bdc60827f4b4f0770db67d9574a4fe8521262fc2c53200603396a23048018' +
'8a77f319f01623463709ae565c67c243fd45ca65f24f600dcb22fd0b3b64fe3a' +
'a67ff63b79356244f8314018974f17322a096a4c6102b55f74016501f14a6333' +
'f4182d716971996efe7aab5de82e2b7cb475db6eb66f835fd66d2a3cc2052d29' +
'db4422054f5f9a144065485dea151d332069454f9f693a48050f453b6c7c203b' +
'fe709d74f6617441f131b0627b5750273315132908388c585634ef1aec003c0f' +
'4247a77d6c7a794b8732bb5eb8586578f24fed001e6969625f25a2247e1fc162' +
'cd7d8a2ffe173b64b8188377fe603b25a363bb344f21035bf471155f9f6e311a' +
'0427cf7a3868892877466118eb69f51bc95ea80b466bca6a2a42431e0e5f4d51' +
'8c013e41e9267630fa1ded015a6ff4492b641b46f207707d57266513c50b166b' +
'4948e0651c6e521fb651025a693fd72bcd7abf2d803ee6510f67f25c030acd21' +
'6102ff5c1e06ae335f34b63b754a815df45d7b255b2c5c0a2755a4164539f216';
var
TABLE: array [0 .. 255] of Cardinal;
procedure BuildTable;
var
I, Off: Integer;
B0, B1, B2, B3: Byte;
begin
for I := 0 to 255 do
begin
Off := I * 8 + 1; // Delphi string is 1-indexed
B0 := StrToInt('$' + TABLE_RAW_HEX[Off] + TABLE_RAW_HEX[Off + 1]);
B1 := StrToInt('$' + TABLE_RAW_HEX[Off + 2] + TABLE_RAW_HEX[Off + 3]);
B2 := StrToInt('$' + TABLE_RAW_HEX[Off + 4] + TABLE_RAW_HEX[Off + 5]);
B3 := StrToInt('$' + TABLE_RAW_HEX[Off + 6] + TABLE_RAW_HEX[Off + 7]);
TABLE[I] := (Cardinal(B3) shl 24) or (Cardinal(B2) shl 16) or
(Cardinal(B1) shl 8) or B0;
end;
end;
function ToUpper(B: Byte): Byte; inline;
begin
if (B >= $61) and (B <= $7A) then
Result := B - 32
else
Result := B;
end;
// 模拟 JavaScript Math.imul(a, b) 32位整型乘法溢出
function Imul(A, B: Cardinal): Cardinal; inline;
begin
Result := Cardinal(Int64(A) * Int64(B));
end;
function Checksum(const Name: string; Flag: Boolean; A3, A4: Byte): Cardinal;
var
Data: TBytes;
V5, V9, V10, V11, V12, Product, V17, V18, V20: Cardinal;
Cu, IdxA, IdxB: Byte;
I: Integer;
begin
Data := TEncoding.UTF8.GetBytes(Name);
V5 := 0;
V9 := 0;
V10 := (15 * A4) and $FF;
V11 := 0;
V12 := (17 * A3) and $FF;
for I := 0 to Length(Data) - 1 do
begin
Cu := ToUpper(Data[I]);
if Flag then
begin
IdxA := (Cu + 13) and $FF;
IdxB := (Cu + 47) and $FF;
V20 := V9;
end
else
begin
IdxA := (Cu + 63) and $FF;
IdxB := (Cu + 23) and $FF;
V20 := V11;
end;
V17 := V5 + TABLE[Cu];
V18 := TABLE[IdxA] xor V17;
Product := Imul(TABLE[IdxB], V18);
V5 := TABLE[V10] + TABLE[V12] + TABLE[V20] + Product;
V12 := (V12 + 9) and $FF;
V10 := (V10 + 13) and $FF;
V9 := (V9 + 19) and $FF;
V11 := (V11 + 7) and $FF;
end;
Result := V5;
end;
function Ad76(B: Byte): Byte; inline;
begin
Result := (((B xor $18) + 61) xor $A7) and $FF;
end;
function C5b(V20: Word): Integer; inline;
var
V1: Integer;
begin
V1 := ((V20 xor $7892) + 19760) and $FFFF;
V1 := V1 xor $3421;
if (V1 mod 11) <> 0 then
Exit(0);
Result := (V1 div 11) and $FFFF;
end;
procedure GetBestV20ForParam(out V20: Word; out V21: Word);
var
W: Integer;
R: Integer;
begin
for W := 0 to $FFFF do
begin
R := C5b(W);
if (R >= 1) and (R <= 1000) then
begin
V20 := W;
V21 := R;
Exit;
end;
end;
raise Exception.Create('无法找到合法的 v20 参数');
end;
procedure GetBestBForVersion(out B: Byte; out N2: Byte);
var
TempB, TempN2, BestB, BestN2: Integer;
begin
BestB := 0;
BestN2 := -1;
for TempB := 0 to 255 do
begin
TempN2 := Ad76(TempB);
if TempN2 > BestN2 then
begin
BestB := TempB;
BestN2 := TempN2;
end;
end;
if BestN2 < VERSION_ARG then
raise Exception.Create('版本参数不满足要求');
B := BestB;
N2 := BestN2;
end;
function FormatLicense(const Raw: array of Byte): string;
var
HexStr: string;
I: Integer;
begin
HexStr := '';
for I := 0 to Length(Raw) - 1 do
HexStr := HexStr + Format('%.2X', [Raw[I]]);
Result := Format('%s-%s-%s-%s', [HexStr.Substring(0, 4), HexStr.Substring(4,
4), HexStr.Substring(8, 4), HexStr.Substring(12, 4)]);
end;
function Keygen(const Name: string): string;
var
V20, V21: Word;
BestB, BestN2: Byte;
Chk: Cardinal;
B0, B1, B2, B4, B5, B6, B7: Byte;
begin
GetBestV20ForParam(V20, V21);
GetBestBForVersion(BestB, BestN2);
Chk := Checksum(Name, True, 0, V21 and $FF);
B4 := Chk and $FF;
B5 := (Chk shr 8) and $FF;
B6 := (Chk shr 16) and $FF;
B7 := (Chk shr 24) and $FF;
B2 := ((V20 and $FF) xor B5) and $FF;
B1 := (((V20 shr 8) and $FF) xor B7) and $FF;
B0 := (BestB xor B6) and $FF;
Result := FormatLicense([B0, B1, B2, TYPE_BYTE, B4, B5, B6, B7]);
end;
function Nibble(C: Char): Byte;
var
O: Integer;
begin
O := Ord(C);
if (O >= $30) and (O <= $39) then
Exit(O - $30);
if ((O - 79) and $DF) = 0 then
Exit(0);
if O = $6C then
Exit(1);
if (O >= $61) and (O <= $7A) then
Exit((O - 87) and $FF);
if (O >= $41) and (O <= $5A) then
Exit((O - 55) and $FF);
Result := 0;
end;
function DecodeLicense(const Lic: string; out Bytes: TBytes): Boolean;
var
S, Chars: string;
I: Integer;
begin
Bytes := nil;
S := Lic.Replace('o', '0').Replace('O', '0').Replace('l', '1');
if (S.Length <> 19) or (S[5] <> '-') or (S[10] <> '-') or (S[15] <> '-') then
Exit(False);
Chars := S.Replace('-', '');
if Chars.Length <> 16 then
Exit(False);
SetLength(Bytes, 8);
for I := 0 to 7 do
begin
Bytes[I] := ((16 * Nibble(Chars[I * 2 + 1])) + Nibble(Chars[I * 2 + 2]
)) and $FF;
end;
Result := True;
end;
function Verify(const Name: string; const Lic: string): Boolean;
var
By: TBytes;
V39, V40, V41, V42, N5999655_1, V44, V45, V46, A1_108, N2, N255: Byte;
V20: Word;
V21: Integer;
Chk: Cardinal;
Ok: Boolean;
begin
if not DecodeLicense(Lic, By) then
Exit(False);
V39 := By[0];
V40 := By[1];
V41 := By[2];
V42 := By[3];
N5999655_1 := By[4];
V44 := By[5];
V45 := By[6];
V46 := By[7];
if V42 <> TYPE_BYTE then
Exit(False);
V20 := ((V44 xor V41) + ((V46 xor V40) shl 8)) and $FFFF;
A1_108 := Ad76((V45 xor V39) and $FF);
V21 := C5b(V20);
N2 := A1_108;
if not((N2 <> 0) and ((V21 - 1) <= $3E7)) then
Exit(False);
if N2 < 2 then
N255 := N2
else
N255 := 0;
Chk := Checksum(Name, True, N255 and $FF, V21 and $FF);
Ok := (N5999655_1 = (Chk and $FF)) and (V44 = ((Chk shr 8) and $FF)) and
(V45 = ((Chk shr 16) and $FF)) and (V46 = ((Chk shr 24) and $FF));
if not Ok then
Exit(False);
Result := VERSION_ARG <= A1_108;
end;
var
Username: string;
License: string;
begin
try
BuildTable;
Writeln('==============================================');
Writeln(' 010 Editor 注册码生成器 (9C 算法) ');
Writeln('==============================================');
Writeln;
Write('请输入用户名 (Username): ');
Readln(Username);
Username := Username.Trim;
if Username = '' then
begin
Writeln('[错误] 用户名不能为空!');
Exit;
end;
if Username.Length > 100 then
begin
Writeln('[错误] 用户名不能超过100个字符!');
Exit;
end;
Writeln('正在计算中...');
License := Keygen(Username);
Writeln;
Writeln('生成的注册码 (License Key):');
Writeln('----------------------------------------------');
Writeln(License);
Writeln('----------------------------------------------');
Write('自动校验状态: ');
if Verify(Username, License) then
begin
// 绿色高亮显示 PASS
if TOSVersion.Platform = pfWindows then
begin
Writeln('PASS');
end
else
Writeln('PASS');
end
else
begin
Writeln('FAIL');
end;
except
on E: Exception do
Writeln('[异常] ' + E.ClassName + ': ' + E.Message);
end;
Writeln;
Write('按下回车键退出...');
Readln;
end.