5 # ABSTRACT: Minimalist PBKDF2 (RFC 2898) with HMAC-SHA1 or HMAC-SHA2
 
   7 our $VERSION = '0.005';
 
  10 use Exporter 5.57 qw/import/;
 
  12 our @EXPORT_OK = qw/derive derive_hex verify verify_hex hmac digest_fcn/;
 
  14 my ( $BACKEND, $LOAD_ERR );
 
  15 for my $mod (qw/Digest::SHA Digest::SHA::PurePerl/) {
 
  16     $BACKEND = $mod, last if eval "require $mod; 1";
 
  19 die $LOAD_ERR if !$BACKEND;
 
  21 #--------------------------------------------------------------------------#
 
  22 # constants and lookup tables
 
  23 #--------------------------------------------------------------------------#
 
  25 # function coderef placeholder, block size in bytes, digest size in bytes
 
  27     'SHA-1'   => [ undef, 64,  20 ],
 
  28     'SHA-224' => [ undef, 64,  28 ],
 
  29     'SHA-256' => [ undef, 64,  32 ],
 
  30     'SHA-384' => [ undef, 128, 48 ],
 
  31     'SHA-512' => [ undef, 128, 64 ],
 
  34 for my $type ( keys %DIGEST_TYPES ) {
 
  36     ( my $name = lc $type ) =~ s{-}{};
 
  37     $DIGEST_TYPES{$type}[0] = \&{"$BACKEND\::$name"};
 
  40 my %INT = map { $_ => pack( "N", $_ ) } 1 .. 16;
 
  42 #--------------------------------------------------------------------------#
 
  44 #--------------------------------------------------------------------------#
 
  48 #pod     $dk = derive( $type, $password, $salt, $iterations, $dk_length )
 
  50 #pod The C<derive> function outputs a binary string with the derived key.
 
  51 #pod The first argument indicates the digest function to use.  It must be one
 
  52 #pod of: SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512.
 
  54 #pod If a password or salt are not provided, they default to the empty string, so
 
  55 #pod don't do that!  L<RFC 2898
 
  56 #pod recommends|https://tools.ietf.org/html/rfc2898#section-4.1> a random salt of at
 
  57 #pod least 8 octets.  If you need a cryptographically strong salt, consider
 
  58 #pod L<Crypt::URandom>.
 
  60 #pod The password and salt should encoded as octet strings. If not (i.e. if
 
  61 #pod Perl's internal 'UTF8' flag is on), then an exception will be thrown.
 
  63 #pod The number of iterations defaults to 1000 if not provided.  If the derived
 
  64 #pod key length is not provided, it defaults to the output size of the digest
 
  70     my ( $type, $passwd, $salt, $iterations, $dk_length ) = @_;
 
  72     my ( $digester, $block_size, $digest_length ) = digest_fcn($type);
 
  74     $passwd = '' unless defined $passwd;
 
  75     $salt   = '' unless defined $salt;
 
  77     $dk_length  ||= $digest_length;
 
  79     # we insist on octet strings for password and salt
 
  80     Carp::croak("password must be an octet string, not a character string")
 
  81       if utf8::is_utf8($passwd);
 
  82     Carp::croak("salt must be an octet string, not a character string")
 
  83       if utf8::is_utf8($salt);
 
  85     my $key = ( length($passwd) > $block_size ) ? $digester->($passwd) : $passwd;
 
  86     my $passes = int( $dk_length / $digest_length );
 
  87     $passes++ if $dk_length % $digest_length; # need part of an extra pass
 
  90     for my $i ( 1 .. $passes ) {
 
  91         $INT{$i} ||= pack( "N", $i );
 
  92         my $digest = my $result =
 
  93           "" . hmac( $salt . $INT{$i}, $key, $digester, $block_size );
 
  94         for my $iter ( 2 .. $iterations ) {
 
  95             $digest = hmac( $digest, $key, $digester, $block_size );
 
 101     return substr( $dk, 0, $dk_length );
 
 104 #pod =func derive_hex
 
 106 #pod Works just like L</derive> but outputs a hex string.
 
 110 sub derive_hex { unpack( "H*", &derive ) }
 
 114 #pod     $bool = verify( $dk, $type, $password, $salt, $iterations, $dk_length );
 
 116 #pod The C<verify> function checks that a given derived key (in binary form) matches
 
 117 #pod the password and other parameters provided using a constant-time comparison
 
 120 #pod The first parameter is the derived key to check.  The remaining parameters
 
 121 #pod are the same as for L</derive>.
 
 126     my ( $dk1, @derive_args ) = @_;
 
 128     my $dk2 = derive(@derive_args);
 
 130     # shortcut if input dk is the wrong length entirely; this is not
 
 131     # constant time, but this doesn't really give much away as
 
 132     # the keys are of different types anyway
 
 134     return unless length($dk1) == length($dk2);
 
 136     # if lengths match, do constant time comparison to avoid timing attacks
 
 138     for my $i ( 0 .. length($dk1) - 1 ) {
 
 139         $match &= ( substr( $dk1, $i, 1 ) eq substr( $dk2, $i, 1 ) ) ? 1 : 0;
 
 145 #pod =func verify_hex
 
 147 #pod Works just like L</verify> but the derived key must be a hex string (without a
 
 153     my $dk = pack( "H*", shift );
 
 154     return verify( $dk, @_ );
 
 157 #pod =func digest_fcn
 
 159 #pod     ($fcn, $block_size, $digest_length) = digest_fcn('SHA-1');
 
 160 #pod     $digest = $fcn->($data);
 
 162 #pod This function is used internally by PBKDF2::Tiny, but made available in case
 
 163 #pod it's useful to someone.
 
 165 #pod Given one of the valid digest types, it returns a function reference that
 
 166 #pod digests a string of data. It also returns block size and digest length for that
 
 174     Carp::croak("Digest function '$type' not supported")
 
 175       unless exists $DIGEST_TYPES{$type};
 
 177     return @{ $DIGEST_TYPES{$type} };
 
 182 #pod     $key = $digest_fcn->($key) if length($key) > $block_size;
 
 183 #pod     $hmac = hmac( $data, $key, $digest_fcn, $block_size );
 
 185 #pod This function is used internally by PBKDF2::Tiny, but made available in case
 
 186 #pod it's useful to someone.
 
 188 #pod The first two arguments are the data and key inputs to the HMAC function.  Both
 
 189 #pod should be encoded as octet strings, as underlying HMAC/digest functions may
 
 190 #pod croak or may give unexpected results if Perl's internal UTF-8 flag is on.
 
 192 #pod B<Note>: if the key is longer than the digest block size, it must be
 
 193 #pod preprocessed using the digesting function.
 
 195 #pod The third and fourth arguments must be a digesting code reference (from
 
 196 #pod L</digest_fcn>) and block size.
 
 200 # hmac function adapted from Digest::HMAC by Graham Barr and Gisle Aas.
 
 201 # Compared to that implementation, this *requires* a preprocessed
 
 202 # key and block size, which makes iterative hmac slightly more efficient.
 
 204     my ( $data, $key, $digest_func, $block_size ) = @_;
 
 206     my $k_ipad = $key ^ ( chr(0x36) x $block_size );
 
 207     my $k_opad = $key ^ ( chr(0x5c) x $block_size );
 
 209     &$digest_func( $k_opad, &$digest_func( $k_ipad, $data ) );
 
 215 # vim: ts=4 sts=4 sw=4 et:
 
 225 PBKDF2::Tiny - Minimalist PBKDF2 (RFC 2898) with HMAC-SHA1 or HMAC-SHA2
 
 233     use PBKDF2::Tiny qw/derive verify/;
 
 235     my $dk = derive( 'SHA-1', $pass, $salt, $iters );
 
 237     if ( verify( $dk, 'SHA-1', $pass, $salt, $iters ) ) {
 
 238         # password is correct
 
 243 This module provides an L<RFC 2898|https://tools.ietf.org/html/rfc2898>
 
 244 compliant PBKDF2 implementation using HMAC-SHA1 or HMAC-SHA2 in under 100 lines
 
 245 of code.  If you are using Perl 5.10 or later, it uses only core Perl modules.
 
 246 If you are on an earlier version of Perl, you need L<Digest::SHA> or
 
 247 L<Digest::SHA::PurePerl>.
 
 249 All documented functions are optionally exported.  No functions are exported by default.
 
 255     $dk = derive( $type, $password, $salt, $iterations, $dk_length )
 
 257 The C<derive> function outputs a binary string with the derived key.
 
 258 The first argument indicates the digest function to use.  It must be one
 
 259 of: SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512.
 
 261 If a password or salt are not provided, they default to the empty string, so
 
 262 don't do that!  L<RFC 2898
 
 263 recommends|https://tools.ietf.org/html/rfc2898#section-4.1> a random salt of at
 
 264 least 8 octets.  If you need a cryptographically strong salt, consider
 
 267 The password and salt should encoded as octet strings. If not (i.e. if
 
 268 Perl's internal 'UTF8' flag is on), then an exception will be thrown.
 
 270 The number of iterations defaults to 1000 if not provided.  If the derived
 
 271 key length is not provided, it defaults to the output size of the digest
 
 276 Works just like L</derive> but outputs a hex string.
 
 280     $bool = verify( $dk, $type, $password, $salt, $iterations, $dk_length );
 
 282 The C<verify> function checks that a given derived key (in binary form) matches
 
 283 the password and other parameters provided using a constant-time comparison
 
 286 The first parameter is the derived key to check.  The remaining parameters
 
 287 are the same as for L</derive>.
 
 291 Works just like L</verify> but the derived key must be a hex string (without a
 
 296     ($fcn, $block_size, $digest_length) = digest_fcn('SHA-1');
 
 297     $digest = $fcn->($data);
 
 299 This function is used internally by PBKDF2::Tiny, but made available in case
 
 300 it's useful to someone.
 
 302 Given one of the valid digest types, it returns a function reference that
 
 303 digests a string of data. It also returns block size and digest length for that
 
 308     $key = $digest_fcn->($key) if length($key) > $block_size;
 
 309     $hmac = hmac( $data, $key, $digest_fcn, $block_size );
 
 311 This function is used internally by PBKDF2::Tiny, but made available in case
 
 312 it's useful to someone.
 
 314 The first two arguments are the data and key inputs to the HMAC function.  Both
 
 315 should be encoded as octet strings, as underlying HMAC/digest functions may
 
 316 croak or may give unexpected results if Perl's internal UTF-8 flag is on.
 
 318 B<Note>: if the key is longer than the digest block size, it must be
 
 319 preprocessed using the digesting function.
 
 321 The third and fourth arguments must be a digesting code reference (from
 
 322 L</digest_fcn>) and block size.
 
 345 =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
 
 349 =head2 Bugs / Feature Requests
 
 351 Please report any bugs or feature requests through the issue tracker
 
 352 at L<https://github.com/dagolden/PBKDF2-Tiny/issues>.
 
 353 You will be notified automatically of any progress on your issue.
 
 357 This is open source software.  The code repository is available for
 
 358 public review and contribution under the terms of the license.
 
 360 L<https://github.com/dagolden/PBKDF2-Tiny>
 
 362   git clone https://github.com/dagolden/PBKDF2-Tiny.git
 
 366 David Golden <dagolden@cpan.org>
 
 368 =head1 COPYRIGHT AND LICENSE
 
 370 This software is Copyright (c) 2014 by David Golden.
 
 372 This is free software, licensed under:
 
 374   The Apache License, Version 2.0, January 2004