I've been starring at this issue for about three days now, and think I need a second set of eyes on the problem. I'm implementing NIST's HASH_DRBG
from SP 800-90A Rev. 1, June 2015 (its the latest doc according to NIST Special Publications page). The test vectors are located at CAVP Testing: Random Number Generators.
The problem I am having is I cannot arrive at the test vector result if I follow the algorithm as published. If I move one step down a few slots, then I can arrive at the correct result. Its very unusual, and I'm not sure what I am doing wrong.
The algorithm I am having problem with it Hash_DRBG_Generate Process. Here's the algorithm as a screen capture from section 10.1.1.4 around page 50:
Step 3, Hashgen, produces the pseduo-random bits for the caller. Steps 4-6 then update state for the next call to generate.
If I execute the algorithm exactly as specified, then I return the following bit string to the caller, which is incorrect. Effectively, it uses Current V.
6C58FE76D644750EA5BE880BB1BDD2D54C98139D70BA0F7CA8637EB2527F8BFD223DEB9187976E87
91B706804FB28534D13EC4818FB59DB430C9F04F55AA8549EAD53B39624DAD6CFDAAD99412B8AEB0
If I move Step 3 between Step 6 and Step 7, then I can arrive at the correct result. Effectively, it uses Next V.
56f33d4fdbb9a5b64d26234497e9dcb87798c68d08f7c41199d4bddf97ebbf6cb5550e5d149ff4d5
bd0f05f25a6988c17436396227184af84a564335658e2f8572bea333eee2abff22ffa6de3e22aca2
My questions are pretty crummy:
- Am am parsing things incorrectly or doing something obviously wrong?
- Why do I need to move Step 3 down to Step 6 and Step 7?
- If I have to choose, should I select (a) correct algorithm and incorrect result, or (b) incorrect algorithm and correct result?
Here's the test vector I'm working from. Its the first test vector (COUNT 0
) using SHA1 with no predictive resistance. The problem occurs at GENERATE (FIRST CALL). The V
value shown, 1658...ed56b
, is the value after Steps 4-6 have executed. However, V does not take that value until after Step 3, Hashgen, has executed.
[SHA-1]
[PredictionResistance = False]
[EntropyInputLen = 128]
[NonceLen = 64]
[PersonalizationStringLen = 0]
[AdditionalInputLen = 0]
[ReturnedBitsLen = 640]
COUNT = 0
EntropyInput = 1610b828ccd27de08ceea032a20e9208
Nonce = 492cf1709242f6b5
PersonalizationString =
** INSTANTIATE:
V = 9e8301725d5f133b4ab7d329fd2f87ae5f89d96a9dd7e2b98beee1c707b8c3fe412d1125b58bae5dc08a11dac3be4a3147347160fef218
C = e5e12450450efe5fdc777c95b8c23c938fcd592e2d788f12461936e4a16131b1f2d11ce7f0159ee1e635e62f3df8bda4fea077ad5f9d06
reseed counter = 1
EntropyInputReseed = 72d28c908edaf9a4d1e526d8f2ded544
AdditionalInputReseed =
** RESEED:
V = 745c659f2944829ca6e209c8ca2dddecf9f1861383e34e94007a3a51b8444fd5ae738e7d9c0d5e69aa97ee16c49cfd2432eb32ba5738fa
C = a1fc40009357a024d878818cf6f979a88d4cc5d760b308ae1a5b9f067972e6f7cf92ddb129a8d3c1bb0005bcf3f8871fd65e794f1990b7
reseed counter = 1
AdditionalInput =
** GENERATE (FIRST CALL):
V = 1658a59fbc9c22c17f5a8b55c1275795873e4beae49657421ad5d95831b736cd7e066c738bcbb343933c411c7c17917593c03a77bed56b
C = a1fc40009357a024d878818cf6f979a88d4cc5d760b308ae1a5b9f067972e6f7cf92ddb129a8d3c1bb0005bcf3f8871fd65e794f1990b7
reseed counter = 2
AdditionalInput =
ReturnedBits = 56f33d4fdbb9a5b64d26234497e9dcb87798c68d08f7c41199d4bddf97ebbf6cb5550e5d149ff4d5bd0f05f25a6988c17436396227184af84a564335658e2f8572bea333eee2abff22ffa6de3e22aca2
** GENERATE (SECOND CALL):
V = b854e5a04ff3c2e657d30ce2b820d13e148b11c245495ff03531785eab2a1dc54d994a5597b15c5b10001f49606c88b4ff0d61acb61820
C = a1fc40009357a024d878818cf6f979a88d4cc5d760b308ae1a5b9f067972e6f7cf92ddb129a8d3c1bb0005bcf3f8871fd65e794f1990b7
reseed counter = 3