Reference-Request

使用 HMAC-SHA256 的 HKDF 的錯誤測試向量

  • April 5, 2014

我自己實現了 HKDF,它似乎工作得很好。我設法複製了這裡列出的所有測試向量,但是……除了這個:

  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)

經過一小時的調試,我發現(並且我相信)我的實現是正確的,而這個測試向量是錯誤的。我無法獲得正確的OKM價值,甚至PRK是錯誤的。為了發現這一點,我做了以下事情:

鑑於此PRK = HMAC-Hash(salt, IKM)(如RFC中所述),我嘗試計算 HMAC,但發現結果值不同。

誰能確認這個測試向量被“竊聽”了?

這個用 C# 倉促編寫的 HKDF 實現與 RFC 測試向量一致:

   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();
           }
   }

隨意重用和修改它,以便列印中間值,以查明實現分歧的位置。像@Andrey 一樣,我發現在使用大於底層雜湊函式塊大小(SHA-1 和 SHA-256 均為 64 字節)的密鑰應用 HMAC 時,您的程式碼可能會出錯:在這種情況下, key 應該首先單獨進行散列,然後將散列結果(SHA-1 和 SHA-256 分別為 20 或 32 個字節)用作實際的 HMAC 密鑰。

因此,您可能希望將您的 HMAC 實現與RFC 4231中的測試向量進行比較,尤其是最後兩個,它們會遇到“密鑰大於塊”的情況。

實現時的一個常見陷阱是錯誤處理比底層雜湊塊更長HMAC(key, data)的情況。key

在您的情況下salt是 80 個八位字節,比 SHA-256“塊”(64 個八位字節)更長,因此salt必須先通過 SHA-256 執行,然後才能i_pad在 HMAC 中進行異或運算。

在沒有看到任何實際程式碼的情況下,只要測試向量確實正確,這是我能提供的最佳答案。

引用自:https://crypto.stackexchange.com/questions/15404