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.
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.
Implementing your own PRNG isn't a big deal, you can use a simple LFSR. The real trick is the Seed generation.
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.
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;
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));
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.
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://home.netsurf.de/wolfgang.ehrhardt/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 (home.netsurf.de/wolfgang.ehrhardt/index.html) for many years, and he has been updating with the pascal/delphi routines since then. Surely should be an expert on this!