123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- unit mR1Encrypt;
- interface
- uses
- Windows, SysUtils, Forms, Classes;
- type
- ER1Error = class(Exception);
- function SimpleR1Check: Integer;
- function CheckR1Times(AIsOnOpen: Boolean = False): Integer;
- function CheckR1Hours: Integer;
- function CheckR1AdditionEdition: Integer;
- function CheckR1Edition(AOpening: Boolean = False): Integer;
- function CheckR1Data: Integer;
- function CheckR1LimitDate: Integer;
- function GetR1ReportOprNum(AOpr: string): Integer;
- function GetR1ReportFuncNum(AOpr: string): Integer;
- function OpenR1Dog: Integer;
- procedure SaveR1Dog;
- function R1UserAuthorize(AAuthorize: array of Byte): Boolean;
- function R1UserUpdateLock(AUpdateData: array of Byte): Boolean;
- implementation
- uses
- Math, CommonMessages, ScUtils, mEncryptPWD, CryptUtils, ScConfig,
- mEncryptUnit, mEncryptTypes, mEncryptEditions, Rockey1,
- PHPWebDm;
- const
- _R1_Key: array [0..16] of Byte = ($00, $00, $00, $0D, $CE, $CE, $CD, $CF, $8C, $8B, $BC, $90, $8D, $8B, $92, $9E, $AC);
- _R1_PID: array [0..11] of Byte = ($00, $00, $00, $08, $06, $71, $23, $3D, $53, $05, $0A, $78);
- _R1_UserPin: array [0..19] of Byte = ($00, $00, $00, $10, $39, $EF, $50, $6B, $41, $0D, $CC, $52, $39, $EF, $50, $6B, $41, $0D, $CC, $52);
- var
- _R1DogHandle: THandle = 0;
- _R1DogOpened: Boolean = False;
- _R1_HID: array [0..15] of Byte;
- function DecryptKey: string;
- var
- arrResult: array of Byte;
- iOutputLength: Integer;
- begin
- iOutputLength := GetOutputLength(_R1_Key);
- SetLength(arrResult, iOutputLength);
- Decrypt_Simple(_R1_Key, Length(_R1_Key), arrResult, iOutputLength);
- SetString(Result, PChar(@arrResult[0]), iOutputLength);
- end;
- function DecryptValues(AInput: array of Byte; ALength: Integer; var AOutput: array of Byte): Integer;
- var
- pKey: Pointer;
- begin
- pKey := nil;
- Decrypt_BlowFish(DecryptKey, @AInput[0], ALength, pKey, Result);
- CopyMemory(@AOutput[0], pKey, Result);
- end;
- function DecryptPID(var AOutput: array of Byte): Integer;
- begin
- Result := DecryptValues(_R1_PID, Length(_R1_PID), AOutput);
- end;
- function DecryptUserPin(var AOutput: array of Byte): Integer;
- begin
- Result := DecryptValues(_R1_UserPin, Length(_R1_UserPin), AOutput);
- end;
- procedure InnerCloseR1Dog;
- begin
- if _R1DogOpened then
- begin
- R1_Close(_R1DogHandle);
- end;
- end;
- procedure InnerOpenR1Dog;
- var
- I: Integer;
- iResult: Cardinal;
- iCount: DWORD;
- aPID: array [0..7] of Byte;
- aUserPin: array [0..16] of Byte;
- iTryCount: Byte;
- begin
- if _R1DogOpened then Exit;
- // 如果是插的彩虹锁,飞天锁驱动函数R1_Find没对iCount初始化,搞得循环2亿多次。现在先初始化iCount就可以了。
- iCount := 0;
- // 查找狗
- iResult := R1_Find(nil, @iCount);
- if iResult <> 0 then
- Exit;
- if iCount = 0 then
- Exit;
- // 解出PID
- if DecryptPID(aPID) = 0 then
- Exit;
- // 解出用户密码
- if DecryptUserPin(aUserPin) = 0 then
- Exit;
- // 不知为什么在win7 32位下,必须加一个0字符才能正确执行。可能跟C要求字符串以0字符结尾有关
- aUserPin[16] := 0;
- for I := 0 to iCount - 1 do
- begin
- // 获取句柄
- iResult := R1_Open(@_R1DogHandle, @aPID[0], I);
- if iResult <> 0 then
- Continue;
- // 验证
- iResult := R1_VerifyUserPin(_R1DogHandle, @aUserPin[0], @iTryCount);
- if iResult <> 0 then
- Continue;
- // 判断一下版本才决定是否正确的锁
- if CheckR1Edition(True) = CS_Success then
- begin
- _R1DogOpened := True;
- Break;
- end
- else
- InnerCloseR1Dog;
- end;
- end;
- const R1EncryptVer = 1;
- function SimpleR1Check: Integer;
- var
- iResult: Cardinal;
- aData: array [0..15] of Byte;
- iLength: WORD;
- begin
- Result := -1;
- InnerOpenR1Dog;
- if not _R1DogOpened then Exit;
- iResult := R1_Read(_R1DogHandle, 0, 3, @aData[0], @iLength, MEM_PRI);
- if (iResult = 0) and (aData[2] = R1EncryptVer) then
- Result := DT_FT_R1;
- end;
- function CheckR1Times(AIsOnOpen: Boolean): Integer;
- var
- iResult: Cardinal;
- aData: array [0..11] of Byte;
- iTimes, iRunTimes, iLength: Word;
- begin
- Result := CS_Error;
- if SimpleR1Check < 0 then
- Exit;
- // 允许次数
- iTimes := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$07-$08,为迷惑,取$03-$0E
- iResult := R1_Read(_R1DogHandle, $03, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- iTimes := aData[4] shl 8 + aData[5];
- if iTimes = 0 then
- Exit;
- if iTimes = $FFFF then
- begin
- Result := CS_Success;
- Exit;
- end;
- bAuthorized := False;
- // 实际次数
- iRunTimes := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$04-$05,为迷惑,取$02-$0D
- iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PUB);
- if iResult = 0 then
- iRunTimes := aData[2] shl 8 + aData[3];
-
- Activations := iRunTimes;
- if AIsOnOpen then
- begin
- if iRunTimes >= iTimes then
- Result := CS_NeedAuthorize
- else
- Result := CS_WantAuthorize;
- end
- else
- begin
- if iRunTimes > iTimes then
- Result := CS_NeedAuthorize
- else
- Result := CS_WantAuthorize;
- end;
- end;
- function CheckR1Hours: Integer;
- var
- iResult: Cardinal;
- aData: array [0..11] of Byte;
- iSeconds, iRunSeconds: Cardinal;
- iLength: Word;
- begin
- Result := CS_Error;
- if SimpleR1Check < 0 then
- Exit;
- // 允许时间
- iSeconds := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$03-$06,为迷惑,取$02-$0D
- iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- iSeconds := ((aData[1] shl 8 + aData[2]) shl 8 + aData[3]) shl 8 + aData[4];
- // iRunSeconds := ((aData[5] shl 8 + aData[6]) shl 8 + aData[7]) shl 8 + aData[8];
- if iSeconds = 0 then
- Exit;
- if iSeconds = $FFFFFFFF then
- begin
- Result := CS_Success;
- Exit;
- end;
- bAuthorized := False;
- // 实际运行时间
- iRunSeconds := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$00-$03,为迷惑,取$00-$0C
- iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PUB);
- if iResult = 0 then
- iRunSeconds := ((aData[0] shl 8 + aData[1]) shl 8 + aData[2]) shl 8 + aData[3];
- LastTime := iRunSeconds;
- if iRunSeconds > iSeconds then
- Result := CS_NeedAuthorize
- else
- Result := CS_WantAuthorize;
- end;
- function CheckR1LimitDate: Integer;
- var
- iResult: Cardinal;
- aData: array [0..11] of Byte;
- iType: Byte;
- iUserDate, iLimitDate: Cardinal;
- fDate, fCompileDate: TDateTime;
- iLength: Word;
- begin
- Result := CS_Error;
- if SimpleR1Check < 0 then
- Exit;
- // 加密类型是否时间限制狗
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$63,为迷惑,取$5B-$66
- iResult := R1_Read(_R1DogHandle, $5B, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult <> 0 then Exit;
- if aData[8] <> Ord(etDate) then
- begin
- Result := CS_Ignore;
- Exit;
- end;
- bAuthorized := False;
- // 允许日期
- iLimitDate := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$09-$0C,为迷惑,取$05-$10
- iResult := R1_Read(_R1DogHandle, $05, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- iLimitDate := ((aData[4] shl 8 + aData[5]) shl 8 + aData[6]) shl 8 + aData[7];
- // 运行日期
- iUserDate := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$06-$09,为迷惑,取$05-$10
- iResult := R1_Read(_R1DogHandle, $05, Length(aData), @aData[0], @iLength, MEM_PUB);
- if iResult = 0 then
- iUserDate := ((aData[1] shl 8 + aData[2]) shl 8 + aData[3]) shl 8 + aData[4];
- fDate := PHPWeb.SystemDateTime;
- fCompileDate := CompileDateTime;
- if fCompileDate > iLimitDate then
- begin
- Result := CS_EndDate;
- Exit;
- end;
- if fDate > iLimitDate then
- Result := CS_EndDate
- else if iLimitDate - fDate < 7 then
- Result := CS_CloseToLimitDate
- else
- Result := CS_Success;
- end;
- function CheckR1AdditionEdition: Integer;
- var
- iResult: Cardinal;
- aData: array [0..15] of Byte;
- iLength: Word;
- begin
- Result := CS_NoDog;
- if SimpleR1Check < 0 then
- Exit;
- // 附加版本限制
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$70-$72,为迷惑,取$70-$7F
- iResult := R1_Read(_R1DogHandle, $70, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- begin
- if aData[1] = $16 then
- Result := CS_Success
- else
- Result := CS_NeedUpdate;
- end;
- end;
- function CheckR1Edition(AOpening: Boolean): Integer;
- var
- iResult: Cardinal;
- aData: array [0..255] of Byte;
- iEdition: Byte;
- iLength: Word;
- I: Integer;
- begin
- Result := CS_NoDog;
- if (not AOpening) and (SimpleR1Check < 0) then
- Exit;
- // 附加版本限制
- iEdition := 0;
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$01,为迷惑,取$00-$FE
- iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- iEdition := aData[1]
- else
- Exit;
- if iEdition = 0 then
- Exit;
- DogEdition := iEdition;
- if CheckEncryptEdition(iEdition) then
- Result := CS_Success
- else
- Result := CS_DogTypeError;
- if Result = CS_Success then
- begin
- _DogEdition := iEdition;
- // 如果是固话清单限制版,则不退出,继续后面的检查
- {$IFNDEF _mEncrypt}
- if not iEdition in [eidLimitedFixBills] then
- Exit;
- {$ENDIF}
- end;
- // 读取附加版本ID
- ZeroMemory(@aData[0], Length(aData));
- // 实际是$80-$92,为迷惑,取$77-$175
- iResult := R1_Read(_R1DogHandle, $77, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult <> 0 then Exit;
- for I := Low(aData) + 9 to High(aData) do
- begin
- iEdition := aData[I];
- if iEdition = 0 then Break;
- if CheckEncryptEdition(iEdition) then
- begin
- Result := CS_Success;
- _DogEdition := iEdition;
- // 如果附加版本是固化清单限制版,则不跳出循环,以便检查是否还有固化清单完整版
- if iEdition = eidLimitedFixBills then
- Continue;
- // 如果是计量支付需要检测所有的功能模块,则在检测到所有功能模块可用前,不可跳出循环
- {$IFDEF _mEncrypt}
- if not (_bHasCompileEdition and _bHasMeasureEdition and _bHasPlanEdition) then
- Continue;
- {$ENDIF}
- Break;
- end;
- end;
- end;
- function CheckR1Data: Integer;
- var
- iResult: Cardinal;
- iCheckData, iOutputLength: Integer;
- pKey: Pointer;
- arrKey: array [0..15] of Byte;
- arrData: array [0..19] of Byte;
- I: Integer;
- bIsZero: Boolean;
- iLength: Word;
- begin
- Result := CS_NoDog;
- if SimpleR1Check < 0 then
- Exit;
- // HID
- ZeroMemory(@_R1_HID[0], Length(_R1_HID));
- iResult := R1_GetHID(_R1DogHandle, @_R1_HID[0]);
- if iResult <> 0 then Exit;
- strHaspID := '';
- // 注意此处与其他狗不同
- for I := 0 to Length(_R1_HID) - 1 do
- strHaspID := strHaspID + Char(_R1_HID[I]);
-
- Randomize;
- iCheckData := RandomRange(11000, 11050);
- case iCheckData of
- 11011..11020:
- begin
- Result := CS_Ignore;
- Exit;
- end;
- end;
- // 校验码
- ZeroMemory(@arrKey[0], Length(arrKey));
- ZeroMemory(@arrData[0], Length(arrData));
- // $10-$23
- iResult := R1_Read(_R1DogHandle, $10, Length(arrData), @arrData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- begin
- pKey := nil;
- try
- Decrypt_BlowFish(EncryptKey, @arrData[0], 20, pKey, iOutputLength);
- CopyMemory(@arrKey[0], pKey, iOutputLength);
- finally
- if Assigned(pKey) then
- FreeMem(pKey);
- end;
- end;
- for I := 0 to Length(_R1_HID) - 1 do
- begin
- if _R1_HID[I] <> arrKey[I] then
- begin
- Result := CS_VerifyError;
- Exit;
- Break;
- end;
- end;
- Result := CS_Success;
- end;
- function GetR1ReportOprNum(AOpr: string): Integer;
- const
- OprStr = '[,-,*,^,:=,/,p,<,<=,>=,>,+,<>,=,or,!=,and,f';
- var
- iResult: Cardinal;
- OprStrs: TStringList;
- StrIndex: Integer;
- OprNum: Byte;
- aData: array [0..19] of Byte;
- iLength: Word;
- begin
- Result := -1;
- StrIndex := GetReportOprList.IndexOf(AOpr);
- if StrIndex > -1 then
- begin
- Result := Integer(GetReportOprList.Objects[StrIndex]);
- end
- else
- begin
- OprStrs := TStringList.Create;
- try
- OprStrs.CommaText := OprStr;
- iResult := R1_Read(_R1DogHandle, $30, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- begin
- StrIndex := OprStrs.IndexOf(AOpr);
- if StrIndex >= 0 then
- begin
- OprNum := aData[StrIndex];
- GetReportOprList.AddObject(AOpr, Pointer(OprNum));
- Result := OprNum;
- end;
- end;
- finally
- OprStrs.Free;
- end;
- end;
- end;
- function GetR1ReportFuncNum(AOpr: string): Integer;
- const
- FuncStr = 'sql,treechapterinsert,getindex,addnull,shrink,copy,'+
- 'sorttreechapter,joindata,chapterinsert,'+
- 'refcopy,count,refcopyex1';
- var
- iResult: Cardinal;
- FuncStrs: TStringList;
- StrIndex: Integer;
- OprNum: Byte;
- aData: array [0..19] of Byte;
- iLength: Word;
- begin
- Result := -1;
- StrIndex := GetReportFuncList.IndexOf(AOpr);
- if StrIndex > -1 then
- begin
- Result := Integer(GetReportFuncList.Objects[StrIndex]);
- end
- else
- begin
- FuncStrs := TStringList.Create;
- try
- FuncStrs.CommaText := FuncStr;
- iResult := R1_Read(_R1DogHandle, $50, Length(aData), @aData[0], @iLength, MEM_PRI);
- if iResult = 0 then
- begin
- StrIndex := FuncStrs.IndexOf(AOpr);
- if StrIndex >= 0 then
- begin
- OprNum := aData[StrIndex];
- GetReportFuncList.AddObject(AOpr, Pointer(900 + OprNum));
- Result := 900 + OprNum;
- end;
- end;
- finally
- FuncStrs.Free;
- end;
- end;
- end;
- function OpenR1Dog: Integer;
- var
- iResult: Cardinal;
- aData: array [0..11] of Byte;
- iTimes, iLength: Word;
- begin
- Result := CS_Error;
- // 打开狗则运行次数立刻+1
- // 实际是$04-$05为迷惑,取$02-$0D
- iResult := R1_Read(_R1DogHandle, $02, Length(aData), @aData[0], @iLength, MEM_PUB);
- if iResult = 0 then
- begin
- iTimes := aData[2] shl 8 + aData[3];
- end
- else
- Exit;
- iTimes := iTimes + 1;
- ZeroMemory(@aData[0], Length(aData));
- aData[0] := iTimes shr 8;
- aData[1] := iTimes and $00FF;
- iResult := R1_Write(_R1DogHandle, $04, 2, @aData[0], @iLength, MEM_PUB);
- if iResult <> 0 then
- Exit;
- Result := CS_Success;
- end;
- procedure SaveR1Dog;
- var
- iResult: Cardinal;
- aData: array [0..11] of Byte;
- aSecData: array [0..3] of Byte;
- iLastTime, iRunSeconds: LongWord;
- iBytesReturned: Cardinal;
- iLength: Word;
- begin
- RunTime := GetTickCount div 1000;
- if RunTime < StartTime then
- begin
- iLastTime := High(LongWord) div 1000 + RunTime - StartTime;
- end
- else
- iLastTime := RunTime - StartTime;
- // 实际是$00-$03,为迷惑,取$00-$0B
- iResult := R1_Read(_R1DogHandle, $00, Length(aData), @aData[0], @iLength, MEM_PUB);
- if iResult = 0 then
- begin
- iRunSeconds := ((aData[$08] shl 8 + aData[$09]) shl 8 + aData[$0A]) shl 8 + aData[$0B];
- iLastTime := iLastTime + iRunSeconds;
- aSecData[$00] := iLastTime shr 24;
- aSecData[$01] := (iLastTime shr 16) and $00FF;
- aSecData[$02] := (iLastTime and $0000FFFF) shr 8;
- aSecData[$03] := iLastTime and $000000FF;
- iResult := R1_Write(_R1DogHandle, $00, 4, @aSecData[0], @iLength, MEM_PUB);
- end;
- end;
- function _R1UserAuthorize30(AAuthorize: array of Byte; ALength: Word): Boolean;
- var
- iResult: DWORD;
- arrUpdateFile: array [0..9999] of Byte;
- begin
- Result := False;
- if _R1DogOpened then
- begin
- CopyMemory(@arrUpdateFile[0], @AAuthorize[0], ALength);
- iResult := R1_Update(_R1DogHandle, @arrUpdateFile[0], ALength);
- if iResult <> 0 then
- raise Exception.Create(Format('Can not update, error = %d', [iResult]));
- Result := True;
- bAuthorized := True;
- end;
- end;
- function R1UserAuthorize(AAuthorize: array of Byte): Boolean;
- var
- pHead: PAuthFileHead;
- Key: array [0..9999] of Byte;
- iPos: Integer;
- begin
- Result := False;
- iPos := SizeOf(TAuthFileHead);
- New(pHead);
- try
- CopyMemory(pHead, @AAuthorize[0], iPos);
- if SameText(pHead^.FileInfo, SAuthFileInfo) and (pHead^.Version = SAuthFileVer) then
- begin
- CopyMemory(@Key[0], @AAuthorize[iPos], pHead^.Length);
- Result := _R1UserAuthorize30(Key, pHead^.Length);
- end;
- finally
- Dispose(pHead);
- end;
- end;
- function R1UserUpdateLock(AUpdateData: array of Byte): Boolean;
- var
- pHead: PAuthFileHead;
- Key: array [0..9999] of Byte;
- iPos: Integer;
- begin
- Result := False;
- iPos := SizeOf(TAuthFileHead);
- New(pHead);
- try
- CopyMemory(pHead, @AUpdateData[0], iPos);
- if SameText(pHead^.FileInfo, SUpdateFileInfo) and (pHead^.Version = SUpdateFileVer) then
- begin
- CopyMemory(@Key[0], @AUpdateData[iPos], pHead^.Length);
- Result := _R1UserAuthorize30(Key, pHead^.Length);
- end;
- finally
- Dispose(pHead);
- end;
- end;
- initialization
- finalization
- InnerCloseR1Dog;
- end.
|