(2021-12-09 05:40:46 отредактировано crash)

Скорость шифрования Guradant ключом AES128

Добрый день! Скажите пожалуйста,
1. Какой метод лучше использовать для шифрования файлов ?
(например файл размером 2МБ шифруется Guradant ключом AES128 примерно 5мин ....
Как-то многовато :( )
Инициализация компонента

begin
// FGrdDongle мой компонент на Delphi переписанный код из компонента на C++
// grddongle.h аналогичен C++  CGrdDongle

  FGrdDongle := TGrdDongle.Create(GrdFMR_Local);
  FGrdDongle.OnErrorHandling := ErrorHandling; ловим ошибки и выводим их в лог программы

  FGrdDongle.PublicCode := $abcdef- CryptPU;  //$abcdef ваше подогнанное значение под реальный
  FGrdDongle.PrivateReadCode :=  $abcdef - CryptRD; //$abcdef ваше  значение под реальный
  FGrdDongle.PrivateWriteCode := 0 - CryptWR;
  FGrdDongle.PrivateMasterCode := 0 - CryptMS;
  FGrdDongle.Open;

  FGrdDongle.Login(DWORD(-1));

  if FGrdDongle.Check <> 0 then
    halt(0);
end;

procedure TMainForm.CryptFile(FileName: TFileName);
var
  MemoryMap: TMemoryStream;
  FMemory: Pointer;
  nret, dw, lenVectorAES: DWORD;
  szInitVectorAES, szDataPsw: string;
  abyGrdAES_Context: array [0 .. GrdAES_CONTEXT_SIZE] of byte;
  szDataStr: string;
  DataLen: DWORD;
  st: string;
begin
  lenVectorAES := 16;
  szInitVectorAES := '__IV_____IV___';

  MemoryMap := TMemoryStream.Create;
  try
    MemoryMap.LoadFromFile(FileName);
    // Implement data encoding by AES128 hardware algorithm
    nRet := FGrdDongle.CryptEx(GrdAN_AES128,
      MemoryMap.Size, MemoryMap.Memory, GrdAM_OFB or GrdAM_Encode, lenVectorAES,
      @szInitVectorAES[1]);

// наверное нужна другая опция для работы с файлами ? а не GrdAM_OFB?


    {
   szInitVectorAES := '__IV_____IV___'; // Init Vector for AES algo
    // Implement data decoding by AES128 hardware algorithm
    nRet := FGrdDongle.CryptEx(GrdAN_AES128,  MemoryMap.Size, MemoryMap.Memory,
      GrdAM_OFB or GrdAM_Decode, lenVectorAES, @szInitVectorAES[1]);
 }
    MemoryMap.WriteBuffer(MemoryMap.Memory^, MemoryMap.Size);
    // Context for multiple buffer encryption
    // MemoryMap.wWriteBuffer(MemoryMap.Memory^, MemoryMap.Size);
    MemoryMap.SaveToFile(ChangeFileExt(FileName, '.crc'));
  finally
    MemoryMap.Free;
  end;
end;

2. По опциям шифрования

{- Guardant Stealth API Algorithm use Method }
{- bit 0-5 block chaining mode }
    GrdAM_ECB=           0;   { Electronic Code Book } 
    GrdAM_CBC=           1;   { Cipher Block Chaining }
    GrdAM_CFB=           2;   { Cipher Feed Back } 
    GrdAM_OFB=           3;   { Output Feed Back }

Распишите подробнее для чего каждая
Cipher Feed Back это я так понимаю строка которая кодируется кодером (шифруется) обратно возвращается по этому -же адресу строки? правильно я понимаю?
Какая опция нужна для кодирования файлов например, а не строки?

3. Как вызвать генератор случайный чисел Guradant ключа? и получить это число?
Что то в примерах не совсем понял где это...

Re: Скорость шифрования Guradant ключом AES128

Если кому нужен компонент (dll-wrapper'a ) написан на основе компонента С++

unit GRDDongle;

{
  free
}
interface

{$IFDEF FPC}

{ Free Pascal }
uses
  SysUtils, GRDDelphi in 'GrdDelphi.pas';
{$ELSE}
{$IF CompilerVersion < 23}

{ Delphi 6 to Delphi XE }
uses
  SysUtils, Windows, Classes, GRDDelphi in 'GrdDelphi.pas';
{$ELSE}

{ Delphi XE2 and above }
uses
  System.SysUtils, Winapi.Windows, System.Classes, GRDDelphi;
// in 'GrdDelphi.pas';
{$IFEND}
{$ENDIF}
{$DEFINE DEBUGGRD_INFO}
// DEBUGGRD_INFO вывод сообщений

const
  CryptPU: DWORD = $8566783; { Random value for access codes security }
  CryptRD: DWORD = $17D49C84; { Random value for access codes security }
  CryptWR: DWORD = $9843DE24; { Random value for access codes security }
  CryptMS: DWORD = $47832845; { Random value for access codes security }
  MAJ_VER = 1; // Major version nr.
  MIN_VER = 0; // Minor version nr.
  REL_VER = 0; // Release nr.
  BLD_VER = 1; // Build nr.

type

  TGRDDongle = class;
  TErrorHandling = procedure(Sender: TObject;
    StatusStr, StatusMessageStr: string; StatusCode, ErrCode: Integer)
    of object;

  TGRDDongle = class(TObject)
  private
    m_hMutex: HANDLE; // next ver
    m_ErrorHandling: TErrorHandling;
    function DoStartup: Integer;
    procedure DoCleanup;
    function GetVersionNr: Integer;
    function GetVersion: string;
  protected
{$IFDEF WIN32}
    m_lGrdDongleClassCounter: Integer;
{$ELSE}
    m_lGrdDongleClassCounter: DWORD;
{$ENDIF WIN32} // _WIN32
    m_bGrdDongleStartup: Boolean;
    m_abyGrdContainer: array [0 .. GrdContainerSize] of Byte;
    m_hGrd: HANDLE;
    m_dwRemoteMode: DWORD;
    { Local and/or remote (GrdSMF_Local + GrdSMF_Remote) }
    // parameters for call SetFindMode()
    m_dwFlags: DWORD; // Combination of GrdFM_XXXXX flags
    m_dwProg: DWORD;
    m_dwID: DWORD;
    m_dwSN: DWORD;
    m_dwVer: DWORD;
    m_dwMask: DWORD;
    m_dwType: DWORD;
    m_dwModels: DWORD; // Possible dongle model bits. See GrdFMM_GSX definition
    m_dwInterfaces: DWORD;
    // Possible dongle interface bits. See GrdFMI_XXX definition
    m_dwStartupFlags: DWORD; // See GrdRCS_XXXXX definition
    m_dwDongleModel: DWORD; // dongle model after login
    m_szNetworkClientIniPath: PChar;
    m_useNotificationApi: Boolean;
    // procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;

    m_GrdDC_NVK: DWORD; // = //  public code }
    m_GrdDC_RDO: DWORD; // = //  private read code }
    m_GrdDC_PRF: DWORD; // = //  private write code }
    m_GrdDC_MST: DWORD; // = //  private master code }

    Function GetInfo(dwInfoCode: DWORD;
      // Code of requested information. See GrdGIX_XXXXX
      pInfoData: pointer; // Pointer to buffer for return data
      dwInfoSize: DWORD): Integer; overload; // Number of bytes for returning

    Function Read(dwAddr, // Starting address in dongle memory to be read
      dwLng: DWORD; // Length of data to be read
      pData: pointer): Integer; // Buffer for data to be read

    Function Write(dwAddr,
      // Starting address in dongle memory to be written
      dwLng: DWORD; // Length of data to be written
      const pData: pointer): Integer; // Buffer for data to be written

  published
    constructor Create(
      // parameters for call GrdStartup() & GrdSetFindMode
      dwRemoteMode: DWORD = GrdFMR_Local + GrdFMR_Remote;
      // parameters for call SetFindMode()
      dwFlags: DWORD = 0; // Combination of GrdFM_XXXXX flags
      dwProg: DWORD = 0; dwID: DWORD = 0; dwSN: DWORD = 0; dwVer: DWORD = 0;
      dwMask: DWORD = 0; dwType: DWORD = 0; dwModels: DWORD = GrdFMM_ALL;
      // Possible dongle model bits. See GrdFMM_GSX definition
      dwInterfaces: DWORD = GrdFMI_ALL;
      // Possible dongle interface bits. See GrdFMI_XXX definition
      dwStartupFlags: DWORD = GrdRCS_UserDefined; // See GrdRCS_XXXXX definition
      const szNetworkClientIniPath: string = '';
      useNotificationApi: Boolean = false);
    { Must be encoded }
    destructor Destroy; override;
    function HandleError(nRet: Integer): Integer;
    procedure PrintResult(nStatusStr: String; nErrorCode: Integer);

    Function Open(
      // parameters for call SetWorkMode()
      dwFlagsWork: DWORD = GrdWM_UAM; // combination of GrdWM_XXX flags
      dwFlagsMode: DWORD = GrdWMFM_DriverAuto): Integer;
    // combination of GrdWMFM_XXX flags}
    Function Unlock: Integer;
    Function Lock(dwTimeoutWaitForUnlock: DWORD = 10000;
      // Max GrdAPI unlock waiting time. -1 == infinity. 0 == no waiting
      dwTimeoutAutoUnlock: DWORD = 10000;
      // Max dongle locking time in ms.  -1 == infinity. 0 == 10000 ms (10 sec)
      dwMode: DWORD = GrdLM_Nothing): Integer;

    function Check: Integer;
    Function DecGP: Integer;
    Function Seek(dwSeek: DWORD): Integer;

    Function GetLastError: Integer;
    Function FormatErrMessage(nLanguage: Integer = GrdLng_RUS): string;
    Function FormatErrMessagenErrorCode(nErrorCode: Integer;
      // Guardant error code
      nLanguage: Integer = GrdLng_RUS): string; // Guardant language ID

    Function GetInfo(dwInfoCode: DWORD;
      // Code of requested information. See GrdGIX_XXXXX
      var ptData: DWORD): Integer; overload;
    // Pointer to variable to be returned

    Function GetDongleModel: DWORD;
    Function SetAccessCodes(dwPublic, // Must be already specified
      dwPrivateRD: DWORD; // Must be already specified
      dwPrivateWR: DWORD = 0; // == 0 if not needed
      dwPrivateMST: DWORD = 0): Integer; // == 0 if not needed
    Function SetWorkMode(dwFlagsWork: DWORD = GrdWM_UAM;
      // combination of GrdWM_XXX flags
      dwFlagsMode: DWORD = GrdWMFM_DriverAuto): Integer;
    // combination of GrdWMFM_XXX flags
    Function SetFindMode(dwRemoteMode: DWORD = GrdFMR_Local + GrdFMR_Remote;
      // Local and/or remote (GrdFMR_Local + GrdFMR_Remote)
      dwFlags: DWORD = 0; // Combination of GrdFM_XXXXX flags
      dwProg: DWORD = 0; dwID: DWORD = 0; dwSN: DWORD = 0; dwVer: DWORD = 0;
      dwMask: DWORD = 0; dwType: DWORD = 0; dwModels: DWORD = GrdFMM_ALL;
      // Possible dongle model bits. See GrdFMM_GSX definition
      dwInterfaces: DWORD = GrdFMI_ALL): Integer;
    Function GetFindMode(dwRemoteMode,
      // Local and/or remote (GrdFMR_Local + GrdFMR_Remote)
      dwFlags, // Combination of GrdFM_XXXXX flags
      dwProg, dwID, dwSN, dwVer, dwMask, dwType, dwModels,
      // Possible dongle model bits. See GrdFMM_GSX definition
      dwInterfaces: DWORD): Integer;

    Function Find(dwMode: DWORD; // GrdF_First or GrdF_Next
      var pdwID: DWORD; // Pointer to variable for return dongle ID
      var FindInfo: TGrdFindInfo): Integer;
    // Place for return dongle info or NULL for ignore it in other languages

    Function Login(dwModuleLMS: DWORD = DWORD(-1);
      // module number or -1 if License Management System functions are not used
      dwLoginFlags: DWORD = GrdLM_PerStation): Integer;
    // Login flags (GrdLLM_PerStation or GrdLLM_PerHandle)
    Function Logout: Integer;
    Function Protect(dwWrProt,
      // address of first BYTES which can by write in SAM
      dwRdProt, // address of first BYTES which can by read  in SAM
      dwNumFunc: DWORD;
      // Number of hardware-implemented algorithms in the dongle
      dwTableLMS: DWORD = 0;
      // For Net II: SAM address of the first byte of LMS Table in 2-byte words; For Net III: number of protected item that contains LMS Table
      dwGlobalFlags: DWORD = 0): Integer; // Reserved, must be 0
    Function Transform(dwAlgoNum, dwLng: DWORD; pData: pointer;
      dwMethod: DWORD = 0;
      // GrdAM_ECB + GrdAM_Encrypt,// if Stealth I or Fidus it must be 0. Otherwise - combination of GrdAM_XXX flags
      pIV: pointer = nil): Integer;
    Function TransformEx(dwAlgoNum, dwLng: DWORD; pData: pointer;
      dwMethod: DWORD = 0;
      // GrdAM_ECB + GrdAM_Encrypt,// if Stealth I or Fidus it must be 0. Otherwise - combination of GrdAM_XXX flags
      dwIVLng: DWORD = 0; pIV: pointer = nil): Integer;

    Function Crypt(dwAlgo,
      // Number of hardware- or software-implemented algorithm
      dwDataLng: DWORD; // Data length
      pData: pointer; // Data for Encryption/Decryption
      dwMethod: DWORD = 0;
      // Encrypt/Decrypt, First/Next/Last, block chaining modes (ECB/OFB/...)
      pIV: pointer = nil; // Initialization Vector
      const pKeyBuf: pointer = nil;
      // Encryption/decryption secret key for software-implemented algorithm (nil if not used)
      pContext: pointer = nil): Integer;

    Function CryptEx(dwAlgo,
      // Number of hardware- or software-implemented algorithm
      dwDataLng: DWORD; // Data length
      pData: pointer; // Data for Encryption/Decryption
      dwMethod: DWORD = 0;
      // Encrypt/Decrypt, First/Next/Last, block chaining modes (ECB/OFB/...)
      dwIVLng: DWORD = 0; pIV: pointer = nil; // Initialization Vector
      const pKeyBuf: pointer = nil;
      // Encryption/decryption secret key for software-implemented algorithm (nil if not used)
      pContext: pointer = nil): Integer;

    Function Hash(dwSoftHash,
      // Number of hardware- or software-implemented algorithm
      dwDataLng: DWORD; // Data length
      const pData: pointer; // Data for hash calculation
      dwMethod: DWORD; // GrdSC_First/GrdSC_Next/GrdSC_Last
      pDigest: pointer;
      // Pointer to memory allocated for hash on GrdSC_Last step
      const pKeyBuf: pointer = nil;
      // Hash calculation secret key for software-implemented algorithm (nil if not used)
      pContext: pointer = nil): Integer;

    // property VertScrollBar: TControlScrollBar read FVertScrollBar write SetVertScrollBar;
    Function HashEx(dwSoftHash,
      // Number of hardware- or software-implemented algorithm
      dwDataLng: DWORD; // Data length
      const pData: pointer; // Data for hash calculation
      dwMethod: DWORD; // GrdSC_First/GrdSC_Next/GrdSC_Last
      dwDigestLng: DWORD; // Digest length
      pDigest: pointer;
      // Pointer to memory allocated for hash on GrdSC_Last step
      dwKeyBufLng: DWORD; // Not used, must be 0
      const pKeyBuf: pointer;
      // Hash calculation secret key for software-implemented algorithm (nil if not used)
      dwContextLng: DWORD; // Context length
      pContext: pointer): Integer;
    Function CRC(const pData: pointer; dwLng: DWORD;
      dwPrevCRC: DWORD = Grd_StartCRC): DWORD;

    Function PI_Activate(dwItemNum: DWORD;
      // Algorithm or Protected Item number to be activated
      dwActivatePsw: DWORD = 0): Integer;
    // Optional password. If not used, must be 0
    Function PI_Deactivate(dwItemNum: DWORD;
      // Algorithm or Protected Item number to be deactivated
      dwDeactivatePsw: DWORD = 0): Integer;
    // Optional password. If not used, must be 0
    Function PI_Read(dwItemNum,
      // Algorithm or Protected Item number to be read
      dwAddr, // Offset in Algorithm or Protected Item data
      dwLng: DWORD; // Number of bytes for reading
      pData: pointer; // Pointer to buffer for read data
      dwReadPsw: DWORD = 0): Integer;
    // Optional password. If not used, must be 0

    Function PI_Update(dwItemNum,
      // Algorithm or Protected Item number to be updated
      dwAddr, // Offset in Algorithm or Protected Item data
      dwLng: DWORD; // Number of bytes for updating
      const pData: pointer; // Pointer to buffer with data to be written
      dwUpdatePsw: DWORD = 0; // Optional password. If not used, must be 0
      dwMethod: DWORD = GrdUM_MOV): Integer;
    Function TRU_SetKey(const pGSII64_Key128: pointer): Integer;
    // Unique
    Function TRU_GenerateQuestion(pQuestion: pointer;
      // Pointer to Question                  8 bytes (64 bit)
      pdwID, // Pointer to ID                        4 bytes
      pdwPublic: DWORD; // Pointer to Dongle Public Code        4 bytes
      pHash: pointer): Integer;
    Function TRU_GenerateQuestionTime(pQuestion: pointer;
      // Pointer to Question                  8 bytes (64 bit)
      pdwID, // Pointer to ID                        4 bytes
      pdwPublic, // Pointer to Dongle Public Code        4 bytes
      pqwDongleTime, // Pointer to Dongle Time (encrypted)   8 bytes
      dwDeadTimesSize, pqwDeadTimes, pdwDeadTimesNumbers: DWORD;
      pHash: pointer): Integer;
    Function TRU_DecryptQuestion(dwAlgoNum_GSII64,
      // Dongle GSII64 algorithm number with same key as in remote dongle
      dwAlgoNum_HashS3: DWORD;
      // Dongle HASH algorithm number with same key as in remote dongle
      pQuestion: pointer;
      // Pointer to Question                  8 bytes (64 bit)
      dwID, // ID                                   4 bytes
      dwPublic: DWORD; // Public Code                          4 bytes
      const pHash: pointer): Integer;

    Function TRU_DecryptQuestionTime(
      // GSII64 algorithm with the same key as in remote dongle
      dwAlgoNum_GSII64,
      // Dongle GSII64 algorithm number with same key as in remote dongle
      dwAlgoNum_HashS3: DWORD;
      // Dongle HASH64 algorithm number with same key as in remote dongle
      pQuestion: pointer;
      // Pointer to Question                  8 bytes (64 bit)
      dwID, // ID                                   4 bytes
      dwPublic: DWORD; // Public Code                          4 bytes
      pqwDongleTime, // Pointer to Dongle Time (encrypted)   8 bytes
      pqwDeadTimes: QWORD; dwDeadTimesNumbers: DWORD;
      const pHash: pointer): Integer;
    Function TRU_SetAnswerProperties(dwTRU_Flags,
      // Use Init & Protect or not
      dwReserved, // Reserved, must be 0
      dwWrProt, // remote GrdProtect parameters, SAM addres of the first byte available for writing in bytes
      dwRdProt, // remote GrdProtect parameters, SAM addres of the first byte available for reading in bytes
      dwNumFunc: DWORD;
      // remote GrdProtect parameters, Number of hardware-implemented algorithms in the dongle including all protected items and LMS table of Net III
      dwTableLMS: DWORD = 0;
      // remote GrdProtect parameters, Net II: SAM address of the first byte of LMS Table in 2-byte words;
      // Net III: number of protected item that contains LMS Table
      dwGlobalFlags: DWORD = 0): Integer;
    Function TRU_EncryptAnswer(dwAddr,
      // Starting address for writing in dongle
      dwLng: DWORD; // Size of data to be written
      const pData: pointer; // Buffer for data to be written
      const pQuestion: pointer;
      // Pointer to decrypted Question            8 bytes (64 bit)
      dwAlgoNum_GSII64,
      // Dongle GSII64 algorithm number with the same key as in remote dongle
      dwAlgoNum_HashS3: DWORD;
      // Dongle HASH algorithm number with the same key as in remote dongle
      pAnswer: pointer; // Pointer to the buffer for Answer data
      pdwAnswerSize: DWORD): Integer;
    Function TRU_ApplyAnswer(const pAnswer: pointer;
      // Answer data update buffer prepared and encrypted by GrdTRU_EncryptAnswer
      dwAnswerSize: DWORD): Integer;
    Function Sign(dwAlgoNum,
      // Number of hardware implemented ECC algorithm
      dwDataLng: DWORD; // Data for sign length (20 bytes for ECC160)
      const pData: pointer; // Data for sign
      dwSignResultLng: DWORD; // ECC sign length (40 bytes for ECC160)
      pSignResult: pointer): Integer;
    Function VerifySign(dwAlgoType,
      // Type of asymmetric cryptoalgorithm. See GrdVSC_XXXXX definition
      dwPublicKeyLng: DWORD; // Public ECC key length
      const pPublicKey: pointer; // Public ECC key
      dwDataLng: DWORD; // Data for sign length (20 bytes for ECC160)
      const pData: pointer; // Data for sign
      dwSignLng: DWORD; // ECC sign length (40 bytes for ECC160)
      const pSign: pointer): Integer;
    Function SetTime(const pGrdSystemTime: TGrdSystemTime): Integer;
    Function GetTime(pGrdSystemTime: TGrdSystemTime): Integer;
    Function PI_GetTimeLimit(dwItemNum: DWORD;
      // Algorithm or Protected Item number
      pGrdSystemTime: TGrdSystemTime): Integer;
    Function PI_GetCounter(dwItemNum: DWORD;
      // Algorithm or Protected Item number
      pdwCounter: DWORD): Integer;
    Function CodeGetInfo(dwAlgoName: DWORD;
      // Algorithm numerical name to be loaded
      grdCodeInfo: TGrdCodeInfo): Integer;
    Function CodeLoad(dwAlgoName,
      // Algorithm numerical name to be loaded
      dwFileSize: DWORD; // Buffer size for GCEXE-file
      const pFileBuf: pointer): Integer;
    Function CodeRun(dwAlgoName: DWORD;
      // Algorithm numerical name to be loaded
      dwP1, // Parameter (subfunction code) for loadable code
      pdwRet, // result := code of loadable code
      dwDataFromDongleLng: DWORD;
      // The amount of data to be received from the dongle
      pDataFromDongle: pointer;
      // Pointer to a buffer for data to be received from the dongle
      dwDataToDongleLng: DWORD; // The amount of data to be sent to the dongle
      const pDataToDongle: pointer): Integer;
    Function SetDriverMode(dwMode: DWORD): Integer;
    Function InitializeNotificationAPI: Integer;
    Function RegisterDongleNotification(pCallBack
      : TGrdDongleNotifyCallBack): Integer;
    Function UnRegisterDongleNotification(): Integer;

  public
    Function ReadVariable(dwAddr: DWORD;
      // Starting address in dongle memory to be read
      ptData: pointer): Integer; overload; // Pointer to variable to be read
    Function ReadBlock(dwLng: DWORD; // Length of data to be read
      pData: pointer): Integer; // Buffer for data to be read
    Function ReadVariable(ptData: pointer): Integer; overload;
    Function WriteVariable(dwAddr: DWORD;
      // Starting address in dongle memory to be written
      const ptData: pointer): Integer; overload;
    // Pointer to variable to be written
    Function WriteBlock(dwLng: DWORD; // Length of data to be written
      const pData: pointer): Integer; // Buffer for data to be written
    Function WriteVariable(const ptData: pointer): Integer; overload;
    Function Init: Integer;
    property PublicCode: DWORD read m_GrdDC_NVK write m_GrdDC_NVK;
    // default GrdDC_DEMONVK;
    property PrivateReadCode: DWORD read m_GrdDC_RDO write m_GrdDC_RDO;
    // default GrdDC_DEMORDO;
    property PrivateWriteCode: DWORD read m_GrdDC_PRF write m_GrdDC_PRF;
    // default GrdDC_DEMOPRF;
    property PrivateMasterCode: DWORD read m_GrdDC_MST write m_GrdDC_MST;
    // default GrdDC_DEMOMST;
    property OnErrorHandling: TErrorHandling read m_ErrorHandling
      write m_ErrorHandling;
    property Version: string read GetVersion;
  end;

implementation

{ TGrdDongle }
/// Constructor
constructor TGRDDongle.Create(
  // parameters for call GrdStartup() & GrdSetFindMode
  dwRemoteMode: DWORD = GrdFMR_Local + GrdFMR_Remote;
  // parameters for call SetFindMode()
  dwFlags: DWORD = 0; // Combination of GrdFM_XXXXX flags
  dwProg: DWORD = 0; dwID: DWORD = 0; dwSN: DWORD = 0; dwVer: DWORD = 0;
  dwMask: DWORD = 0; dwType: DWORD = 0; dwModels: DWORD = GrdFMM_ALL;
  // Possible dongle model bits. See GrdFMM_GSX definition
  dwInterfaces: DWORD = GrdFMI_ALL;
  // Possible dongle interface bits. See GrdFMI_XXX definition
  dwStartupFlags: DWORD = GrdRCS_UserDefined; // See GrdRCS_XXXXX definition
  const szNetworkClientIniPath: string = '';
  useNotificationApi: Boolean = false);
var
  nRet: Integer;
begin
  m_lGrdDongleClassCounter := 0;
  m_dwRemoteMode := dwRemoteMode;
  m_dwFlags := dwFlags; // Combination of GrdFM_XXXXX flags
  m_dwProg := dwProg;
  m_dwID := dwID;
  m_dwSN := dwSN;
  m_dwVer := dwVer;
  m_dwMask := dwMask;
  m_dwType := dwType;
  m_dwModels := dwModels;
  // Possible dongle model bits. See GrdFMM_GSX definition
  m_dwInterfaces := dwInterfaces;
  // Possible dongle interface bits. See GrdFMI_XXX definition
  m_dwStartupFlags := dwStartupFlags; // See GrdRCS_XXXXX definition
  m_dwDongleModel := DWORD(-1);
  // dongle model after login
  m_szNetworkClientIniPath := PChar(szNetworkClientIniPath);
  m_useNotificationApi := useNotificationApi;
  inc(m_lGrdDongleClassCounter);
  // Open(dwPublic, dwPrivRD, 0, 0);
  HandleError(nRet);
  inherited Create;
end;

// destructor
destructor TGRDDongle.Destroy;
var
  nRet: Integer;
begin
  if m_hGrd <> nil then
  begin
    nRet := GrdCloseHandle(m_hGrd);
    if (nRet <> GrdE_OK) Then
      m_hGrd := nil;
  end;
  DoCleanup;
  inherited Destroy;
end;

function TGRDDongle.GetVersion: string;
var
  vn: Integer;
begin
  vn := GetVersionNr;
  Result := inttostr(Hi(HiWord(vn))) + '.' + inttostr(Lo(HiWord(vn))) + '.' +
    inttostr(Hi(LoWord(vn))) + '.' + inttostr(Lo(LoWord(vn)));
end;

function TGRDDongle.GetVersionNr: Integer;
begin
  Result := makelong(MakeWord(BLD_VER, REL_VER), MakeWord(MIN_VER, MAJ_VER));
end;

{ --------------------------------------------------------------------------- }
procedure TGRDDongle.PrintResult(nStatusStr: String; nErrorCode: Integer);
begin
  // Translate error code to text message
  if Assigned(OnErrorHandling) then
    OnErrorHandling(Self, Format(nStatusStr, []),
      FormatErrMessagenErrorCode(nErrorCode), 0, nErrorCode);
end;

{ --------------------------------------------------------------------------- }

function TGRDDongle.HandleError(nRet: Integer): Integer;

begin
  if (nRet <> GrdE_OK) Then
  begin
    if (m_hGrd <> nil) Then
    // Perform some cleanup operations if hGrd handle exists
    begin
      // Close hGrd handle, log out from dongle/server, free allocated memory
      PrintResult('- Closing handle: ', nRet);
      nRet := GrdCloseHandle(m_hGrd);
      PrintResult('', nRet);
    end;
    // Deinitialize this copy of GrdAPI. GrdCleanup() must be called after last GrdAPI call before program termination
    PrintResult('-- Deinitializing this copy of GrdAPI: ', nRet);
    nRet := GrdCleanup();
    PrintResult('', nRet);
  end
  else
    PrintResult('+ Result: ', nRet);

  Result := nRet;
end;

/// Create class object. It call GrdStartup, GrdCreateHandle, GrdSetAccessCodes, GrdSetWorkMode, GrdSetFindMode
/// and must by call after constructor and before any first other member function calls
Function TGRDDongle.Open(dwFlagsWork: DWORD = GrdWM_UAM;
  // combination of GrdWM_XXX flags
  dwFlagsMode: DWORD = GrdWMFM_DriverAuto): Integer;
// combination of GrdWMFM_XXX flags

var
  nRet: Integer;
begin
  nRet := DoStartup();
  if (nRet <> GrdE_OK) then
  begin
    HandleError(nRet);
    exit(nRet);
  end;

  if (m_hGrd = nil) then
  begin
    // Create Grd protected object
    m_hGrd := GrdCreateHandle(@m_abyGrdContainer, GrdCHM_MultiThread, nil);
    if (m_hGrd = nil) then
      Result := GrdE_Internal;
    HandleError(nRet);
  end;

  // Store dongle codes in Guardant protected container
  nRet := GrdSetAccessCodes(m_hGrd, m_GrdDC_NVK + CryptPU,
    m_GrdDC_RDO + CryptRD, m_GrdDC_PRF + CryptWR, m_GrdDC_MST + CryptMS);
  if (nRet <> GrdE_OK) then
  begin
    HandleError(nRet);
    exit(nRet);
  end;

  // Set System Address Mode (SAM) as default mode
  nRet := GrdSetWorkMode(m_hGrd, dwFlagsWork, dwFlagsMode);
  if (nRet <> GrdE_OK) then
  begin
    HandleError(nRet);
    exit(nRet);
  end;

  // Set dongle search parameters
  Result := GrdSetFindMode(m_hGrd, m_dwRemoteMode, m_dwFlags, m_dwProg, m_dwID,
    m_dwSN, m_dwVer, m_dwMask, m_dwType, m_dwModels, m_dwInterfaces);
  HandleError(Result);
end;

/// Get last error information from protected container with specified handle
/// The last error code is maintained on a per-handle basis
/// Multiple handles do not overwrite each other's last-error code
Function TGRDDongle.GetLastError: Integer;
begin
  Result := GrdGetLastError(m_hGrd, nil);
end;

/// Convert error code to text message string
Function TGRDDongle.FormatErrMessagenErrorCode(nErrorCode: Integer;
  // Guardant error code
  nLanguage: Integer = GrdLng_RUS): string; // Guardant language ID
var
  szBuf: array [0 .. 1023] of ansichar; { buffer for error string }
begin
  GrdFormatMessage(m_hGrd, nErrorCode, nLanguage, @szBuf[0],
    sizeof(szBuf), nil);
  Result := szBuf;
  // MessageBox(0,@szBuf, 'Ошибка',0);
end;

/// Convert last error code (stored in handle) to text message string
Function TGRDDongle.FormatErrMessage(nLanguage: Integer = GrdLng_RUS): string;
// Guardant language ID
var
  szBuf: array [0 .. 1023] of ansichar; { buffer for error string }
begin
  GrdFormatMessage(m_hGrd, 0, nLanguage, @szBuf[0], sizeof(szBuf), nil);
  Result := szBuf;
end;

/// Get requested information
Function TGRDDongle.GetInfo(dwInfoCode: DWORD;
  // Code of requested information. See GrdGIX_XXXXX
  pInfoData: pointer; // Pointer to buffer for return data
  dwInfoSize: DWORD): Integer; // Number of bytes for returning
begin
  Result := GrdGetInfo(m_hGrd, dwInfoCode, pInfoData, dwInfoSize);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('GetInfo', Result);
{$ENDIF}
end;
/// template for get requested information of different types
// template<class Type>

Function TGRDDongle.GetInfo(dwInfoCode: DWORD;
  // Code of requested information. See GrdGIX_XXXXX
  var ptData: DWORD): Integer; // Pointer to variable to be returned
begin
  Result := GetInfo(dwInfoCode, @ptData, sizeof(ptData));
{$IFDEF DEBUGGRD_INFO}
  PrintResult('GetInfo', Result);
{$ENDIF}
end;

Function TGRDDongle.GetDongleModel: DWORD;
begin
  if (m_dwDongleModel <> $FFFFFFFF) then
    exit(m_dwDongleModel);

  if (GetInfo(GrdGIL_Model, @m_dwDongleModel, sizeof(m_dwDongleModel)) <>
    GrdE_OK) then
    exit($FFFFFFFF);

  case m_dwDongleModel of

    GrdDM_FidusUSB, GrdDM_FidusLPT:
      m_dwDongleModel := GrdFMM_Fidus;
    GrdDM_Stealth1LPT, GrdDM_Stealth1USB:
      m_dwDongleModel := GrdFMM_Stealth1;
    GrdDM_Stealth2LPT, GrdDM_Stealth2USB:
      m_dwDongleModel := GrdFMM_Stealth2;
    GrdDM_Stealth3USB:
      m_dwDongleModel := GrdFMM_Stealth3;
    GrdDM_SignUSB:
      m_dwDongleModel := GrdFMM_SignUSB;
    GrdDM_Soft:
      m_dwDongleModel := GrdFMM_Soft;
    GrdDM_CodeUSB:
      m_dwDongleModel := GrdFMM_CodeUSB;
  else
    m_dwDongleModel := $FFFFFFFF;
  end;
  Result := m_dwDongleModel;
end;

/// Store dongle codes in Guardant protected container
Function TGRDDongle.SetAccessCodes(dwPublic, // Must be already specified
  dwPrivateRD: DWORD; // Must be already specified
  dwPrivateWR: DWORD = 0; // == 0 if not needed
  dwPrivateMST: DWORD = 0): Integer; // == 0 if not needed
begin
  Result := GrdSetAccessCodes(m_hGrd, dwPublic, dwPrivateRD, dwPrivateWR,
    dwPrivateMST);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('SetAccessCodes', Result);
{$ENDIF}
end;

/// Set dongle working mode to Guardant protected container
Function TGRDDongle.SetWorkMode(dwFlagsWork: DWORD = GrdWM_UAM;
  // combination of GrdWM_XXX flags
  dwFlagsMode: DWORD = GrdWMFM_DriverAuto): Integer;
// combination of GrdWMFM_XXX flags
begin
  Result := GrdSetWorkMode(m_hGrd, dwFlagsWork, dwFlagsMode);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('SetWorkMode', Result);
{$ENDIF}
end;

/// Set dongle search conditions and operation modes to Guardant protected container
Function TGRDDongle.SetFindMode(dwRemoteMode: DWORD = GrdFMR_Local +
  GrdFMR_Remote; // Local and/or remote (GrdFMR_Local + GrdFMR_Remote)
  dwFlags: DWORD = 0; // Combination of GrdFM_XXXXX flags
  dwProg: DWORD = 0; dwID: DWORD = 0; dwSN: DWORD = 0; dwVer: DWORD = 0;
  dwMask: DWORD = 0; dwType: DWORD = 0; dwModels: DWORD = GrdFMM_ALL;
  // Possible dongle model bits. See GrdFMM_GSX definition
  dwInterfaces: DWORD = GrdFMI_ALL): Integer;
// Possible dongle interface bits. See GrdFMI_XXX definition
begin
  Result := GrdSetFindMode(m_hGrd, dwRemoteMode, dwFlags, dwProg, dwID, dwSN,
    dwVer, dwMask, dwType, dwModels, dwInterfaces);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('SetFindMode', Result);
{$ENDIF}
end;

Function TGRDDongle.GetFindMode(dwRemoteMode,
  // Local and/or remote (GrdFMR_Local + GrdFMR_Remote)
  dwFlags, // Combination of GrdFM_XXXXX flags
  dwProg, dwID, dwSN, dwVer, dwMask, dwType, dwModels,
  // Possible dongle model bits. See GrdFMM_GSX definition
  dwInterfaces: DWORD): Integer;
// Possible dongle interface bits. See GrdFMI_XXX definition
var
  nRet: Integer;
begin
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Remote, @dwRemoteMode,
    sizeof(dwRemoteMode));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Flags, @dwFlags, sizeof(dwFlags));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Model, @dwModels, sizeof(dwModels));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Interface, @dwInterfaces,
    sizeof(dwInterfaces));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Ver, @dwVer, sizeof(dwVer));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Prog, @dwProg, sizeof(dwProg));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_SN, @dwSN, sizeof(dwSN));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_ID, @dwID, sizeof(dwID));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  nRet := GrdGetInfo(m_hGrd, GrdGIF_Type, @dwType, sizeof(dwType));
  if (GrdE_OK <> nRet) then
    exit(nRet);;
  Result := GrdGetInfo(m_hGrd, GrdGIF_Mask, @dwMask, sizeof(dwMask));

{$IFDEF DEBUGGRD_INFO}
  PrintResult('GetFindMode', Result);
{$ENDIF}
end;

/// Obtain the ID and other dongle info of the first or next dongle found
Function TGRDDongle.Find(dwMode: DWORD; // GrdF_First or GrdF_Next
  var pdwID: DWORD; // Pointer to variable for return dongle ID
  var FindInfo: TGrdFindInfo): Integer;
// Place for return dongle info or NULL for ignore it in other languages
begin
  Result := GrdFind(m_hGrd, dwMode, @pdwID, @FindInfo);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Find', Result);
{$ENDIF}
end;

/// Login to Guardant dongle
Function TGRDDongle.Login(dwModuleLMS: DWORD = DWORD(-1);
  // module number or -1 if License Management System functions are not used
  dwLoginFlags: DWORD = GrdLM_PerStation): Integer;
// Login flags (GrdLLM_PerStation or GrdLLM_PerHandle)
begin
  Result := GrdLogin(m_hGrd, dwModuleLMS, dwLoginFlags);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Login', Result);
{$ENDIF}
end;

/// Log out from Guardant dongle
Function TGRDDongle.Logout: Integer;
begin
  Result := GrdLogout(m_hGrd, 0);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Logout', Result);
{$ENDIF}
end;

/// startup stuff
Function TGRDDongle.DoStartup: Integer;
var
  // lock:CGrdMutex;
  nRet: Integer;
begin
  if not m_bGrdDongleStartup then
  begin
    nRet := GrdStartupEx(m_dwRemoteMode, m_szNetworkClientIniPath,
      m_dwStartupFlags);
    if (nRet <> GrdE_OK) then
    begin
      HandleError(nRet);
      exit(nRet);
    end;

{$IFDEF WIN32}
    if m_useNotificationApi then
    begin
      nRet := GrdInitializeNotificationAPI;
      if (nRet <> GrdE_OK) then
      begin
        GrdCleanup();
        // result := nRet;
        HandleError(nRet);
        exit(nRet);
      end;
    end;
{$ENDIF WIN32} // _WIN32
    m_bGrdDongleStartup := true;
  end;
  Result := GrdE_OK;
end;

/// cleanup stuff
procedure TGRDDongle.DoCleanup;
begin
  // CGrdMutex lock;
  dec(m_lGrdDongleClassCounter);
  if (m_lGrdDongleClassCounter = 0) and (m_bGrdDongleStartup) then
  begin

{$IFDEF WIN32}
    if m_useNotificationApi then
      GrdUnInitializeNotificationAPI();
{$ENDIF WIN32} // _WIN32
    GrdCleanup;
    m_bGrdDongleStartup := false;
  end;
end;

/// Increment lock counter of specified dongle
Function TGRDDongle.Lock(dwTimeoutWaitForUnlock: DWORD = 10000;
  // Max GrdAPI unlock waiting time. -1 == infinity. 0 == no waiting
  dwTimeoutAutoUnlock: DWORD = 10000;
  // Max dongle locking time in ms.  -1 == infinity. 0 == 10000 ms (10 sec)
  dwMode: DWORD = GrdLM_Nothing): Integer;
// in default works like critical section
begin
  Result := GrdLock(m_hGrd, dwTimeoutWaitForUnlock,
    dwTimeoutAutoUnlock, dwMode);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Lock', Result);
{$ENDIF}
end;

/// Unlock specified dongle
Function TGRDDongle.Unlock: Integer;
begin
  Result := GrdUnlock(m_hGrd);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Unlock', Result);
{$ENDIF}
end;

/// Check for dongle availability
Function TGRDDongle.Check: Integer;
begin
  Result := GrdCheck(m_hGrd);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Check', Result);
{$ENDIF}
end;

/// Check for dongle availability and decrement GP executions counter
/// Requires Private write code to be specified in SetAccessCodes
Function TGRDDongle.DecGP: Integer;
begin
  Result := GrdDecGP(m_hGrd);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('DecGP', Result);
{$ENDIF}
end;

/// GrdDongle fSeek analog
/// Moves the dongle memory pointer (if any) associated with handle to a new location
Function TGRDDongle.Seek(dwSeek: DWORD): Integer;
begin
  Result := GrdSeek(m_hGrd, dwSeek);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Seek', Result);
{$ENDIF}
end;

/// Read a block of bytes from the dongle's memory
Function TGRDDongle.Read(dwAddr, // Starting address in dongle memory to be read
  dwLng: DWORD; // Length of data to be read
  pData: pointer): Integer; // Buffer for data to be read
begin
  Result := GrdRead(m_hGrd, dwAddr, dwLng, pData, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Read', Result);
{$ENDIF}
end;

/// Read a variable from the dongle's memory
Function TGRDDongle.ReadVariable(dwAddr: DWORD;
  // Starting address in dongle memory to be read
  ptData: pointer): Integer; // Pointer to variable to be read
begin
  Result := Read(dwAddr, sizeof(ptData), ptData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('ReadVariable', Result);
{$ENDIF}
end;

/// Read a block of bytes from the dongle's memory
Function TGRDDongle.ReadBlock(dwLng: DWORD; // Length of data to be read
  pData: pointer): Integer; // Buffer for data to be read
begin
  Result := Read(GrdSeekCur, dwLng, pData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('ReadBlock', Result);
{$ENDIF}
end;

/// Read a variable from the dongle's memory
Function TGRDDongle.ReadVariable(ptData: pointer): Integer;
// Pointer to variable to be read
begin
  Result := Read(GrdSeekCur, sizeof(ptData), ptData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('ReadVariable', Result);
{$ENDIF}
end;

/// Write a block of bytes into the dongle's memory
/// Requires Private write code to be specified in SetAccessCodes
Function TGRDDongle.Write(dwAddr,
  // Starting address in dongle memory to be written
  dwLng: DWORD; // Length of data to be written
  const pData: pointer): Integer; // Buffer for data to be written
begin
  Result := GrdWrite(m_hGrd, dwAddr, dwLng, pData, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Write', Result);
{$ENDIF}
end;

/// write a variable into the dongle's memory
Function TGRDDongle.WriteVariable(dwAddr: DWORD;
  // Starting address in dongle memory to be written
  const ptData: pointer): Integer; // Pointer to variable to be written
begin
  Result := Write(dwAddr, sizeof(ptData), ptData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('WriteVariable', Result);
{$ENDIF}
end;

/// Write a block of bytes into the dongle's memory
/// Requires Private write code to be specified in SetAccessCodes
Function TGRDDongle.WriteBlock(dwLng: DWORD; // Length of data to be written
  const pData: pointer): Integer; // Buffer for data to be written
begin
  Result := Write(GrdSeekCur, dwLng, pData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('WriteBlock', Result);
{$ENDIF}
end;

/// write a variable into the dongle's memory

Function TGRDDongle.WriteVariable(const ptData: pointer): Integer;
// Pointer to variable to be written
begin
  Result := Write(GrdSeekCur, sizeof(ptData), ptData);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('WriteVariable', Result);
{$ENDIF}
end;

/// Initialize the dongle's memory
/// Requires Private master code to be specified in SetAccessCodes
Function TGRDDongle.Init: Integer;
begin
  Result := GrdInit(m_hGrd);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Init', Result);
{$ENDIF}
end;

/// Implement locks / Specify the number of hardware algorithms
/// and LMS table address
/// Requires Private master code to be specified in SetAccessCodes
Function TGRDDongle.Protect(dwWrProt,
  // address of first BYTES which can by write in SAM
  dwRdProt, // address of first BYTES which can by read  in SAM
  dwNumFunc: DWORD; // Number of hardware-implemented algorithms in the dongle
  dwTableLMS: DWORD = 0;
  // For Net II: SAM address of the first byte of LMS Table in 2-byte words; For Net III: number of protected item that contains LMS Table
  dwGlobalFlags: DWORD = 0): Integer; // Reserved, must be 0
begin
  Result := GrdProtect(m_hGrd, dwWrProt, dwRdProt, dwNumFunc, dwTableLMS,
    dwGlobalFlags, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Protect', Result);
{$ENDIF}
end;

/// --- Cryptographic functions

/// Transform a block of bytes using dongle's hardware-implemented algorithm (including GSII64)
Function TGRDDongle.Transform(dwAlgoNum, dwLng: DWORD; pData: pointer;
  dwMethod: DWORD = 0;
  // GrdAM_ECB + GrdAM_Encrypt,// if Stealth I or Fidus it must be 0. Otherwise - combination of GrdAM_XXX flags
  pIV: pointer = nil): Integer;
// if Stealth I or Fidus it must be NULL. Otherwise - 8-bytes initialization vector
begin
  Result := GrdTransform(m_hGrd, dwAlgoNum, dwLng, pData, dwMethod, pIV);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Transform', Result);
{$ENDIF}
end;

/// Transform a block of bytes using dongle's hardware-implemented algorithm (including GSII64)
Function TGRDDongle.TransformEx(dwAlgoNum, dwLng: DWORD; pData: pointer;
  dwMethod: DWORD = 0;
  // GrdAM_ECB + GrdAM_Encrypt,// if Stealth I or Fidus it must be 0. Otherwise - combination of GrdAM_XXX flags
  dwIVLng: DWORD = 0; pIV: pointer = nil): Integer;
// if Stealth I or Fidus it must be NULL. Otherwise - n-bytes initialization vector
begin
  Result := GrdTransformEx(m_hGrd, dwAlgoNum, dwLng, pData, dwMethod, dwIVLng,
    pIV, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('TransformEx', Result);
{$ENDIF}
end;

/// Encrypt/decrypt a block of bytes using encryption algorithm
Function TGRDDongle.Crypt(dwAlgo,
  // Number of hardware- or software-implemented algorithm
  dwDataLng: DWORD; // Data length
  pData: pointer; // Data for Encryption/Decryption
  dwMethod: DWORD = 0;
  // Encrypt/Decrypt, First/Next/Last, block chaining modes (ECB/OFB/...)
  pIV: pointer = nil; // Initialization Vector
  const pKeyBuf: pointer = nil;
  // Encryption/decryption secret key for software-implemented algorithm (nil if not used)
  pContext: pointer = nil): Integer;
// Context for multiple-buffer encryption. Must be corresponded GrdXXXXXX_CONTEXT_SIZE bytes size
begin
  Result := GrdCrypt(m_hGrd, dwAlgo, dwDataLng, pData, dwMethod, pIV, pKeyBuf,
    pContext);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Crypt', Result);
{$ENDIF}
end;

/// Encrypt/decrypt a block of bytes using encryption algorithm
Function TGRDDongle.CryptEx(dwAlgo,
  // Number of hardware- or software-implemented algorithm
  dwDataLng: DWORD; // Data length
  pData: pointer; // Data for Encryption/Decryption
  dwMethod: DWORD = 0;
  // Encrypt/Decrypt, First/Next/Last, block chaining modes (ECB/OFB/...)
  dwIVLng: DWORD = 0; pIV: pointer = nil; // Initialization Vector
  const pKeyBuf: pointer = nil;
  // Encryption/decryption secret key for software-implemented algorithm (nil if not used)
  pContext: pointer = nil): Integer;
// Context for multiple-buffer encryption. Must be corresponded GrdXXXXXX_CONTEXT_SIZE bytes size
begin
  Result := GrdCryptEx(m_hGrd, dwAlgo, dwDataLng, pData, dwMethod, dwIVLng, pIV,
    pKeyBuf, pContext, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('CryptEx', Result);
{$ENDIF}
end;

/// Hash calculation of a block of bytes
Function TGRDDongle.Hash(dwSoftHash,
  // Number of hardware- or software-implemented algorithm
  dwDataLng: DWORD; // Data length
  const pData: pointer; // Data for hash calculation
  dwMethod: DWORD; // GrdSC_First/GrdSC_Next/GrdSC_Last
  pDigest: pointer; // Pointer to memory allocated for hash on GrdSC_Last step
  const pKeyBuf: pointer = nil;
  // Hash calculation secret key for software-implemented algorithm (nil if not used)
  pContext: pointer = nil): Integer;
// Context for multiple buffer calculation. Must be corresponded GrdXXXXXX_CONTEXT_SIZE bytes size
begin
  Result := GrdHash(m_hGrd, dwSoftHash, dwDataLng, pData, dwMethod, pDigest,
    pKeyBuf, pContext);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('Hash', Result);
{$ENDIF}
end;

/// Hash calculation of a block of bytes
Function TGRDDongle.HashEx(dwSoftHash,
  // Number of hardware- or software-implemented algorithm
  dwDataLng: DWORD; // Data length
  const pData: pointer; // Data for hash calculation
  dwMethod: DWORD; // GrdSC_First/GrdSC_Next/GrdSC_Last
  dwDigestLng: DWORD; // Digest length
  pDigest: pointer; // Pointer to memory allocated for hash on GrdSC_Last step
  dwKeyBufLng: DWORD; // Not used, must be 0
  const pKeyBuf: pointer;
  // Hash calculation secret key for software-implemented algorithm (nil if not used)
  dwContextLng: DWORD; // Context length
  pContext: pointer): Integer;
// Context for multiple buffer calculation. Must be corresponded GrdXXXXXX_CONTEXT_SIZE bytes size
begin
  Result := GrdHashEx(m_hGrd, dwSoftHash, dwDataLng, pData, dwMethod,
    dwDigestLng, pDigest, dwKeyBufLng, pKeyBuf, dwContextLng, pContext, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('HashEx', Result);
{$ENDIF}
end;

/// Calculate 32-bit CRC of a memory block
Function TGRDDongle.CRC(const pData: pointer; dwLng: DWORD;
  dwPrevCRC: DWORD = Grd_StartCRC): DWORD;
begin
  Result := GrdCRC(pData, dwLng, dwPrevCRC);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('CRC', Result);
{$ENDIF}
end;

/// --- Protected Item functions

/// Activate dongle Algorithm or Protected Item
Function TGRDDongle.PI_Activate(dwItemNum: DWORD;
  // Algorithm or Protected Item number to be activated
  dwActivatePsw: DWORD = 0): Integer;
// Optional password. If not used, must be 0
begin
  Result := GrdPI_Activate(m_hGrd, dwItemNum, dwActivatePsw);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_Activate', Result);
{$ENDIF}
end;

/// Deactivate dongle Algorithm or Protected Item
Function TGRDDongle.PI_Deactivate(dwItemNum: DWORD;
  // Algorithm or Protected Item number to be deactivated
  dwDeactivatePsw: DWORD = 0): Integer;
// Optional password. If not used, must be 0
begin
  Result := GrdPI_Deactivate(m_hGrd, dwItemNum, dwDeactivatePsw);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_Deactivate', Result);
{$ENDIF}
end;

/// Read data from dongle Protected Item
Function TGRDDongle.PI_Read(dwItemNum,
  // Algorithm or Protected Item number to be read
  dwAddr, // Offset in Algorithm or Protected Item data
  dwLng: DWORD; // Number of bytes for reading
  pData: pointer; // Pointer to buffer for read data
  dwReadPsw: DWORD = 0): Integer; // Optional password. If not used, must be 0
begin
  Result := GrdPI_Read(m_hGrd, dwItemNum, dwAddr, dwLng, pData, dwReadPsw, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_Read', Result);
{$ENDIF}
end;

/// Update data in dongle Protected Item
Function TGRDDongle.PI_Update(dwItemNum,
  // Algorithm or Protected Item number to be updated
  dwAddr, // Offset in Algorithm or Protected Item data
  dwLng: DWORD; // Number of bytes for updating
  const pData: pointer; // Pointer to buffer with data to be written
  dwUpdatePsw: DWORD = 0; // Optional password. If not used, must be 0
  dwMethod: DWORD = GrdUM_MOV): Integer;
// Update method. See GrdUM_XXX definitions
begin
  Result := GrdPI_Update(m_hGrd, dwItemNum, dwAddr, dwLng, pData, dwUpdatePsw,
    dwMethod, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_Update', Result);
{$ENDIF}
end;

/// --- Guardant Trusted Remote Update API

/// Write secret GSII64 remote update key for Guardant Secured Remote Update to the dongle
/// Requires Private master code to be specified in SetAccessCodes
Function TGRDDongle.TRU_SetKey(const pGSII64_Key128: pointer): Integer;
// Unique Trusted Remote Update GSII64 128-bit secret key
begin
  Result := GrdTRU_SetKey(m_hGrd, pGSII64_Key128);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_SetKey', Result);
{$ENDIF}
end;

/// Generate encrypted question and initialize remote update procedure
Function TGRDDongle.TRU_GenerateQuestion(pQuestion: pointer;
  // Pointer to Question                  8 bytes (64 bit)
  pdwID, // Pointer to ID                        4 bytes
  pdwPublic: DWORD; // Pointer to Dongle Public Code        4 bytes
  pHash: pointer): Integer; // Pointer to Hash of previous 16 bytes 8 bytes
begin
  Result := GrdTRU_GenerateQuestion(m_hGrd, pQuestion, @pdwID,
    @pdwPublic, pHash);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_GenerateQuestion', Result);
{$ENDIF}
end;

/// Generate encrypted question and initialize remote update procedure
Function TGRDDongle.TRU_GenerateQuestionTime(pQuestion: pointer;
  // Pointer to Question                  8 bytes (64 bit)
  pdwID, // Pointer to ID                        4 bytes
  pdwPublic, // Pointer to Dongle Public Code        4 bytes
  pqwDongleTime, // Pointer to Dongle Time (encrypted)   8 bytes
  dwDeadTimesSize, pqwDeadTimes, pdwDeadTimesNumbers: DWORD; pHash: pointer)
  : Integer; // Pointer to Hash of previous data
begin
  Result := GrdTRU_GenerateQuestionTime(m_hGrd, pQuestion, @pdwID, @pdwPublic,
    @pqwDongleTime, dwDeadTimesSize, @pqwDeadTimes, @pdwDeadTimesNumbers,
    pHash, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_GenerateQuestionTime', Result);
{$ENDIF}
end;

/// Decrypt and validate question
Function TGRDDongle.TRU_DecryptQuestion(dwAlgoNum_GSII64,
  // Dongle GSII64 algorithm number with same key as in remote dongle
  dwAlgoNum_HashS3: DWORD;
  // Dongle HASH algorithm number with same key as in remote dongle
  pQuestion: pointer; // Pointer to Question                  8 bytes (64 bit)
  dwID, // ID                                   4 bytes
  dwPublic: DWORD; // Public Code                          4 bytes
  const pHash: pointer): Integer;
// Pointer to Hash of previous 16 bytes 8 bytes
begin
  Result := GrdTRU_DecryptQuestion(m_hGrd, dwAlgoNum_GSII64, dwAlgoNum_HashS3,
    pQuestion, dwID, dwPublic, pHash);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_DecryptQuestion', Result);
{$ENDIF}
end;

/// Decrypt and validate question
Function TGRDDongle.TRU_DecryptQuestionTime(
  // GSII64 algorithm with the same key as in remote dongle
  dwAlgoNum_GSII64,
  // Dongle GSII64 algorithm number with same key as in remote dongle
  dwAlgoNum_HashS3: DWORD;
  // Dongle HASH64 algorithm number with same key as in remote dongle
  pQuestion: pointer; // Pointer to Question                  8 bytes (64 bit)
  dwID, // ID                                   4 bytes
  dwPublic: DWORD; // Public Code                          4 bytes
  pqwDongleTime, // Pointer to Dongle Time (encrypted)   8 bytes
  pqwDeadTimes: QWORD; dwDeadTimesNumbers: DWORD; const pHash: pointer)
  : Integer;
// Pointer to Hash of previous 16 bytes 8 bytes
begin
  Result := GrdTRU_DecryptQuestionTime(m_hGrd, dwAlgoNum_GSII64,
    dwAlgoNum_HashS3, pQuestion, dwID, dwPublic, @pqwDongleTime, @pqwDeadTimes,
    dwDeadTimesNumbers, pHash);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_DecryptQuestionTime', Result);
{$ENDIF}
end;

/// Set Init & Protect parameters for Trusted Remote Update
/// This function must be called after GrdTRU_DecryptQuestion and before GrdTRU_EncryptAnswer functions
/// only if Init & Protect operations will be executed during remote update (call GrdTRU_ApplyAnswer) procedure on remote PC
Function TGRDDongle.TRU_SetAnswerProperties(dwTRU_Flags,
  // Use Init & Protect or not
  dwReserved, // Reserved, must be 0
  dwWrProt, // remote GrdProtect parameters, SAM addres of the first byte available for writing in bytes
  dwRdProt, // remote GrdProtect parameters, SAM addres of the first byte available for reading in bytes
  dwNumFunc: DWORD;
  // remote GrdProtect parameters, Number of hardware-implemented algorithms in the dongle including all protected items and LMS table of Net III
  dwTableLMS: DWORD = 0;
  // remote GrdProtect parameters, Net II: SAM address of the first byte of LMS Table in 2-byte words;
  // Net III: number of protected item that contains LMS Table
  dwGlobalFlags: DWORD = 0): Integer;
// remote GrdProtect parameters, Reserved, must be 0
begin
  Result := GrdTRU_SetAnswerProperties(m_hGrd, dwTRU_Flags, dwReserved,
    dwWrProt, dwRdProt, dwNumFunc, dwTableLMS, dwGlobalFlags, nil);

{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_SetAnswerProperties', Result);
{$ENDIF}
end;

/// Prepare data for Trusted Remote Update
Function TGRDDongle.TRU_EncryptAnswer(dwAddr,
  // Starting address for writing in dongle
  dwLng: DWORD; // Size of data to be written
  const pData: pointer; // Buffer for data to be written
  const pQuestion: pointer;
  // Pointer to decrypted Question            8 bytes (64 bit)
  dwAlgoNum_GSII64,
  // Dongle GSII64 algorithm number with the same key as in remote dongle
  dwAlgoNum_HashS3: DWORD;
  // Dongle HASH algorithm number with the same key as in remote dongle
  pAnswer: pointer; // Pointer to the buffer for Answer data
  pdwAnswerSize: DWORD): Integer;
// IN: Maximum buffer size for Answer data, OUT: Size of pAnswer buffer
begin
  Result := GrdTRU_EncryptAnswer(m_hGrd, dwAddr, dwLng, pData, pQuestion,
    dwAlgoNum_GSII64, dwAlgoNum_HashS3, pAnswer, @pdwAnswerSize);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_EncryptAnswer', Result);
{$ENDIF}
end;

/// Write data from secured buffer received via remote update procedure
Function TGRDDongle.TRU_ApplyAnswer(const pAnswer: pointer;
  // Answer data update buffer prepared and encrypted by GrdTRU_EncryptAnswer
  dwAnswerSize: DWORD): Integer; // Size of pAnswer buffer
begin
  Result := GrdTRU_ApplyAnswer(m_hGrd, pAnswer, dwAnswerSize);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('TRU_ApplyAnswer', Result);
{$ENDIF}
end;

/// Digitally sign a block of bytes by using dongle hardware implemented ECC algorithm
Function TGRDDongle.Sign(dwAlgoNum,
  // Number of hardware implemented ECC algorithm
  dwDataLng: DWORD; // Data for sign length (20 bytes for ECC160)
  const pData: pointer; // Data for sign
  dwSignResultLng: DWORD; // ECC sign length (40 bytes for ECC160)
  pSignResult: pointer): Integer; // ECC sign
begin
  Result := GrdSign(m_hGrd, dwAlgoNum, dwDataLng, pData, dwSignResultLng,
    pSignResult, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('Sign', Result);
{$ENDIF}
end;

/// ECC algorithm digest verifying. Full software implemented
Function TGRDDongle.VerifySign(dwAlgoType,
  // Type of asymmetric cryptoalgorithm. See GrdVSC_XXXXX definition
  dwPublicKeyLng: DWORD; // Public ECC key length
  const pPublicKey: pointer; // Public ECC key
  dwDataLng: DWORD; // Data for sign length (20 bytes for ECC160)
  const pData: pointer; // Data for sign
  dwSignLng: DWORD; // ECC sign length (40 bytes for ECC160)
  const pSign: pointer): Integer; // ECC sign
begin
  Result := GrdVerifySign(m_hGrd, dwAlgoType, dwPublicKeyLng, pPublicKey,
    dwDataLng, pData, dwSignLng, pSign, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('VerifySign', Result);
{$ENDIF}
end;

/// Set dongle system time
Function TGRDDongle.SetTime(const pGrdSystemTime: TGrdSystemTime): Integer;
// Pointer to TGrdSystemTime
begin
  Result := GrdSetTime(m_hGrd, @pGrdSystemTime, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('SetTime', Result);
{$ENDIF}
end;

/// Get dongle system time
Function TGRDDongle.GetTime(pGrdSystemTime: TGrdSystemTime): Integer;
// Pointer to TGrdSystemTime
begin
  Result := GrdGetTime(m_hGrd, @pGrdSystemTime, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('GetTime', Result);
{$ENDIF}
end;

/// Get time limit for specified item
Function TGRDDongle.PI_GetTimeLimit(dwItemNum: DWORD;
  // Algorithm or Protected Item number
  pGrdSystemTime: TGrdSystemTime): Integer; // Pointer to TGrdSystemTime
begin
  Result := GrdPI_GetTimeLimit(m_hGrd, dwItemNum, @pGrdSystemTime, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_GetTimeLimit', Result);
{$ENDIF}
end;

/// Get counter for specified item
Function TGRDDongle.PI_GetCounter(dwItemNum: DWORD;
  // Algorithm or Protected Item number
  pdwCounter: DWORD): Integer; // Pointer to counter value
begin
  Result := GrdPI_GetCounter(m_hGrd, dwItemNum, @pdwCounter, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('PI_GetCounter', Result);
{$ENDIF}
end;

/// Get information from user-defined loadable code descriptor
Function TGRDDongle.CodeGetInfo(dwAlgoName: DWORD;
  // Algorithm numerical name to be loaded
  grdCodeInfo: TGrdCodeInfo): Integer;
begin
  Result := GrdCodeGetInfo(m_hGrd, dwAlgoName, sizeof(TGrdCodeInfo),
    @grdCodeInfo, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('CodeGetInfo', Result);
{$ENDIF}
end;

/// Load GCEXE file to the dongle
Function TGRDDongle.CodeLoad(dwAlgoName,
  // Algorithm numerical name to be loaded
  dwFileSize: DWORD; // Buffer size for GCEXE-file
  const pFileBuf: pointer): Integer; // Pointer to the buffer for GCEXE-file
begin
  Result := GrdCodeLoad(m_hGrd, dwAlgoName, dwFileSize, pFileBuf, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('CodeLoad', Result);
{$ENDIF}
end;

/// Run user-defined loadable code
Function TGRDDongle.CodeRun(dwAlgoName: DWORD;
  // Algorithm numerical name to be loaded
  dwP1, // Parameter (subfunction code) for loadable code
  pdwRet, // result := code of loadable code
  dwDataFromDongleLng: DWORD;
  // The amount of data to be received from the dongle
  pDataFromDongle: pointer;
  // Pointer to a buffer for data to be received from the dongle
  dwDataToDongleLng: DWORD; // The amount of data to be sent to the dongle
  const pDataToDongle: pointer): Integer;
// Pointer to a buffer for data to be sent to the dongle
begin
  Result := GrdCodeRun(m_hGrd, dwAlgoName, dwP1, @pdwRet, dwDataFromDongleLng,
    pDataFromDongle, dwDataToDongleLng, pDataToDongle, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('CodeRun', Result);
{$ENDIF}
end;

/// Switching driver type of USB-dongle
Function TGRDDongle.SetDriverMode(dwMode: DWORD): Integer;
// New Guardant dongle USB driver mode. See GrdDM_XXX definitions
begin
  Result := GrdSetDriverMode(m_hGrd, dwMode, nil);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('SetDriverMode', Result);
{$ENDIF}
end;

// manual InitializeNotificationAPI
Function TGRDDongle.InitializeNotificationAPI: Integer;
begin
  m_useNotificationApi := true;
  Result := GrdInitializeNotificationAPI;
{$IFDEF DEBUGGRD_INFO}
  PrintResult('InitializeNotificationAPI', Result);
{$ENDIF}
end;

/// Register dongle notification for specified handle
Function TGRDDongle.RegisterDongleNotification
  (pCallBack: TGrdDongleNotifyCallBack): Integer;
// Pointer to Dongle Notification CallBack routine
begin
  if (m_useNotificationApi) then
    Result := GrdRegisterDongleNotification(m_hGrd, pCallBack);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('RegisterDongleNotification', Result);
{$ENDIF};

  Result := GrdE_OK;
end;

/// Unregister dongle notification for specified handle
Function TGRDDongle.UnRegisterDongleNotification(): Integer;
begin
  if (m_useNotificationApi) then
    Result := GrdUnRegisterDongleNotification(m_hGrd);
{$IFDEF DEBUGGRD_INFO}
  PrintResult('UnRegisterDongleNotification', Result);
{$ENDIF};
  Result := GrdE_OK;
end;

end.

Re: Скорость шифрования Guradant ключом AES128

1. Какой метод лучше использовать для шифрования файлов ?

Шифрование аппаратными алгоритмами действительно занимает много времени. Если требуется шифровать большие объемы данных, то лучше использовать программные алгоритмы. При этом секретный ключ такого алгоритма можно зашифровать с помощью аппаратного алгоритма ключа, или хранить в защищенной ячейке памяти. Также ключ шифрования можно вырабатывать, например, используя таблицу вопросов и ответов.

2. По опциям шифрования

Все опции подробно описаны на нашем портале документации.

3. Как вызвать генератор случайный чисел Guradant ключа? и получить это число?

Для этого необходимо использовать функцию GrdTransform.

Re: Скорость шифрования Guradant ключом AES128

Спасибо! все понял!