NIST DRBGs
Documentation 
#include <cryptopp/drbg.h>

NIST SP 80090A added three Deterministic Random Bit Generators (DRBGs) to replace the retired ANSI X9.17 and X9.31 generators. Crypto++ 5.7 added support for DRBGs at Commit 5c932fcc3b6333e4. The initial commit added the Hash_DRBG
and CAVP test vectors. Later, Commit 2868452193e32156 added HMAC_DRBG
and additional CAVP test vectors.
The NIST generators are provided headeronly, so you can fetch the include file and use it in any version of the Crypto++ library. Just drop it in place and use it as if it was part of the release ZIP.
Using a NIST generator is a little trickier than using a typical RandomNumberGenerator from the library. They are trickier because they have randomness requirements during instantiation and reseed, and the source of the randomness matters. In addition, they accept at least three other types of randomness distinct from the entropy and randomness required during instantiation. This page will explain how to use them.
The Crypto++ NIST DRBGs provide Backtracking Resistance (BR). BR is a design feature, and all NIST DRBGs have it. The library's implementation does not provide Predictive Resistance (PR) as specified in SP 80090A, Section 8.8, Prediction Resistance and Backtracking Resistance.
Though the generators are NIST approved and they complete the CAVP test vectors, the classes are not FIPS validated since the library and classes have not undergone CMVP testing.
Classes
The NIST deterministic generators are found in drbg.h
. The base class is called NIST_DRBG
, and it provides the interface for both Hash_DRBG
and HMAC_DRBG
. Both Hash_DRBG
and HMAC_DRBG
are templates, and they require a hash, a security strength in bytes, and a seed length in bytes.
Construction
Hash_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULL, size_t nonceLength=0, const byte* personalization=NULL, size_t personalizationLength=0)
HMAC_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULL, size_t nonceLength=0, const byte* personalization=NULL, size_t personalizationLength=0)
entropy
is a pointer to a byte array generated by a NIST SP 80090C generator. NonblockingRng
, RDRAND and RDSEED generators satisfy SP 80090C. Also see Randomness Source below.
entropyLength
is the size of the entropy
buffer. The constant STRENGTH
is the minimum entropy required to instantiate the generator. The parameter's value will change depending on the generator and the security strength.
nonce
is additional entropy used to instantiate the generator. The nonce buffer is optional. The parameter is "weaker" than entropy, but "stronger" than the personalization string. Also see Randomness Source below.
nonceLength
is the size of the nonce
buffer.
personalization
is additional entropy used to instantiate the generator. The personalization string is optional. The parameter is "weaker" than both entropy and nonce. Also see Randomness Source below.
personalizationLength
is the size of the personalization
buffer.
Randomness Source
The following discusses requirements of entropy
, nonce
, persoanlization
and additional
input.
Entropy
SP 80090A, Section 8.6.5 Randomness Source states the following. Entropy is always required for instantiation and reseed.
A DRBG mechanism requires an approved randomness source during instantiation and reseeding, including whenever prediction resistance is requested (see Section 8.8). This input is requested using the
Get_entropy_input
function introduced in Section 9 and is specified in more detail in SP 80090C.
An approved randomness source is an entropy source that conforms to SP 80090B, or an RBG that conforms to SP 80090C − either a DRBG or an NRBG.
Nonce
SP 80090A, Section 8.6.7, Nonce states the following when a nonce is required:
 A random value that is generated anew for each nonce, using an approved random bit generator.
 A timestamp of sufficient resolution (detail) so that it is different each time it is used.
 A monotonically increasing sequence number, or
 A combination of a timestamp and a monotonically increasing sequence number, such that the sequence number is reset when and only when the timestamp changes
Personalization
SP 80090A, Section 8.7.1, Personalization String states the following:
A personalization string is an optional (but recommended) input to the instantiate function and is used to derive the seed (see Section 8.6.1). The personalization string may be obtained from inside or outside a cryptographic module, and may be an empty string.
The intent of a personalization string is to introduce additional input into the instantiation of a DRBG. This personalization string might contain values unknown to an attacker, or values that tend to differentiate this DRBG instantiation from all others. Ideally, a personalization string will be set to some bitstring that is as unique as possible. Good sources for the personalization string contents include:
 Application identifiers
 Device serial numbers
 User identification
 Permodule or perdevice values
 Timestamps
 Network addresses
 Special key values for this specific DRBG instantiation
 Protocol version identifiers
 Random numbers and Nonces
 Outputs from other approved or nonapproved random bit generators
Additional Input
SP 80090A, Section 8.7.2 Additional Input states the following:
Additional input may optionally be provided to the reseed and generate functions during requests. The additional input may be obtained from inside or outside a cryptographic module, and may include secret or public information.
Generator Testing
The NIST generators are tested in validat1.cpp
in functions ValidateHash_DRBG()
and ValidateHmac_DRBG()
. The test vectors were taken from NIST's CAVP Testing: Random Number Generators.
You can execute the Hash_DRBG
test vectors using cryptest.exe v 77
(HMAC_DRBG
is 78). The tests exercise various instantiations of the generator using different combinations of entropy
(E), nonce
(N), additional
entropy (A), and personalization
strings (P).
$ ./cryptest.exe v 77 Using seed: 1483211134 Testing NIST DRBG generators... passed Hash_DRBG SHA1/128/440 (COUNT=0, E=16, N=8) passed Hash_DRBG SHA1/128/440 (COUNT=1, E=16, N=8) passed Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16) passed Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16) passed Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=0, P=16) passed Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=0, P=16) passed Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16, P=16) passed Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16, P=16) passed Hash_DRBG SHA256/128/440 (C0UNT=0, E=32, N=16, A=32, P=32) passed Hash_DRBG SHA256/128/440 (C0UNT=1, E=32, N=16, A=32, P=32) passed Hash_DRBG SHA512/256/888 (C0UNT=0, E=32, N=16, A=32, P=32) passed Hash_DRBG SHA512/256/888 (C0UNT=1, E=32, N=16, A=32, P=32) Test ended at Sat Dec 31 14:05:34 2016
Sample Programs
The following shows how you might use the NIST generators. The generators are unique becuase they effectively need an external generator to provide the initial entropy used during instantiation and entropy used during reseed.
An example of instantiating a SHA256 generator is shown below. The example provides more entropy than required for SHA256. The NonblockingRng meets the requirements of NIST SP 80090B. RDRAND and RDSEED generators would work as well.
NIST instantiation requirements demand the generator is constructed with at least MINIMUM_ENTROPY
entropy, which is 16 in the case of SHA256. However, a 32byte entropy string is provided below. A nonce is not required for Hash_DRBG
, but a 16 byte nonce is provided (other NIST DRBGs require a nonce).
SecByteBlock entropy(48), result(128); NonblockingRng prng; RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size())); Hash_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16); drbg.GenerateBlock(result, result.size()); ...
The generator has the same entropy requirements during reseed operations (there are no nonce requirements). If you reseed after each generate operation, than you satisfy the requirements for Predictive Resistance (PR).
prng.GenerateBlock(entropy, entropy.size()); drbg.IncorporateEntropy(entropy, entropy.size()); drbg.GenerateBlock(result, result.size()); ...