Wikipedia列出了以下针对HMAC的伪代码:

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})$ $。

评论


$ \ begingroup $
那么,仅仅是其中一个垫子就够了吗?拥有两个背后的理由是什么?
$ \ endgroup $
– BlueRaja-Danny Pflughoeft
13年8月8日19:55



$ \ begingroup $
显然,使用单个常量将符合安全证明;我不知道他们为什么选择两个。
$ \ endgroup $
– cryptopathe
13年3月11日在9:48

#2 楼

HMAC的原始安全证明,以及不需要hash防撞的新证明,都是针对hash(o_key_pad ∥ hash(i_key_pad ∥ message))的构造而o_key_padi_key_pad不同(并且都填满一个块)。这就是至少一个常量的基本原理。另一个没有作用,只是必须与第一个不同。

此外,请注意,如果哈希为MD5(或其他具有破坏的耐碰撞性的哈希),则建议的替代hash(key ∥ hash(message))无法与未知密钥的随机函数区分开:很容易使消息与MD5冲突,因此对于此结构; HMAC-MD5仍然保持相对强劲,这要归功于额外的i_key_pad