Here is a very simple Perl script that does PBKDF2-HMAC-* functions. These functions (hmac_pad, pp_pbkdf2 and pp_pbkdf2_hex) have been incorporated into the pass_gen.pl script in JtR main runtime (bleeding edge). I simply put these functions here to publish them for anyone to be able to find, and to be indexed into search engines. This code is pretty flexible, allowing the 'flawed' (IMHO) HMAC function with about any crypto algorithm to be used in the PBKDF2 key stretching function.

Written by Jim Fougeron, Sept, 2014 and hereby placed in public domain.

#!/usr/bin/perl -w
 
# pp_pbkdf2.pl  this is a SUPER simple pure Perl pbkdf2-hmac-*crypt implementation.
#
# Copyright (C) Sept 2014, Jim Fougeron.
# This code is hereby released into public domain as long as this Copyright statement is maintained.
# This software may be modified, redistributed, and used for any purpose, in source and binary forms,
# with or without modification, as long as this copyright statement is maintained.
 
# test vectors.
# ./pp_pbkdf2.pl password CKrgSLbQECwE 10000 sha256 32  output: 41dbfab2f658346b325c7a7f29ef1735e1c07d40370157a58ddbfa9ec5108dd4
# ./pp_pbkdf2.pl password kIIWWNB 24000 sha512 68       output: 50d71996d584cce98ea14ffeaf12adc447173b8c333b5c6191ab97a101d2c3b56216ed892e28fcc78d84f39a0d33b1eb5ae2e36cb46ec30211366f0af270f6b405ff26c8
# ./pp_pbkdf2.pl password BadAlgo 4800 md5 40           output: df6495d5493ff96802a6b557c814d32a3f8917687d9dcd2be6b6b3bcaa2d09f6cb8e81b413c96454
#
# algo can be any of these:   md4 md5 sha1 sha224 sha256 sha384 sha512 tiger haval256.  Others could easily be used.
# the only 'issue' is in computing the width of the HMAC data.
#
# NOTE, this code does not perform the optimization of doing the first limb hash of ipad and opad, and re-using those results.
# I have not found an optimal way to do that in perl, like I have done in the JtR code base.
#
use POSIX;
use strict;
use Digest::SHA qw(sha256 sha1 sha224 sha384 sha512);
use Digest::MD5 qw(md5);
use Digest::MD4 qw(md4);
 
sub tiger {
	require Digest::Tiger;
	return Digest::Tiger::hash($_[0]);
}
sub haval256 {
	require Digest::Haval256;
	my $hash = new Digest::Haval256;
	$hash->add($_[0]);
	return $hash->digest;
}
 
sub hmac_pad {
	my ($pass, $ch, $algo) = @_;
	my $pad;  # ipad or opad, depending upon ch passed in.
	no strict 'refs';
	$pad = &$algo("a");
	use strict;
	my $len = (length($pad)>= 48) ? 128 : 64; # I am not 100% sure this is valid for ALL algos.
	$pad = $ch x $len;
	if (length($pass) > $len) { no strict 'refs'; $pass = &$algo($pass); use strict; }
	$pad ^= $pass;
	return $pad;
}
sub pp_pbkdf2 {
	my ($pass, $orig_salt, $iter, $algo, $bytes) = @_;
	my $ipad = hmac_pad($pass, '6', $algo);  # 6 is \x36 for an ipad
	my $opad = hmac_pad($pass, '\\', $algo); # \ is \x5c for an opad
	my $final_out=""; my $i=1;
	while (length($final_out) < $bytes) {
		my $salt = $orig_salt . chr($i>>24); $salt .= chr(($i>>16)&0xFF); $salt .= chr(($i>>8)&0xFF); $salt .= chr($i&0xFF);
		$i += 1;
		no strict 'refs';
		$salt = &$algo($opad.&$algo($ipad.$salt));
		use strict;
		my $out = $salt;
		for (my $i = 1; $i < $iter; $i += 1) {
			no strict 'refs';
			$salt = &$algo($opad.&$algo($ipad.$salt));
			use strict;
			$out ^= $salt;
		}
		if (length($final_out)+length($out) > $bytes) {
			$out = substr($out, 0, $bytes-length($final_out));
		}
		$final_out .= $out;
	}
	return $final_out;
}
sub pp_pbkdf2_hex {
	my ($pass, $salt, $iter, $algo, $bytes) = @_;
	return unpack("H*", pp_pbkdf2($pass,$salt,$iter,$algo,$bytes));
}
 
if (!defined($ARGV[4])) { print "Usage pp_pbkdf2.pl pass salt count algo bytes_wanted\n"; exit (1); }
print pp_pbkdf2_hex($ARGV[0],$ARGV[1],$ARGV[2],$ARGV[3],$ARGV[4]) . "\n";
john/pp_PBKDF2.txt · Last modified: 2014/09/04 19:26 by JimF
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate to DokuWiki Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki Powered by OpenVZ Powered by Openwall GNU/*/Linux