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
          404142434445464748494a4b4c4d4e4f (80 octets)
   salt = 0x606162636465666768696a6b6c6d6e6f
          a0a1a2a3a4a5a6a7a8a9aaabacadaeaf (80 octets)
   info = 0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf
          f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff (80 octets)
   L    = 82

   PRK  = 0x06a6b88c5853361a06104c9ceb35b45c
          ef760014904671014a193f40c15fc244 (32 octets)
   OKM  = 0xb11e398dc80327a1c8e7f78c596a4934
          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"?

  • 2
    $\begingroup$ 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. $\endgroup$ – Stephen Touset Apr 4 '14 at 22:15
  • $\begingroup$ I will test this when I get home using my hash code, I first need to create the HKDF wrapper code to test though. $\endgroup$ – Richie Frame Apr 5 '14 at 5:18
  • $\begingroup$ @RichieFrame I already tested it with two existing HKDF implementations. The test vector is correct. $\endgroup$ – Stephen Touset Apr 5 '14 at 5:51
  • 1
    $\begingroup$ This question appears to be off-topic because it is about software development (try StackOverflow). $\endgroup$ – D.W. Apr 6 '14 at 3:27
  • 2
    $\begingroup$ 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) $\endgroup$ – Cryptographeur Apr 6 '14 at 11:32

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);
                    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.


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.

  • $\begingroup$ The HMAC algorithm appears to digest the over-sized key just fine. $\endgroup$ – user10496 Jul 3 '15 at 7:55

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