#-----------------------------------------------#
#	POC HMAC SHA 1 conforme RFC 2202	#
#	jve - 2008				#
#-----------------------------------------------#
#! /usr/bin/perl -w

use strict;
use Digest::SHA1 qw(sha1);


my ($K, $Ksha1, $text, $Hsha1); # 'K' the key, 'text' the data to compute the hmac on, 'H' the HMAC
my $SHA1_blocksize = 64; # SHA1 travaille sur des blocs de 512 bits

if ($ARGV[0] eq '-f')
{
	open KEYFILE, $ARGV[1] || die("Could not open key file!");
	print read(KEYFILE, $K, $ARGV[2])." bytes key read\n";
	chomp $K;
	close KEYFILE;

	open DATAFILE, $ARGV[3]|| die("Could not open data file!");
	print read(DATAFILE, $text, $ARGV[4])." bytes data read\n";
	chomp $text;
	close DATAFILE;
}
else
{
	if ($ARGV[0] eq '-h')
	{
		print "\n\t#-- POC HMAC SHA 1 conforme RFC 2202 --#\n\n",
			"\tUsage:\tperl hmac0.2.pl -f <binary key file> <key length in bytes> <data file> <data length in bytes>\n",
			"\tor\n\t\tperl hmac0.2.pl {direct input mode}\n",
			"\t\nnote : the limit size for files is 2^16 bytes\n";
		exit 0;
	}
	else
	{
		print "saisir clef ascii = ";
		$K = <STDIN>;
		chomp $K;

		print "saisir data ascii = ";
		$text = <STDIN>;
		chomp $text;
	}
}

# Si la taille de la clé excède la taille d'un bloc SHA1 (64 octets),
# la clé est remplacée par un hash SHA1 de la clé
$Ksha1 = $K;
$Ksha1 = sha1($K) if length($K) > $SHA1_blocksize;


# HMAC(m) = sha1((key xor ('0x5c' * SHA1_blocksize)) || sha1((key xor ('0x36' * SHA1_blocksize)) || text))
# avec || représentant la concatenation

# ipad = K xor '0x363636....3636'
my $K_xor_IPAD =  $Ksha1 ^ (chr(0x36) x $SHA1_blocksize);

# opad = K xor '0x5c5c5c....5c5c' 
my $K_xor_OPAD = $Ksha1 ^ (chr(0x5c) x $SHA1_blocksize);

# Et pour finir...
$Hsha1 = sha1($K_xor_OPAD.sha1($K_xor_IPAD.$text));

# affichage de  l'empreinte en hexadecimal
print "HMAC SHA1==>\t".unpack("H*", $Hsha1)."\n";

