Take the 2-minute tour ×

This question already has an answer here:

On Wikipedia it is said that HMAC is basically (without taking into account padding):

$H(key\ \Vert\ H(key\ \Vert\ message))$

where $\Vert$ denotes concatenation.

I understand the need to hash twice, but why concatenate the key a second time in the outter hashing?

Why not simply hash twice, but without reusing the key, like this:

$H( H(key\ \Vert\ message))$

A bit like Bitcoin's double-SHA, rumored to be done to prevent length-extension attacks.

share|improve this question

marked as duplicate by CodesInChaos, fgrieu, rath, DrLecter, e-sushi Mar 18 at 15:41


silly me: I answered a clear duplicate. –  fgrieu Mar 18 at 12:40
@fgrieu At least you gained some points for your efforts. ;) –  e-sushi Mar 18 at 15:42

1 Answer 1

up vote 4 down vote accepted

As pointed in the question, with common Merkle–Damgård hashes like SHA-256, $H(key\ \Vert\ message)$ is vulnerable to a length extension attack, where $H(key\ \Vert\ message\ \Vert\ pad\ \Vert\ extension)$ can be computed knowing $H(key\ \Vert\ message)$ and the length of $key\ \Vert\ message$ (with $pad$ trivially determined from that), for any known $extension$. Indeed, $H( H(key\ \Vert\ message))$ is enough to block that simple attack.

One good reason to NOT use $H( H(key\ \Vert\ message))$ as a MAC is that we do not have a security proof for that construction, when we have one for HMAC since the origin. Even better, the modern security proof of HMAC gives an argument that HMAC is secure even if the compression function in the underlying hash has properties insufficient to make the hash collision-resistant. In particular, HMAC-MD5 still seems quite strong, even though collision-resistance of MD5 is badly broken.

Both of these security proofs require two hashes each starting with (different variants of) the key. Intuitively: there's a similarity to adding rounds in a block cipher, which makes recovering the key or otherwise breaking the cipher much harder; the outer hash sorts of re-enciphers the result of the previous one.

share|improve this answer
thanks a lot and silly me for asking a duplicate... But to be honest I did both Google and not notice the duplicate here on crypto.stackexchange ^ ^ –  Cedric Martin Mar 18 at 14:11
