CryptProtectData в Delphi на 64-битной платформе - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь использовать CryptProtectData в Delphi XE7 в Windows 10. Я использую ответ Дэвида в качестве основы.

Код работает при компиляции на 32-битной платформе, но яне могу заставить его работать на 64-битной платформе (соответствует нормально, но у меня есть ошибки времени выполнения).

Вот код (я немного изменил код Дэвида, чтобы использовать параметр pOptionalEntropy):

unit Unit1;

interface

uses
  System.SysUtils, Winapi.Windows;

const
  CRYPTPROTECT_LOCAL_MACHINE = 4;

type
  TLargeByteArray = array [0 .. Pred(MaxInt)] of byte;
  PLargeByteArray = ^TLargeByteArray;

  _CRYPTOAPI_BLOB = record
    cbData: DWORD;
    pbData: PByte;
  end;

  DATA_BLOB = _CRYPTOAPI_BLOB;
  PDATA_BLOB = ^DATA_BLOB;

type
  _CRYPTPROTECT_PROMPTSTRUCT = record
    cbSize: DWORD;
    dwPromptFlags: DWORD;
    hwndApp: HWND;
    szPrompt: PWideChar;
  end;

  CRYPTPROTECT_PROMPTSTRUCT = _CRYPTPROTECT_PROMPTSTRUCT;
  PCRYPTPROTECT_PROMPTSTRUCT = ^CRYPTPROTECT_PROMPTSTRUCT;

function CryptProtectData(pDataIn: PDATA_BLOB;
  szDataDescr: PWideChar; pOptionalEntropy: PDATA_BLOB;
  pReserved: Pointer; pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD;
  pDataOut: PDATA_BLOB): BOOL; stdcall; external 'Crypt32.dll';

function CryptUnprotectData(pDataIn: PDATA_BLOB; ppszDataDescr: PPWideChar;
  pOptionalEntropy: PDATA_BLOB; pReserved: Pointer;
  pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD;
  pDataOut: PDATA_BLOB): BOOL; stdcall; external 'Crypt32.dll';

function EncryptData(const AStr: String; const AdditionalEntropy: string): string;


implementation


procedure FreeDataBlob(var Data: DATA_BLOB);
begin
  if Assigned(Data.pbData) then
    LocalFree(HLOCAL(Data.pbData));
  FillChar(Data, SizeOf(DATA_BLOB), 0);
end;

function GetDataBlobText(Data: DATA_BLOB): string;
begin
  SetString(Result, PChar(Data.pbData), Data.cbData div SizeOf(Char));
end;

function SetDataBlobText(const Text: string; var Data: DATA_BLOB): Boolean;
begin
  FillChar(Data, SizeOf(DATA_BLOB), 0);
  if Length(Text) > 0 then
  begin
    Data.cbData := SizeOf(Char) * Length(Text);
    Data.pbData := Pointer(LocalAlloc(LPTR, Data.cbData));
    if Assigned(Data.pbData) then
    begin
      Move(Pointer(Text)^, Data.pbData^, Data.cbData);
      Result := True;
    end
    else
      Result := False;
  end
  else
    Result := True;
end;

function EncryptData(const AStr: String; const AdditionalEntropy: string): string;
var
  DataIn: DATA_BLOB;
  DataOut: DATA_BLOB;
  DataEntropy: DATA_BLOB;
  pDataEntropy: Pointer;
  bRes: Boolean;
begin
  if SetDataBlobText(AStr, DataIn) then
  begin
    DataOut.cbData := 0;
    DataOut.pbData := nil;
    try
      pDataEntropy := nil;
      if AdditionalEntropy <> '' then
      begin
        if not SetDataBlobText(AdditionalEntropy, DataEntropy) then
          Exit;
        pDataEntropy := @DataEntropy;
      end;

      try
        FillChar(DataOut, SizeOf(DATA_BLOB), 0);
        bRes := CryptProtectData(
                  @DataIn,
                  nil, //data description (PWideChar)
                  pDataEntropy, //optional entropy (PDATA_BLOB)
                  nil, //reserved
                  nil, //prompt struct
                  CRYPTPROTECT_LOCAL_MACHINE, //flags
                  @DataOut
                );
        if bRes then
        begin
          Result := GetDataBlobText(DataOut);

          FreeDataBlob(DataOut);
        end
        else
          RaiseLastOSError;
      finally
        if pDataEntropy <> nil then
          FreeDataBlob(DataEntropy);
      end;

    finally
      FreeDataBlob(DataIn);
    end;
  end;
end;

end.

Когда константа AdditionalEntropy не пуста, я заполняю параметр энтропии в CryptProtectData, но CryptProtectData возвращает False и последняя ошибка ОС выглядит следующим образом:

'c0000005 ACCESS_VIOLATION'

Когда константа AdditionalEntropy пуста, я передаюноль к третьему параметру CryptProtectData, и на этот раз я получаю

'System Error. Code: 87. The parameter is incorrect'

В последнем случае программа иногда зависает.

Что не так с кодом?

...