问题
Can anyone recommend a cryptographically-secure pseudo random number generator library for Delphi (Win32)?
Can be free or commercial, but will ideally be an active project. I'd like it to include source code.
回答1:
You can use Windows CryptoAPI:
uses Wcrypt2;
function GenerateRandom(Len: Cardinal): TBytes;
var
hProv : HCRYPTPROV;
begin
if not CryptAcquireContext(@hProv,
nil,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT) then
CryptAcquireContext(@hProv,
nil,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
CRYPT_NEWKEYSET + CRYPT_VERIFYCONTEXT);
if hProv > 0 then
try
SetLength(Result,Len);
CryptGenRandom(hProv,Len,@Result[0]);
finally
CryptReleaseContext(hProv,0);
end;
end;
Example of using the above code:
function BytesToHex(const Bytes: TBytes): string;
var
i : integer;
begin
for i := 0 to Length(Bytes)-1 do
Result := Result + IntToHex(Bytes[i],2);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(BytesToHex(GenerateRandom(16)));
end;
回答2:
The Delphi Encryption Compendium (which is famous-ish in the German speaking Delphi community, but nowhere else - presumably since it isn't officially promoted) contains a cryptographically secure Yarrow RNG.
Just include the unit DECRandom (and maybe DECUtils) and use it like this (this example uses IInteger but that isn't mandatory):
function generateRandomNumber: IInteger;
var
A: IInteger;
begin
NRnd(A, 512); // generate 512 Bit random number, 2^512 <= A < 2^513
Result := A;
end;
initialization
// Method 1: uses system timer to initialize the RNG (seed)
RandomSeed;
// Method 2: use own seed
randomSeed(Data, SizeOf(Data));
回答3:
Check out ISAAC (Indirection, Shift, Accumulate, Add, and Count), a fast PRNG and also cryptographically secure ( burtleburtle.net/bob/rand/isaacafa.html ). Probably ISAAC is as fast as the famous Mersenne Twister PRNG.
Wolfgang Ehrhardt has done the pascal/delphi port for ISAAC and is available at http://www.wolfgang-ehrhardt.de/misc_en.html#prng (free and source available). There is also a link to another delphi port provided on the author's site, but I would go with the "Wolfgang Ehrhardt" version. I know his site (http://www.wolfgang-ehrhardt.de/index.html) for many years, and he has been updating with the pascal/delphi routines since then. Surely should be an expert on this!
回答4:
You could use the existing Win32 CryptGenRandom() API.
回答5:
OpenSSL would be a possibility. Source is available although I am not aware if a Delphi version is available. It includes a cryptographically secure prng. It is an active project, but it may be overkill for what you are looking for.
回答6:
I was also going to suggest the OpenSSL libraries. And you also get encryption, SSL, hashing etc included.
Indy has converted a lot of the headers and includes RAND_screen - but that can't/shouldn't be used, apparently, on programs without a UI. Unfortunately it misses out most of the RAND_* ones - but they're very easy to import and use.
eg:
function RAND_load_file(const filename: PAnsiChar; max_bytes: longint): integer; cdecl; external 'libeay32.dll';
function RAND_bytes(buf: PByte; num: integer): integer; cdecl; external 'libeay32.dll';
function RAND_pseudo_bytes(buf: PByte; num: integer): integer; cdecl; external 'libeay32.dll';
then in the code:
RAND_load_file(PAnsiChar(AnsiString('name-of-seed-file')), 512);
//or
//RAND_screen;
...
...
const
PKCS5_SALT_LEN = 8;
var
salt: TBytes;
begin
SetLength(salt, PKCS5_SALT_LEN);
RAND_pseudo_bytes(@salt[0], PKCS5_SALT_LEN);
...
end;
The same seed issues as discussed still apply, of course.
来源:https://stackoverflow.com/questions/2621897/are-there-any-cryptographically-secure-prng-libraries-for-delphi