3

I have two strings (key and data) which are in hex string format, and I'd like to take the HMAC of them. The strings are:

$data = "0000000002ccbe80";
$key  = "48656c6c6f21deadbeef";

I want to produce the equivalent of the javascript jsSHA function where the strings are treated as hex strings. This demo http://caligatio.github.io/jsSHA/ lets you specify that the key and data are HEX strings.

However, when I use hmac_sha1_hex($data, $key) in Perl, the strings are treated as text. I get this output for the hmac_sha1_hex:

775083be8f8c94baea8d12a5038d191cab3759ac

How do I produce the same output as the jsSHA demo where both inputs are treated as hex and the output is also in hex? I want this output:

f2ea4899a8582c21610085988c54645fd7193393
Vijay Boyapati
  • 7,632
  • 7
  • 31
  • 48
  • Where are you getting `hmac_sha1_hex` from? – Borodin Aug 27 '14 at 22:37
  • Apologies Borodin, I'm not quite sure I understand your question: I'm using Digest::SHA qw(hmac_sha1_hex) to compute the hmac of the key and data. But it seems to treat the inputs as text and I want them treated as hex, if that makes sense. – Vijay Boyapati Aug 27 '14 at 22:50
  • 1
    I didn't realise there was HMAC functionality written into `Digest::SHA`. I've added yet another solution to show how that works. But the key to your question is the use of `pack` to convert hex strings to binary. – Borodin Aug 27 '14 at 23:12
  • FYI, your answer helped me answer my other question: http://stackoverflow.com/questions/25534193/google-authenticator-implementation-in-perl/ – Vijay Boyapati Aug 27 '14 at 23:40

1 Answers1

6

I don't know which module you are using to provide hmac_sha1_hex, but instead I recommend the Digest family of modules. If you use Digest::HMAC in combination with Digest::SHA1 you can calculate a SHA1 HMAC, and the translation from a hex string to binary is done with pack.

This code parcels the whole thing up into a subroutine for you.

use strict;
use warnings;

use Digest::HMAC;
use Digest::SHA1;

my $data = '0000000002ccbe80';
my $key  = '48656c6c6f21deadbeef';

print hmac_sha1_hex_string($key, $data), "\n";

sub  hmac_sha1_hex_string {
   my ($key, $data) = map pack('H*', $_), @_;
   my $hmac = Digest::HMAC->new($key, 'Digest::SHA1');
   $hmac->add($data);
   $hmac->hexdigest;
}

output

f2ea4899a8582c21610085988c54645fd7193393

Update

I overlooked that there is also a Digest::HMAC_SHA1 module that does all this for you and makes the code simpler still.

Like this

use strict;
use warnings;

use Digest::HMAC_SHA1 qw/ hmac_sha1_hex /;

my $data = '0000000002ccbe80';
my $key  = '48656c6c6f21deadbeef';

print hmac_sha1_hex_string($key, $data), "\n";

sub  hmac_sha1_hex_string {
   my ($key, $data) = map pack('H*', $_), @_;
   hmac_sha1_hex($data, $key);
}

The output is identical to that of the previous code.


Update

Just to complete the set, this is how to do it using the procedural interface of Digest::HMAC instead of the object-oriented style.

use strict;
use warnings;

use Digest::HMAC qw/ hmac_hex /;
use Digest::SHA1 qw/ sha1 /;

my $data = '0000000002ccbe80';
my $key  = '48656c6c6f21deadbeef';

print hmac_sha1_hex_string($key, $data), "\n";

sub  hmac_sha1_hex_string {
   my ($key, $data) = map pack('H*', $_), @_;
   hmac_hex($data, $key, \&sha1);
}

Update

I've just read your answer to my comment. I didn't realise there was HMAC functionality written into Digest::SHA. Using that module and its hmac_sha1_hex call, all there is left is to perform the pack calls on the hex strings.

use strict;
use warnings;

use Digest::SHA qw/ hmac_sha1_hex /;

my $data = '0000000002ccbe80';
my $key  = '48656c6c6f21deadbeef';

print hmac_sha1_hex_string($key, $data), "\n";

sub  hmac_sha1_hex_string {
   my ($key, $data) = map pack('H*', $_), @_;
   hmac_sha1_hex($data, $key);
}
Community
  • 1
  • 1
Borodin
  • 126,100
  • 9
  • 70
  • 144