Thursday, July 05, 2012

Using openssl to generate HMAC using a binary key

If you want to do a quick command-line generation of a HMAC, then the openssl command is useful.
For example:
# echo -n 'value' | openssl dgst -sha1 -hmac 'key'
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -md5 -hmac 'key'
(stdin)= 01433efd5f16327ea4b31144572c67f6

...or alternatively...
# echo -n 'value' | openssl sha1 -hmac 'key'
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl md5 -hmac 'key'
(stdin)= 01433efd5f16327ea4b31144572c67f6

Reference:
http://stackoverflow.com/questions/7285059/hmac-sha1-in-bash

BUT, note in the above commands, the 'value' and 'key' are ascii strings. The above syntax is problematic if you want to specify a Binary value for the key, which does not correspond to printable characters.

This had been a problem reported in the past:
http://www.mail-archive.com/openssl-users@openssl.org/msg49098.html
http://www.mail-archive.com/openssl-users@openssl.org/msg49100.html

But I can report here, that certainly with openssl v1.0.0, the following method allows you to specify a binary key, by passing it as a string of hex values.

To demonstate the point, let's get the hex string equivalent of the three character acsii string 'key', so that we can use the same hashes as in the examples above. To do this, I use utility 'xxd' which does a hexdump. (For further information on 'xdd' see my previous blog posts.)

# echo -n 'key' | xxd -p
6b6579

Ok, so the hex-string "6b6579" corresponds to ascii string "key".

So after reading up the man page for 'openssl dgst', we try a further alternate form of the command, like this:

# echo -n 'value' | openssl dgst -sha1 -mac HMAC -macopt key:key
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -sha1 -mac HMAC -macopt hexkey:6b6579
(stdin)= 57443a4c052350a44638835d64fd66822f813319

# echo -n 'value' | openssl dgst -md5 -mac HMAC -macopt key:key
(stdin)= 01433efd5f16327ea4b31144572c67f6

# echo -n 'value' | openssl dgst -md5 -mac HMAC -macopt hexkey:6B6579
(stdin)= 01433efd5f16327ea4b31144572c67f6

Note the use of the '-macopt hexkey:string' option which allows you to specify the key in hexadecimal (two hex digits per byte).

Nice! So now we can do something like this:

# echo -n '55f80d132e8b68eb' | xxd -r -p | openssl dgst -sha1 -mac HMAC -macopt key:645a487340f4c7f0
(stdin)= 2f0928b4bb365b4a590d84960a7cd04fd2d80221

I hope to show a practical use of the above in a future blog post!

Finally, I will just confirm some details of the system that gave the above output:

# rpm -qa | grep openssl
openssl-1.0.0-20.el6_2.5.x86_64

# cat /etc/redhat-release
CentOS release 6.2 (Final)

By the way, if your wondering about the '(stdin)= ' that openssl is outputing, then see my previous blog post on this subject.

3 comments:

PuZZleDucK said...

Woot! You're a life saver Nigel!

I've been struggling with this for ages, I was using the flags:
-sha1 -macopt hexkey:FFFF -hmac ''

I was triggering hmac with the "-hmac ''" flag, but obviously I needed to drop the empty-key hmac entry and use "-mac HMAC" instead... thanks again!!

joefitz said...

On OSX I'm using OpenSSL 0.9.8zh 14 Jan 2016 and it is giving me this error message:

unknown option '-mac'

seems it only has -hmac... not sure how I can use binary keys.

joefitz said...

My mistake was that openssl is no longer symbolically linking the files in homebrew and so I was using the system version of openssl instead of the newer 1.0.2 version I thought I had installed. When I explicitly reference the homebrew version your examples work great.