Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

I have implemented HKDF by myself and it seems to work good. I managed to replicate all the test vectors listed here but... except this one:

   Test with SHA-256 and longer inputs/outputs

   Hash = SHA-256
   IKM  = 0x000102030405060708090a0b0c0d0e0f
          101112131415161718191a1b1c1d1e1f
          202122232425262728292a2b2c2d2e2f
          303132333435363738393a3b3c3d3e3f
          404142434445464748494a4b4c4d4e4f (80 octets)
   salt = 0x606162636465666768696a6b6c6d6e6f
          707172737475767778797a7b7c7d7e7f
          808182838485868788898a8b8c8d8e8f
          909192939495969798999a9b9c9d9e9f
          a0a1a2a3a4a5a6a7a8a9aaabacadaeaf (80 octets)
   info = 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf
          c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
          d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
          e0e1e2e3e4e5e6e7e8e9eaebecedeeef
          f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff (80 octets)
   L    = 82

   PRK  = 0x06a6b88c5853361a06104c9ceb35b45c
          ef760014904671014a193f40c15fc244 (32 octets)
   OKM  = 0xb11e398dc80327a1c8e7f78c596a4934
          4f012eda2d4efad8a050cc4c19afa97c
          59045a99cac7827271cb41c65e590e09
          da3275600c2f09b8367793a9aca3db71
          cc30c58179ec3e87c14c01d5c1f3434f
          1d87 (82 octets)

After one hour of debug, I figured out (and I believe) that my implementation is right and that this test vector is wrong. I don't manage to get the right OKM value and even the PRK is wrong. To discover this I did the following:

Given that PRK = HMAC-Hash(salt, IKM) (as described in the RFC), I tried to compute the HMAC and I saw that the result value was different.

Can anyone confirm that this test vector is "bugged"?

share|improve this question

closed as off-topic by D.W., e-sushi, figlesquidge, Gilles, rath Apr 7 at 3:58

  • This question does not appear to be about cryptography within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

1  
Comparing the results against any other implementation of HKDF would trivially confirm for you that it is your implementation that is buggy, and not the test vector. Put succinctly, if you hear hoof prints, think horses — not zebras. –  Stephen Touset Apr 4 at 22:15
    
I will test this when I get home using my hash code, I first need to create the HKDF wrapper code to test though. –  Richie Frame Apr 5 at 5:18
    
@RichieFrame I already tested it with two existing HKDF implementations. The test vector is correct. –  Stephen Touset Apr 5 at 5:51
1  
This question appears to be off-topic because it is about software development (try StackOverflow). –  D.W. Apr 6 at 3:27
2  
This question appears to be off-topic because it is too specific, and thus unlikely to be of use to future visitors (although this only became clear after the question had been answered in the negative) –  figlesquidge Apr 6 at 11:32

2 Answers 2

One common pitfall when implementing HMAC(key, data) is mishandling the case when key is longer than the underlying hash block.

In your case salt is 80 octets, which is longer that SHA-256 "block" (64 octets) so the salt have to be run through SHA-256 before being XOR'ed with i_padin the HMAC.

Without seeing any actual code, and provided that the test vector is indeed correct, this is the best answer I can offer.

share|improve this answer

This hastily written implementation of HKDF in C# agrees with the RFC test vectors:

    private const int SHA1 = 1;
    private const int SHA256 = 2;

    private static HMAC NewHMAC(int h, byte[] key)
    {
            switch (h) {
            case SHA1:
                    return new HMACSHA1(key);
            case SHA256:
                    return new HMACSHA256(key);
            default:
                    throw new Exception("NYI");
            }
    }

    private static byte[] HKDFExtract(int h,
            byte[] salt, byte[] ikm)
    {
            using (HMAC hm = NewHMAC(h, salt)) {
                    return hm.ComputeHash(ikm);
            }
    }

    private static byte[] HKDFExpand(int h,
            byte[] prk, byte[] info, int len)
    {
            using (HMAC hm = NewHMAC(h, prk)) {
                    MemoryStream ms = new MemoryStream();
                    byte[] T = new byte[0];
                    int j = 0;
                    while (len > 0) {
                            byte[] buf = new byte[T.Length + info.Length + 1];
                            Array.Copy(T, 0, buf, 0, T.Length);
                            Array.Copy(info, 0, buf, T.Length, info.Length);
                            buf[buf.Length - 1] = (byte)(++ j);
                            T = hm.ComputeHash(buf);
                            int clen = Math.Min(T.Length, len);
                            ms.Write(T, 0, clen);
                            len -= clen;
                    }
                    return ms.ToArray();
            }
    }

Feel free to reuse and modify it at will, in order to print intermediate values, to pinpoint the location at which your implementation diverges. Like @Andrey, I find it plausible that your code gets it wrong when applying HMAC with a key larger than the underlying hash function block size (which is 64 bytes for both SHA-1 and SHA-256): in such a case, the key should first be hashed alone, and the hash result (20 or 32 bytes, for SHA-1 and SHA-256, respectively) is then used as the actual HMAC key.

Thus, you may want to compare your HMAC implementation with the test vectors from RFC 4231, especially the last two, which exercise the "key larger than block" situation.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.