function hmac (key, message)
if (length(key) > blocksize) then
key = hash(key) // keys longer than blocksize are shortened
end if
if (length(key) < blocksize) then
// keys shorter than blocksize are zero-padded ('∥' is concatenation)
key = key ∥ [0x00 * (blocksize - length(key))]
end if
// Where blocksize is that of the underlying hash function
o_key_pad = [0x5c * blocksize] ⊕ key
// Where ⊕ is exclusive or (XOR)
i_key_pad = [0x36 * blocksize] ⊕ key
// Where '∥' is concatenation
return hash(o_key_pad ∥ hash(i_key_pad ∥ message))
end function
为什么它们在那里?他们是如何选择的?
在我看来,$ hash(key + hash(message))$(其中+是串联)就足够了。
很明显我缺少了一些东西。是什么?
#1 楼
这些“魔术数字”与HMAC构造背后的安全证明有关。Bellare,Canetti和Krawczyk在其Crypto'96论文中首先证明$ \ mathrm {NMAC} _ {{k_1,k_2)}(x)= F_ {k_2}(F_ {k_1} (x))$形成安全的MAC(“消息验证码”),条件是$ F_k(\ cdot)$是具有某些良好安全性的迭代和密钥压缩功能,并且$ k_1 $和$ k_2 $是统计上独立的密钥。 NMAC可以通过常见的迭代哈希函数(例如SHA-256)实例化,但是应该可以用密钥替换IV,这在标准实现中是不可能的。
为了避免这个实际问题,作者定义了另一种机制,称为HMAC。给定单个键$ k $以及从压缩函数$ f(\ cdot)$构建的迭代哈希函数$ H(\ cdot)$,它们首先派生两个键$ k_1 = f(k(o \ k) {opad})$和$ k_2 = $ k $中的f(k \ oplus \ mathtt {ipad})$并定义$ \ mathrm {HMAC} _k(x)= \ mathrm {NMAC} _ {{k_1,k_2 )}(x)$。因此,常量$ \ mathtt {ipad} $和$ \ mathtt {opad} $的含义是不同的,因此输入$ k \ oplus \ mathtt {opad} $和$ k \ oplus \ mathtt {ipad} $到压缩功能是不同的。 HMAC设计师任意选择了它们的值,只要$ \ mathtt {opad} \ neq \ mathtt {ipad},任何一对$(\ mathtt {opad},\ mathtt {ipad})$ $。
#2 楼
HMAC的原始安全证明,以及不需要hash
防撞的新证明,都是针对hash(o_key_pad ∥ hash(i_key_pad ∥ message))
的构造而o_key_pad
与i_key_pad
不同(并且都填满一个块)。这就是至少一个常量的基本原理。另一个没有作用,只是必须与第一个不同。 此外,请注意,如果哈希为MD5(或其他具有破坏的耐碰撞性的哈希),则建议的替代
hash(key ∥ hash(message))
无法与未知密钥的随机函数区分开:很容易使消息与MD5冲突,因此对于此结构; HMAC-MD5仍然保持相对强劲,这要归功于额外的i_key_pad
。
评论
$ \ begingroup $
那么,仅仅是其中一个垫子就够了吗?拥有两个背后的理由是什么?
$ \ endgroup $
– BlueRaja-Danny Pflughoeft
13年8月8日19:55
$ \ begingroup $
显然,使用单个常量将符合安全证明;我不知道他们为什么选择两个。
$ \ endgroup $
– cryptopathe
13年3月11日在9:48