Reference-Request
使用 HMAC-SHA256 的 HKDF 的錯誤測試向量
我自己實現了 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 中進行異或運算。在沒有看到任何實際程式碼的情況下,只要測試向量確實正確,這是我能提供的最佳答案。