Skip to content

Commit 20c2a61

Browse files
committed
Make unpredictableSeed use CryptGenRandom (CryptoAPI) on Windows
1 parent bea3184 commit 20c2a61

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

std/random.d

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,42 @@ else
17721772
}
17731773
}
17741774

1775+
version (Windows)
1776+
{
1777+
pragma(lib, "advapi32.lib"); // `std.registry` does so, too.
1778+
1779+
private bool wincryptGenRandom(T)(out T result) @trusted
1780+
{
1781+
import core.sys.windows.windef : DWORD;
1782+
import core.sys.windows.wincrypt;
1783+
1784+
HCRYPTPROV wincryptHandle;
1785+
1786+
const gotHandle = CryptAcquireContext(
1787+
&wincryptHandle,
1788+
null,
1789+
MS_STRONG_PROV.ptr,
1790+
PROV_RSA_FULL,
1791+
CRYPT_VERIFYCONTEXT,
1792+
);
1793+
if (!gotHandle)
1794+
return false;
1795+
1796+
scope (exit)
1797+
if (!CryptReleaseContext(wincryptHandle, 0)) { /* ignore */ }
1798+
1799+
const gotRandom = CryptGenRandom(
1800+
wincryptHandle,
1801+
DWORD(T.sizeof),
1802+
cast(ubyte*) &result,
1803+
);
1804+
if (!gotRandom)
1805+
return false;
1806+
1807+
return true;
1808+
}
1809+
}
1810+
17751811
/**
17761812
A "good" seed for initializing random number engines. Initializing
17771813
with $(D_PARAM unpredictableSeed) makes engines generate different
@@ -1788,7 +1824,19 @@ how excellent the source of entropy is.
17881824
*/
17891825
@property uint unpredictableSeed() @trusted nothrow @nogc
17901826
{
1791-
version (AnyARC4Random)
1827+
version (Windows)
1828+
{
1829+
uint result;
1830+
if (!wincryptGenRandom!uint(result))
1831+
{
1832+
version (none)
1833+
return fallbackSeed();
1834+
else
1835+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1836+
}
1837+
return result;
1838+
}
1839+
else version (AnyARC4Random)
17921840
{
17931841
return arc4random();
17941842
}
@@ -1837,7 +1885,19 @@ if (isUnsigned!UIntType)
18371885
/// ditto
18381886
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391887
{
1840-
version (AnyARC4Random)
1888+
version (Windows)
1889+
{
1890+
UIntType result;
1891+
if (!wincryptGenRandom!UIntType(result))
1892+
{
1893+
version (none)
1894+
return fallbackSeed();
1895+
else
1896+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1897+
}
1898+
return result;
1899+
}
1900+
else version (AnyARC4Random)
18411901
{
18421902
static if (UIntType.sizeof <= uint.sizeof)
18431903
{

0 commit comments

Comments
 (0)