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.
If I move Step 3 between Step 6 and Step 7, then I can arrive at the correct result. Effectively, it uses Next V.
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