I read Are there any cryptographically secure PRNG libraries for Delphi? but the solution it presents uses WCrypt2 which I don't want to use.
So I made my own unit depending on nothing.
An example using this unit:
uses SysUtils, WinRandomBytes;
function BytesToHex(const Bytes: TBytes): string;
var i : integer;
begin
Result := '';
for i := 0 to Length(Bytes)-1 do
begin
Result := Result + IntToHex(Bytes[i],2);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var bytes : TBytes;
begin
bytes := OSWinRandomBytes(32);
ShowMessage(BytesToHex(bytes));
end;
This is the new unit for acquiring random bytes via the Windows Crypto API. It exposes one function OSWinRandomBytes() which either returns the requested random bytes or raises an error.
unit WinRandomBytes;
interface
uses SysUtils;
{ Return requested TBytes or raise an Exception }
function OSWinRandomBytes(Length: cardinal) : TBytes;
implementation
uses Windows;
type HCRYPTPROV = pointer;
type TCryptAcquireContextA = function(var phProv: HCRYPTPROV; pszContainer: PAnsiChar; pszProvider: PAnsiChar; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;
type TCryptGenRandom = function(hProv: HCRYPTPROV; dwLen: DWORD; pbBuffer: Pointer): BOOL; stdcall;
type TCryptReleaseContext = function(hProv: HCRYPTPROV; dwFlags: DWORD): BOOL; stdcall;
const PROV_RSA_FULL = 1;
const CRYPT_VERIFYCONTEXT = $F0000000;
var AdvApiLoaded: boolean;
var AdvApiHandle: HModule;
var CryptAcquireContextA : TCryptAcquireContextA;
var CryptGenRandom : TCryptGenRandom;
var CryptReleaseContext : TCryptReleaseContext;
function LoadAdvApi() : boolean;
begin
if not AdvApiLoaded then
begin
AdvApiLoaded := true;
AdvApiHandle := LoadLibrary('advapi32.dll');
if AdvApiHandle <> 0 then
begin
CryptAcquireContextA := GetProcAddress(AdvApiHandle,'CryptAcquireContextA');
CryptGenRandom := GetProcAddress(AdvApiHandle,'CryptGenRandom');
CryptReleaseContext := GetProcAddress(AdvApiHandle,'CryptReleaseContext');
end;
end;
Result := Assigned(CryptAcquireContextA) and Assigned(CryptGenRandom) and Assigned(CryptReleaseContext);
end;
function OSWinRandomBytes(Length: cardinal) : TBytes;
var hProv : HCRYPTPROV;
begin
if not LoadAdvApi() then
begin
raise Exception.Create('Error loading advapi32.dll');
end;
hProv := nil;
if not CryptAcquireContextA(hProv,
nil,
nil,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT) then
begin
RaiseLastOSError();
end;
try
SetLength(Result, Length);
if not CryptGenRandom(hProv, Length, @Result[0]) then
begin
RaiseLastOSError();
end;
finally
CryptReleaseContext(hProv, 0);
end;
end;
begin
AdvApiLoaded := false;
AdvApiHandle := 0;
CryptAcquireContextA := nil;
CryptGenRandom := nil;
CryptReleaseContext := nil;
end.
Aucun commentaire:
Enregistrer un commentaire