| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 | unit mR1Encrypt;interfaceuses  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;implementationuses  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;initializationfinalization  InnerCloseR1Dog;end.
 |