Я пытаюсь использовать 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'
В последнем случае программа иногда зависает.
Что не так с кодом?