2

I've been trying to learn how HMAC is calculated but seem to be missing something. According to this wiki page, calling HMAC-SHA1 on an empty key and message should result in a value of fbdb1d1b18aa6c08324b7d64b71fb76370690e1d.

I've confirmed it with:

$ echo -n "" | openssl dgst -sha1 -hmac ""

(stdin)= fbdb1d1b18aa6c08324b7d64b71fb76370690e1d

Following the pseudocode in the wiki page, I tried running this in bash:

ipad=$(printf '\x36%.0s' {1..64})

opad=$(printf '\x5C%.0s' {1..64})

echo -n $opad$(echo -n $ipad | sha1sum | awk '{print $1}') | sha1sum

I thought since the key is empty, the inner padded key will just be 64 bytes of \x36 characters and \x5C for the outer padded key. And since the message is also empty, HMAC can be calculated via SHA1(o_key_pad||SHA1(i_key_pad)). But it returns a different result. What am I missing?

schroeder
  • 129,372
  • 55
  • 299
  • 340

1 Answers1

2

The output of sha1sum is in ASCII to display the hexadecimal digest. HMAC-SHA1 uses the raw, binary output of the hash, not any encoded representation of it. What you have done is equivalent to this:

HMACK(m) = hex(H((K ⊕ opad) || hex(H((K ⊕ ipad) || m))))

An actual HMAC implementation with key K, message m, and hash function H is defined as:

HMACK(m) = H((K ⊕ opad) || H((K ⊕ ipad) || m))

Let's try modifying your script to convert hex back into binary with xxd and run it in bash:

$ ipad=$(printf '\x36%.0s' {1..64})
$ opad=$(printf '\x5C%.0s' {1..64})
$ echo -n ${opad}$(echo -n "$ipad" | sha1sum | awk '{print $1}' | xxd -ps -r) | sha1sum
fbdb1d1b18aa6c08324b7d64b71fb76370690e1d  -

Ta da!

forest
  • 66,706
  • 20
  • 212
  • 270