Вы можете использовать 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;
Пример использования приведенного выше кода:
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;
Компендиум Delphi Encryption Compendium (известный в немецкоязычном сообществе Delphi, но нигде больше - по-видимому, потому что это не так) t официально рекламируется) содержит криптографически безопасный Yarrow RNG .
Просто включите модуль DECRandom
(и, возможно, DECUtils
) и используйте его следующим образом (в этом примере используется IInteger
, но это не обязательно):
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));
OpenSSL был бы возможным вариантом. Исходный текст доступен, хотя я не знаю, доступна ли версия для Delphi. Он включает криптографически защищенный prng. Это активный проект, но он может оказаться излишним для того, что вы ищете.
Вы можете использовать существующий Win32 CryptGenRandom ()
API.
Я также собирался предложить библиотеки OpenSSL . И вы также получаете шифрование, SSL, хеширование и т. Д.
Indy преобразовал множество заголовков и включает RAND_screen, но, по-видимому, это нельзя / не следует использовать в программах без пользовательского интерфейса. К сожалению, в нем отсутствует большинство RAND_ *, но их очень легко импортировать и использовать.
например:
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';
затем в коде:
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;
Конечно, те же проблемы с начальным значением, которые обсуждались, все еще применяются.
Посмотрите на ISAAC (Indirection, Shift, Accumulate, Add, and Count), быстрый ГПСЧ, а также криптографически безопасный ( burtleburtle.net/bob/rand/isaacafa.html ). Возможно, ISAAC так же быстр, как и знаменитый ГПСЧ Mersenne Twister.
Вольфганг Эрхардт сделал порт ISAAC на pascal/delphi, который доступен по адресу http://www.wolfgang-ehrhardt.de/misc_en.html#prng (бесплатно и с исходными текстами). На сайте автора также есть ссылка на другой порт delphi, но я бы выбрал версию "Wolfgang Ehrhardt". Я знаю его сайт (http://www.wolfgang-ehrhardt.de/index.html) уже много лет, и с тех пор он обновлял его с помощью процедур pascal/delphi. Несомненно, он должен быть экспертом в этом!