Skip to content

Commit 9a3cdea

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

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

std/random.d

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,49 @@ 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, PBYTE;
1782+
import core.sys.windows.wincrypt :
1783+
CryptAcquireContext,
1784+
CryptGenRandom,
1785+
CryptReleaseContext,
1786+
CRYPT_VERIFYCONTEXT,
1787+
HCRYPTPROV,
1788+
MS_STRONG_PROV,
1789+
PROV_RSA_FULL;
1790+
1791+
HCRYPTPROV wincryptHandle;
1792+
1793+
const gotHandle = CryptAcquireContext(
1794+
&wincryptHandle,
1795+
null,
1796+
MS_STRONG_PROV.ptr,
1797+
PROV_RSA_FULL,
1798+
CRYPT_VERIFYCONTEXT,
1799+
);
1800+
if (!gotHandle)
1801+
return false;
1802+
1803+
scope (exit)
1804+
if (!CryptReleaseContext(wincryptHandle, 0)) { /* ignore */ }
1805+
1806+
const gotRandom = CryptGenRandom(
1807+
wincryptHandle,
1808+
DWORD(T.sizeof),
1809+
cast(PBYTE) &result,
1810+
);
1811+
if (!gotRandom)
1812+
return false;
1813+
1814+
return true;
1815+
}
1816+
}
1817+
17751818
/**
17761819
A "good" seed for initializing random number engines. Initializing
17771820
with $(D_PARAM unpredictableSeed) makes engines generate different
@@ -1788,7 +1831,19 @@ how excellent the source of entropy is.
17881831
*/
17891832
@property uint unpredictableSeed() @trusted nothrow @nogc
17901833
{
1791-
version (AnyARC4Random)
1834+
version (Windows)
1835+
{
1836+
uint result;
1837+
if (!wincryptGenRandom!uint(result))
1838+
{
1839+
version (none)
1840+
return fallbackSeed();
1841+
else
1842+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1843+
}
1844+
return result;
1845+
}
1846+
else version (AnyARC4Random)
17921847
{
17931848
return arc4random();
17941849
}
@@ -1837,7 +1892,19 @@ if (isUnsigned!UIntType)
18371892
/// ditto
18381893
@property UIntType unpredictableSeed() @nogc nothrow @trusted
18391894
{
1840-
version (AnyARC4Random)
1895+
version (Windows)
1896+
{
1897+
UIntType result;
1898+
if (!wincryptGenRandom!UIntType(result))
1899+
{
1900+
version (none)
1901+
return fallbackSeed();
1902+
else
1903+
assert(false, "CryptAcquireContext() or CryptGenRandom() failed.");
1904+
}
1905+
return result;
1906+
}
1907+
else version (AnyARC4Random)
18411908
{
18421909
static if (UIntType.sizeof <= uint.sizeof)
18431910
{

0 commit comments

Comments
 (0)