Skip to content

Commit 8efc22f

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

File tree

1 file changed

+61
-2
lines changed

1 file changed

+61
-2
lines changed

std/random.d

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

1775+
version (Windows)
1776+
{
1777+
pragma(lib, "advapi32.lib"); // `std.registry` does so, too.
1778+
1779+
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+
MS_STRONG_PROV,
1789+
PROV_RSA_FULL,
1790+
CRYPT_VERIFYCONTEXT,
1791+
);
1792+
if (!gotHandle)
1793+
return false;
1794+
1795+
scope (exit)
1796+
if (!CryptReleaseContext(&wincryptHandle, 0)) { /* ignore */ }
1797+
1798+
const gotRandom = CryptGenRandom(
1799+
wincryptHandle,
1800+
DWORD(T.sizeof),
1801+
cast(void*) &result,
1802+
);
1803+
if (!gotRandom)
1804+
return false;
1805+
1806+
return true;
1807+
}
1808+
}
1809+
17751810
/**
17761811
A "good" seed for initializing random number engines. Initializing
17771812
with $(D_PARAM unpredictableSeed) makes engines generate different
@@ -1788,7 +1823,19 @@ how excellent the source of entropy is.
17881823
*/
17891824
@property uint unpredictableSeed() @trusted nothrow @nogc
17901825
{
1791-
version (AnyARC4Random)
1826+
version (Windows)
1827+
{
1828+
uint result;
1829+
if (!wincryptGenRandom!UIntType(result))
1830+
{
1831+
version (none)
1832+
return fallbackSeed();
1833+
else
1834+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1835+
}
1836+
return result;
1837+
}
1838+
else version (AnyARC4Random)
17921839
{
17931840
return arc4random();
17941841
}
@@ -1837,7 +1884,19 @@ if (isUnsigned!UIntType)
18371884
/// ditto
18381885
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391886
{
1840-
version (AnyARC4Random)
1887+
version (Windows)
1888+
{
1889+
UIntType result;
1890+
if (!wincryptGenRandom!UIntType(result))
1891+
{
1892+
version (none)
1893+
return fallbackSeed();
1894+
else
1895+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1896+
}
1897+
return result;
1898+
}
1899+
else version (AnyARC4Random)
18411900
{
18421901
static if (UIntType.sizeof <= uint.sizeof)
18431902
{

0 commit comments

Comments
 (0)