# What is the best hash for HMAC?

Long question but I am starting to lose sight of all the HASH algo's there are.

I know SHAKE128 and 256 are part of the SHA-3 standard but is the SHA3 standard officially released yet? i can only find a draft of the publication, does this mean it's not official and therefor not proven to be secure?

I have not found a proper SHAKE128 or 256 c implementation which is why i'm wondering if they should be used yet, because if they were good I'd think there'd be a lot of example code for them.

I know SHA-1 has a theoretical attack which comes close to being practical and obviously MD5 is broken which is why i would like to keep away from those.

Then SHA-2 remains but SHA-2 contains sha 224, 256, 386 and 512. I've tested these (and whirlpool and Tiger) on my test device and this was the speed:

HMAC        bytes   speed μs
Sha1        64      746
128     857
Sha224      64      918
128     1066
Sha256      64      918
128     1066
Sha384      64      2395
128     2840
Sha512      64      2400
128     2840
Sha512_224  64      2390
128     2835
Sha512_356  64      2390
128     2835
MD5         64      308
128     345
Whirlpool   64      5630
128     6420
Tiger       64      832
128     952


So MD5 is fastest followed by SHA-1 but those i would like to evade. Now Tiger is the 3th fastest followed by SHA 224 and 256.

I do know that having an insecure HASH does not necessarily mean your HMAC is insecure but still, I always lock my car even though no one has the key.

So the question: what is the best hash to use, obviously it needs to be relatively fast and by my standards sha-512 isn't fast (enough).

• There are only two significant SHA-2 variants, SHA-256 and SHA-512. All the other variants only differ by truncation and have different IVs. – CodesInChaos Mar 23 '15 at 14:18
• BLAKE2b is faster than MD5 and SHA-1 on modern 64-bit systems and has a native keyed hashing mode that is a suitable equivalent for HMAC. That said, HMAC's security proof only requires the compression function to be a PRF. While MD5 is broken and SHA-1 is likely not far behind, none of their broken properties are relevant to HMAC. HMAC-MD5 and HMAC-SHA1 are still unbroken (albeit distasteful). – Stephen Touset Mar 23 '15 at 15:59
• SHAKE is not at all appropriate for HMAC use, and SHA3 in general is not really designed for use with HMAC – Richie Frame Mar 24 '15 at 6:50

I know SHAKE128 and 256 are part of the SHA-3 standard but is the SHA3 standard officially released yet? i can only find a draft of the publication, does this mean it's not official and therefor not proven to be secure?

No, SHA-3 has not been formally approved. On the other hand, what do you mean "not proved to be secure"? Do you really thing that NIST approves only things that are "proven"? In practice, we have only a handful of things that are "proven" (OTP, secure sharing); while NIST certainly tries to vet what they place on the approved list, they have no proof.

In any case, from your questions, it appears that you are interested in speed. Now, SHA-3 is actually slower in software than SHA-2 (what SHA-3 excells at is if you can implement it with hardware gates); hence it would appear to be the wrong direction for you.

What is the best hash to use, obviously it needs to be relatively fast and by my standards sha-512 isn't fast

Well, before I get into that, I would like to point out that your HMAC implementation can likely be improved.

In HMAC, as you know, we use the key to generate an IPAD and an OPAD; we then compute $a = Hash(IPAD | Message)$, and then compute $b = Hash(OPAD | a)$, and $b$ is the result of the HMAC.

Now, IPAD and OPAD are sized to be precisely 1 Merkle-Damgaard block of the hash function; hence one thing you can do is you can compute the initial hash compression function evaluation $Compress(IV, IPAD)$ and store that intermediate state; similarly, you can compute the initial hash compression function evaluation $Compress(IV, OPAD)$ and store that.

Then, to compute $a = Hash(IPAD | Message)$, you can restore the initiate state for that, and just compute the hash over the message (just using the precomputed evaluation as the IV, and adjusting the final padding to account for the longer message); similarly, you can use the same trick when computing $Hash(OPAD | a)$.

This allows you to compute HMAC using two fewer hash compression operations over the naive method. Now, if you are computing the HMAC only once for a key, or if you are computing HMAC over a huge message, this doesn't help much. However, if you are computing HMACs over a number of tiny messages, this helps a lot.

I suspect you aren't using this optimization, because if you were, the time differential between 64 bytes messages and 128 byte messages would be considerably larger.

Implementing this may have the time taken to HMAC a 64 byte message on SHA256 by 40% (3 hash compression operations rather than 5).

Now, as for the "best hash"; well, if you want to stick with NIST approved operations, the fastest alternative is HMAC-SHA1 (which is FIPS approved still); if you don't care for that, well, the best you have is HMAC-SHA256.

• To be honest i do not know if the code I am using does that. but i believe it does. But that might be a question for stackoverflow. – Vincent Mar 23 '15 at 15:19
• @poncho maybe update now that SHA3 is released? – Legorooj Dec 30 '19 at 23:08

It depends.

If you have full control over the whole system, all components and can use whatever algorithm you want to deploy, you can stick to the one giving you the best efficiency which fulfills your security requirements. In this case, it would be Tiger. However, Tiger has a 192 bit output. If that is not enough for you, go for SHA256.

However, if the availability of the hash function is an issue (e.g. has to be supported in web browsers), and you (with good reason) excluded MD5 and SHA-1, then SHA256 would be the obvious choice.

In general, sticking to SHA-256 today is quite okay for most non-critical systems. It is fast, widespread and has been the target of a lot of cryptanalysis. If for some reason the hash is considered too short, going to SHA-512 is probably your next best candidate.