Minimum requirements: OS >= Windows Vista and compilers 10 or 6.
Intel introduced RdRand with its Ivy Bridge CPUs and RdSeed with its Broadwell CPUs; bypassing Haswell.
I have an Ivy Bridge so no RdSeed.
RdRand is reseeded, at most, every 511 * 128 bits and during idle periods. An analogy could be a quartz watch getting a radio signal every 24 hours.
What is the difference between RdRand and RdSeed?
From Intel:
The numbers returned by RdRand have additive prediction resistance. "If you put two 64-bit values with additive prediction resistance togehter (sic), the prediction resistance of the resulting value is only 65 bits (2^64 + 2^64 = 2^65)." says Intel. They go on, "The numbers retuned by RDSEED have multiplicative prediction resistance. If you use two 64-bit samples with multiplicative prediction resistance to build a 128-bit value, you end up with a random number with 128 bits of prediction resistance (2^128 * 2^128 = 2^256). Combine two of those 128-bit values together, and you get a 256-bit number with 256 bits of prediction resistance."
Oops. John M. of the Intel Developer Zone should have written '2^64 * 2^64 = 2^128' in the last part. That with the misspelling of 'together' indicates a bad hair day.
In the Digital Random Number Generator (DRNG) Software Implementation Guide we are given a method whereby a RdRand output can be made with multiplicative prediction resistance.
The method is to use 512 * 128 bit random numbers, encrypt them with CBC-MAC AES and use the last 128 bits, normally the MAC, as a seed. I say 'normally' because we are not using the result as a MAC - we are simply 'hammering' 512 blocks via a '512:1 data reduction' to a seed. It is usually dangerous to use a random set of Initial Values ( IV ) in the context of a MAC generation but, again, we are not using the result as a MAC and Intel use a random IV.
I suspect that Microsoft's BCryptGenRandom may not have multiplicative prediction resistance. It certainly did not when it was introduced in Windows Vista ( NIST SP 800-90 standard ) - not sure about Windows 8 and since. I have no idea how often Microsoft reseed their generator.
It occurred to me that we could use CBC-MAC AES on BCryptGenRandom to get "seed-grade entropy".
The following code does just that. It uses a random IV and generates a random encryption key by BCryptGenRandom itself. The 'plaintext' to encrypt is 512 blocks of 16 random bytes ( 8KB ). The exercise is repeated to give 2 * 128 bits - a 256 bit seed. It has two modes depending upon whether we want a binary output or a hex output. If a hex output then it is placed upon the clipboard.
How long will this lot take? On my machine a 256 bit seed is determined in 0.25ms.
Uses?
CMWC256Lite ( Random number generator ) is from CMWC256 and written for >= Windows XP SP3. It has a method 'GetHexSeed256' and that can be used in Seed( GetHexSeed256 ). If you have >= Windows Vista then you can now use Seed( GetSeed256( %Bin ) ).
Another use is in generating a key for encryption for putting into a password manager.
Intel introduced RdRand with its Ivy Bridge CPUs and RdSeed with its Broadwell CPUs; bypassing Haswell.
I have an Ivy Bridge so no RdSeed.
RdRand is reseeded, at most, every 511 * 128 bits and during idle periods. An analogy could be a quartz watch getting a radio signal every 24 hours.
What is the difference between RdRand and RdSeed?
From Intel:
The short answer
The decision process for which instruction to use is mercifully simple, and based on what the output will be used for.
If you wish to seed another pseudorandom number generator (PRNG), use RDSEED
For all other purposes, use RDRAND
That's it. RDSEED is intended for seeding a software PRNG of arbitrary width. RDRAND is intended for applications that merely require high-quality random numbers.
The decision process for which instruction to use is mercifully simple, and based on what the output will be used for.
If you wish to seed another pseudorandom number generator (PRNG), use RDSEED
For all other purposes, use RDRAND
That's it. RDSEED is intended for seeding a software PRNG of arbitrary width. RDRAND is intended for applications that merely require high-quality random numbers.
Oops. John M. of the Intel Developer Zone should have written '2^64 * 2^64 = 2^128' in the last part. That with the misspelling of 'together' indicates a bad hair day.
In the Digital Random Number Generator (DRNG) Software Implementation Guide we are given a method whereby a RdRand output can be made with multiplicative prediction resistance.
The method is to use 512 * 128 bit random numbers, encrypt them with CBC-MAC AES and use the last 128 bits, normally the MAC, as a seed. I say 'normally' because we are not using the result as a MAC - we are simply 'hammering' 512 blocks via a '512:1 data reduction' to a seed. It is usually dangerous to use a random set of Initial Values ( IV ) in the context of a MAC generation but, again, we are not using the result as a MAC and Intel use a random IV.
I suspect that Microsoft's BCryptGenRandom may not have multiplicative prediction resistance. It certainly did not when it was introduced in Windows Vista ( NIST SP 800-90 standard ) - not sure about Windows 8 and since. I have no idea how often Microsoft reseed their generator.
It occurred to me that we could use CBC-MAC AES on BCryptGenRandom to get "seed-grade entropy".
The following code does just that. It uses a random IV and generates a random encryption key by BCryptGenRandom itself. The 'plaintext' to encrypt is 512 blocks of 16 random bytes ( 8KB ). The exercise is repeated to give 2 * 128 bits - a 256 bit seed. It has two modes depending upon whether we want a binary output or a hex output. If a hex output then it is placed upon the clipboard.
How long will this lot take? On my machine a 256 bit seed is determined in 0.25ms.
Uses?
CMWC256Lite ( Random number generator ) is from CMWC256 and written for >= Windows XP SP3. It has a method 'GetHexSeed256' and that can be used in Seed( GetHexSeed256 ). If you have >= Windows Vista then you can now use Seed( GetSeed256( %Bin ) ).
Another use is in generating a key for encryption for putting into a password manager.
Code:
#Compile Exe #Dim All #Register None #Include "Win32API.inc" %BlockSize = 16 %AES128 = 16 %AES192 = 24 %AES256 = 32 %Bin = 0 %Hex = 1 Function PBMain() As Long MsgBox GetSeed256( %Hex ) End Function Function GetSeed256( lMode As Long ) As String Local hAESAlg, hHashAlg, dwResult, hRand, hKey As Dword Local IV, AESKey, sRandomBytes, sReturn, sTemp, sFunction As String Local i, ClipResult As Long For i = 1 To 2 ' generate 2 * 128 bits ==> 256 bits IV = String$(16,0) ' Generate a random IV BCryptOpenAlgorithmProvider(hRand, $$BCRYPT_RNG_ALGORITHM, $$Nul, 0) ' Prepare For Random number generation BCryptGenRandom(hRand, StrPtr( IV ), 16, 0) BCryptCloseAlgorithmProvider(hRand, 0) AESKey = String$( 32, 0 ) ' Generate a random encryption key BCryptOpenAlgorithmProvider(hRand, $$BCRYPT_RNG_ALGORITHM, $$Nul, 0) ' Prepare For Random number generation BCryptGenRandom(hRand, StrPtr( AESKey ), 32, 0) ' 256 bits BCryptCloseAlgorithmProvider(hRand, 0) sRandomBytes = String$( 8192, 0 ) ' Generate 512 * %BlockSize random numbers BCryptOpenAlgorithmProvider(hRand, $$BCRYPT_RNG_ALGORITHM, $$Nul, 0) ' Prepare For Random number generation BCryptGenRandom(hRand, StrPtr( sRandomBytes ), 8192, 0) BCryptCloseAlgorithmProvider(hRand, 0) BCryptOpenAlgorithmProvider( hAESAlg, $$BCRYPT_AES_ALGORITHM, $$Nul, 0 ) ' Use default CBC algorithm BCryptGenerateSymmetricKey( hAESAlg, hKey, ByVal %null, 0, StrPtr( AESKey ), %AES128, 0 ) ' We want hKey ' Perform the encryption in place - output buffer = input buffer ' Note that we do not need padding so last parameter is zero BCryptEnCrypt( hKey, StrPtr( sRandomBytes ), Len( sRandomBytes ), ByVal %Null, StrPtr( IV ), _ %BlockSize, StrPtr( sRandomBytes ), Len( sRandomBytes ), dwResult, 0 ) BCryptCloseAlgorithmProvider( hAESAlg, 0 ) BCryptDestroyKey( hKey ) sReturn += Right$( sRandomBytes, 16 ) ' Last block of ciphertext - 128 bits Next If lMode = %Hex Then sTemp = Space$( 65 ) CryptBinaryToString( StrPtr( sReturn ), 32, %CRYPT_STRING_HEXRAW Or %CRYPT_STRING_NOCRLF, ByVal StrPtr( sTemp ), 65) sFunction = UCase$( Left$( sTemp, 64 ) ) Do Clipboard Reset, ClipResult Loop Until IsTrue ClipResult Do Clipboard Set Text sFunction, ClipResult Loop Until IsTrue ClipResult Function = sFunction Else Function = sReturn End If End Function
Comment