James Stanley

Perl's Digest::SHA::hmac_sha256_base64 is wrong

Wed 6 July 2016

I spent nearly 2 hours today struggling to authenticate with an API that uses base64 SHA256 HMAC's, only to find that the hmac_sha256_base64 implementation appears to be wrong.

For example:

#!/usr/bin/perl

use strict; use warnings;

use MIME::Base64 qw(encode_base64); use Digest::SHA qw(hmac_sha256 hmac_sha256_base64);

my $key = 'foo'; my $data = 'hello world';

print "hmac_sha256_base64: " . hmac_sha256_base64($data, $key) . "\n"; print "encode_base64(hmac_sha256): " . encode_base64(hmac_sha256($data, $key)) . "\n";

The output is:

hmac_sha256_base64:         jvVS287gOBboArZDFbSGoJkwJBVkIGt4nprJe1BOzoo
encode_base64(hmac_sha256): jvVS287gOBboArZDFbSGoJkwJBVkIGt4nprJe1BOzoo=

Using hmac_sha256_base64 is (nearly?) always the wrong thing to do, just use encode_base64(hmac_sha256()) instead. Also, note that encode_base64 leaves a spurious trailing endline which you'll have to remove in anything more than a toy example.

I wasn't able to find any information about this problem online (until after I knew what the problem was - it is documented in the POD if you know what to look for), so I'm posting this in case it helps someone.

I submitted a bug report before I read the POD, but it will presumably not get fixed.

If you like my blog, please consider subscribing to the RSS feed or the mailing list:

James Stanley - james@incoherency.co.uk | jesblogfnk2boep4.onion | [rss]