diff --git a/.gitignore b/.gitignore
index 8a4c9f2..0c4dc4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
*.ppu
*~
tests/RandomTest
+src/backup
\ No newline at end of file
diff --git a/src/Olive.Random.BSD.pas b/src/Olive.Random.BSD.pas
new file mode 100644
index 0000000..31f8ec2
--- /dev/null
+++ b/src/Olive.Random.BSD.pas
@@ -0,0 +1,107 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+Unit Olive.Random.BSD;
+
+interface
+
+uses
+ CTypes,
+ Objects,
+ Classes,
+ SysUtils,
+ Olive.Random.RandomInterface,
+ Olive.Random.URandom;
+
+type
+ PCChar = ^CChar;
+ PBSDRandom = ^BSDRandom;
+ BSDRandom = class (RandomTrait, RandomInterface)
+ private
+ function GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+ public
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+procedure arc4random_buf(var Buffer; NBytes : csize_t);
+ cdecl;external 'c' name 'arc4random_buf';
+
+implementation
+
+function BSDRandom.GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+var
+ CharBuffer : array of pcuint8;
+begin
+ SetLength(CharBuffer, NBytes);
+ arc4random_buf(CharBuffer[0], NBytes);
+ if Length(CharBuffer) <> NBytes then
+ begin
+ RandomByteBuffer[0] := 0;
+ Result := -1;
+ end else
+ begin
+ Move(CharBuffer[Low(CharBuffer)], RandomByteBuffer[0], NBytes);
+ Result := High(RandomByteBuffer);
+ end;
+end;
+
+function BSDRandom.GetBytes(NBytes : SizeUInt) : TBytes;
+var
+ RandomBuffer : AnsiString;
+begin
+ SetLength(RandomBuffer, NBytes);
+ SetLength(Result, NBytes);
+ RandomBuffer := GetString(NBytes);
+ Move(RandomBuffer[1], Result[0], NBytes);
+end;
+
+function BSDRandom.GetString(NBytes : SizeUInt) : AnsiString;
+var
+ RandomBuffer : TBytes;
+ B : SizeInt;
+begin
+ SetLength(RandomBuffer, (NBytes*2));
+ SetLength(Result, NBytes);
+ B := GetSystemBytes(RandomBuffer, (NBytes*2));
+ Move(RandomBuffer[0], Result[1], NBytes);
+end;
+
+end.
diff --git a/src/Olive.Random.Generic.pas b/src/Olive.Random.Generic.pas
new file mode 100644
index 0000000..80273b6
--- /dev/null
+++ b/src/Olive.Random.Generic.pas
@@ -0,0 +1,81 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+Unit Olive.Random.Generic;
+
+interface
+
+uses
+ Objects,
+ Classes,
+ SysUtils,
+ Olive.Random.RandomInterface;
+
+type
+ PRandomGeneric = ^RandomGeneric;
+ RandomGeneric = class (RandomTrait, RandomInterface)
+ public
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+implementation
+
+
+function RandomGeneric.GetBytes(NBytes : SizeUInt) : TBytes;
+var
+ RandomBuffer : AnsiString;
+begin
+ SetLength(Result, NBytes);
+ RandomBuffer := GetString(NBytes);
+ Move(RandomBuffer[1], Result[0], NBytes);
+end;
+
+function RandomGeneric.GetString(NBytes : SizeUInt) : AnsiString;
+var
+ ByteBuffer : TBytes;
+begin
+ SetLength(Result, NBytes);
+ SetLength(ByteBuffer, (NBytes*2));
+ ByteBuffer := MTRandomBytes((NBytes*2));
+ Move(ByteBuffer[0], Result[1], NBytes);
+end;
+
+end.
diff --git a/src/Olive.Random.Linux.pas b/src/Olive.Random.Linux.pas
new file mode 100644
index 0000000..0d47368
--- /dev/null
+++ b/src/Olive.Random.Linux.pas
@@ -0,0 +1,133 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+Unit Olive.Random.Linux;
+
+interface
+
+uses
+ CTypes,
+ Objects,
+ Classes,
+ SysUtils,
+ Olive.Random.RandomInterface;
+
+const
+ {$IF DEFINED(CPU64)} SYS_getrandom = 318;
+ {$ELSEIF DEFINED(CPU32)} SYS_getrandom = 355;
+ {$ELSE} SYS_getrandom = 278; {$ENDIF}
+ GRND_DEFAULT = $0000;
+
+type
+ PCChar = ^CChar;
+ PLinuxRandom = ^LinuxRandom;
+ LinuxRandom = class (RandomTrait, RandomInterface)
+ private
+ function GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+ public
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+function syscall(NRGetRandom : CInt) : CInt;cdecl;varargs;external 'c' name 'syscall';
+
+implementation
+
+function LinuxRandom.GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+var
+ RandomCharBuffer : PCChar;
+ Return : CInt;
+begin
+ GetMem(RandomCharBuffer, NBytes);
+ Return := syscall(SYS_getrandom, @RandomCharBuffer^, NBytes, GRND_DEFAULT);
+ Move(RandomCharBuffer[0], RandomByteBuffer[0], NBytes);
+ FreeMem(RandomCharBuffer);
+ Result := Return;
+end;
+
+function LinuxRandom.GetBytes(NBytes : SizeUInt) : TBytes;
+var
+ RandomBuffer : AnsiString;
+begin
+ SetLength(Result, NBytes);
+ SetLength(RandomBuffer, NBytes);
+ RandomBuffer := GetString(NBytes);
+ Move(RandomBuffer[1], Result[0], NBytes);
+end;
+
+function LinuxRandom.GetString(NBytes : SizeUInt) : AnsiString;
+var
+ Buffer : TFileStream;
+ RandomByteBuffer : TBytes;
+ ReadBytes : SizeUInt;
+ SysBytesRead : CInt;
+begin
+ SetLength(RandomByteBuffer, (NBytes*2));
+ SetLength(Result, NBytes);
+ SysBytesRead := GetSystemBytes(RandomByteBuffer, (NBytes*2));
+ if (SysBytesRead <> (NBytes*2)) then
+ begin
+ if FileExists('/dev/urandom') then
+ begin
+ Writeln('URandom');
+ Buffer := TFileStream.Create('/dev/urandom', fmOpenRead);
+ Buffer.Position := 0;
+ ReadBytes := 0;
+ while ReadBytes <= (NBytes*2) do
+ begin
+ Buffer.Read(RandomByteBuffer[ReadBytes], SizeOf(RandomByteBuffer));
+ Inc(ReadBytes);
+ end;
+ Buffer.Free;
+ end
+ else if (not FileExists('/dev/udrandom')) then
+ begin
+ Writeln('Random');
+ RandomByteBuffer := MTRandomBytes((NBytes*2));
+ end else
+ begin
+ raise Exception.Create('All methods to aquire random bytes failed.')
+ at get_caller_addr(get_frame), get_caller_frame(get_frame);
+ end;
+ end;
+ Move(RandomByteBuffer[0], Result[1], NBytes);
+end;
+
+end.
diff --git a/src/Olive.Random.RandomInterface.pas b/src/Olive.Random.RandomInterface.pas
new file mode 100644
index 0000000..af2464f
--- /dev/null
+++ b/src/Olive.Random.RandomInterface.pas
@@ -0,0 +1,90 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+{$interfaces corba}
+{$codepage UTF8}
+Unit Olive.Random.RandomInterface;
+
+interface
+
+uses
+ Classes,
+ SysUtils;
+
+type
+ RandomInterface = interface
+ ['{0750E585-C1D2-4C1F-A8A4-4EDC41847396}']
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+ RandomTrait = class (TObject)
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function MTRandomBytes(NBytes : SizeUInt) : TBytes; virtual;
+ end;
+
+implementation
+
+constructor RandomTrait.Create;
+begin
+ inherited Create;
+end;
+
+destructor RandomTrait.Destroy;
+begin
+ inherited Destroy;
+end;
+
+function RandomTrait.MTRandomBytes(NBytes : SizeUInt) : TBytes;
+var
+ i : SizeUint;
+begin
+ Randomize;
+ SetLength(Result, (NBytes*2));
+ for i := 0 to (NBytes*2) do
+ begin
+ Result[i] := Random(MaxInt) mod 256;
+ end;
+ SetLength(Result, NBytes);
+end;
+
+end.
diff --git a/src/Olive.Random.URandom.pas b/src/Olive.Random.URandom.pas
new file mode 100644
index 0000000..c6db58b
--- /dev/null
+++ b/src/Olive.Random.URandom.pas
@@ -0,0 +1,131 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+Unit Olive.Random.URandom;
+
+interface
+
+uses
+ CTypes,
+ Objects,
+ Classes,
+ SysUtils,
+ Olive.Random.RandomInterface;
+
+const
+ {$IF DEFINED(CPU64)} SYS_getrandom = 318;
+ {$ELSEIF DEFINED(CPU32)} SYS_getrandom = 355;
+ {$ELSE} SYS_getrandom = 278; {$ENDIF}
+ GRND_DEFAULT = $0000;
+
+type
+ PCChar = ^CChar;
+ PURandom = ^URandom;
+ URandom = class (RandomTrait, RandomInterface)
+ private
+ function GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+ public
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+function syscall(NRGetRandom : CInt) : CInt;cdecl;varargs;external 'c' name 'syscall';
+
+implementation
+
+function URandom.GetSystemBytes(var RandomByteBuffer : TBytes; NBytes : SizeUint) : CInt;
+var
+ RandomCharBuffer : PCChar;
+ Return : CInt;
+begin
+ GetMem(RandomCharBuffer, NBytes);
+ Return := syscall(SYS_getrandom, @RandomCharBuffer^, NBytes, GRND_DEFAULT);
+ Move(RandomCharBuffer[0], RandomByteBuffer[0], NBytes);
+ FreeMem(RandomCharBuffer);
+ Result := Return;
+end;
+
+function URandom.GetBytes(NBytes : SizeUInt) : TBytes;
+var
+ RandomBuffer : AnsiString;
+begin
+ SetLength(Result, NBytes);
+ SetLength(RandomBuffer, NBytes);
+ RandomBuffer := GetString(NBytes);
+ Move(RandomBuffer[1], Result[0], NBytes);
+end;
+
+function URandom.GetString(NBytes : SizeUInt) : AnsiString;
+var
+ Buffer : TFileStream;
+ RandomByteBuffer : TBytes;
+ ReadBytes : SizeUInt;
+ SysBytesRead : CInt;
+begin
+ SetLength(RandomByteBuffer, (NBytes*2));
+ SetLength(Result, NBytes);
+ SysBytesRead := GetSystemBytes(RandomByteBuffer, (NBytes*2));
+ if (SysBytesRead <> (NBytes*2)) then
+ begin
+ if FileExists('/dev/urandom') then
+ begin
+ Buffer := TFileStream.Create('/dev/urandom', fmOpenRead);
+ Buffer.Position := 0;
+ ReadBytes := 0;
+ while ReadBytes <= (NBytes*2) do
+ begin
+ Buffer.Read(RandomByteBuffer[ReadBytes], SizeOf(RandomByteBuffer));
+ Inc(ReadBytes);
+ end;
+ Buffer.Free;
+ end
+ else if (not FileExists('/dev/udrandom')) then
+ begin
+ RandomByteBuffer := MTRandomBytes((NBytes*2));
+ end else
+ begin
+ raise Exception.Create('All methods to aquire random bytes failed.')
+ at get_caller_addr(get_frame), get_caller_frame(get_frame);
+ end;
+ end;
+ Move(RandomByteBuffer[0], Result[1], NBytes);
+end;
+
+end.
diff --git a/src/Olive.Random.Windows.pas b/src/Olive.Random.Windows.pas
new file mode 100644
index 0000000..e5e6210
--- /dev/null
+++ b/src/Olive.Random.Windows.pas
@@ -0,0 +1,123 @@
+{********************************************************}
+{ }
+{ Olive BBS }
+{ }
+{ Copyleft (ↄ) 2020 Olive BBS }
+{ }
+{ This file is part of Olive BBS }
+{ }
+{ Olive BBS is free software: you can redistribute it }
+{ and/or modify it under the terms of the GNU General }
+{ Public License as published by the Free Software }
+{ Foundation, either version 3 of the License, or }
+{ (at your option) any later version. }
+{ }
+{ Olive BBS is distributed in the hope that it will }
+{ be useful, but WITHOUT ANY WARRANTY; without even }
+{ the implied warranty of MERCHANTABILITY or FITNESS }
+{ FOR A PARTICULAR PURPOSE. See the GNU General }
+{ Public License for more details. }
+{ }
+{ You should have received a copy of the GNU General }
+{ Public License along with Olive BBS. If not, see }
+{ . }
+{ }
+{********************************************************}
+{ ___ ___ ___ }
+{ ( ).-. ( ) ( ) }
+{ .--. | |( __)___ ___ .--. | |.-. | |.-. .--. }
+{ / \| |(''"( )( / \| / \| / \ / _ \ }
+{ | .-. | | | | | | | | .-. | .-. | .-. |. .' `. ; }
+{ | | | | | | | | | | | | | | | | | | | || ' | | }
+{ | | | | | | | | | | | |/ | | | | | | |_\_`.(___) }
+{ | | | | | | | | | | | ' _.| | | | | | ( ). '. }
+{ | ' | | | | | ' ' ; | .'.-| ' | | ' | || | `\ | }
+{ ' `-' | | | | \ `' /' `-' ' `-' ;' `-' ; ; '._,' ' }
+{ `.__.(___(___) '_.' `.__.' `.__. `.__. '.___.' }
+{ }
+{********************************************************}
+
+{$mode objfpc}{$H+}
+Unit Olive.Random.Windows;
+
+interface
+
+uses
+ Objects,
+ Classes,
+ SysUtils,
+ Windows,
+ Olive.Random.RandomInterface;
+
+const
+ CRYPT_VERIFYCONTEXT = $F0000000;
+ CRYPT_MACHINE_KEYSET = 32;
+ PROV_RSA_FULL = 1;
+ CRYPT_NEWKEYSET = 8;
+
+
+type
+ HCRYPTPROV = ULONG_PTR;
+ PWindowsRandom = ^WindowsRandom;
+ WindowsRandom = class (RandomTrait, RandomInterface)
+ public
+ function GetBytes(NBytes : SizeUInt) : TBytes;
+ function GetString(NBytes : SizeUInt) : AnsiString;
+ end;
+
+ function CryptAcquireContextW(var phProv: HCRYPTPROV; pszContainer: LPCTSTR;
+ pszProvider: LPCTSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL;stdcall; external 'advapi32' name 'CryptAcquireContextW';
+ function CryptGenRandom(hProv: HCRYPTPROV; dwLen: DWORD;
+ var pbBuffer: BYTE): BOOL; stdcall; external 'advapi32' name 'CryptGenRandom';
+
+implementation
+
+
+function WindowsRandom.GetBytes(NBytes : SizeUInt) : TBytes;
+var
+ RandomBuffer : AnsiString;
+begin
+ SetLength(Result, NBytes);
+ SetLength(RandomBuffer, NBytes);
+ RandomBuffer := GetString(NBytes);
+ Move(RandomBuffer[1], Result[0], NBytes);
+end;
+
+function WindowsRandom.GetString(NBytes : SizeUInt) : AnsiString;
+var
+ RandomBuffer : ^BYTE;
+ hCryptProv : ^ULONG_PTR;
+ WinCrypt : Boolean;
+ ReturnString : AnsiString;
+ i, Bytes : SizeInt;
+ ReturnBytes : TBytes;
+begin
+ GetMem(RandomBuffer, (NBytes * 2));
+ CryptAcquireContextW(hCryptProv^, nil, nil, PROV_RSA_FULL,
+ CRYPT_NEWKEYSET or CRYPT_MACHINE_KEYSET or CRYPT_VERIFYCONTEXT );
+ WinCrypt := CryptGenRandom(hCryptProv^, (NBytes * 2), RandomBuffer^);
+ SetLength(ReturnString, (NBytes*2));
+ if WinCrypt then
+ begin
+ for i := 1 to (NBytes*2) do
+ begin
+ ReturnString[i] := Chr(RandomBuffer[i]);
+ end;
+ end else
+ begin
+ SetLength(ReturnBytes, (NBytes*2));
+ ReturnBytes := MTRandomBytes((NBytes*2));
+ end;
+ SetLength(Result, NBytes);
+ FreeMem(RandomBuffer, (NBytes * 2));
+ if WinCrypt then
+ begin
+ Move(ReturnString[1], Result[1], NBytes);
+ end else
+ begin
+ Move(ReturnBytes[0], Result[1], NBytes);
+ end;
+
+end;
+
+end.