Crypt-Passphrase-PBKDF2
view release on metacpan or search on metacpan
Revision history for Crypt-Passphrase-PBKDF2
0.004 2025-09-06 12:46:33+02:00 Europe/Brussels
- Fix needs_rehash tests
- Improve documentation
0.003 2025-08-27 10:31:49+02:00 Europe/Brussels
- Fix crypt_types() subroutine name
0.002 2023-02-27 22:16:22+01:00 Europe/Amsterdam
- Increase default iterations to 100000
- Make needs_rehash method stricter
0.001 2021-03-11 22:04:47+01:00 Europe/Amsterdam
Initial release to an unsuspecting world
lib/Crypt/Passphrase/PBKDF2.pm view on Meta::CPAN
sha384 => 'SHA-384',
sha512 => 'SHA-512',
);
sub new {
my ($class, %args) = @_;
my $type = $args{type} || 'sha256';
croak "Hash type $type not supported" unless exists $param_for_type{$type};
return bless {
salt_size => $args{salt_size} || 16,
iterations => $args{iterations} || 100_000,
type => $type,
}, $class;
}
sub ab64_encode {
my $input = shift;
return encode_base64($input, '') =~ tr/+=/./dr;
}
sub ab64_decode {
my $input = shift;
return decode_base64($input =~ tr/./+/r);
}
sub hash_password {
my ($self, $password) = @_;
my $salt = $self->random_bytes($self->{salt_size});
my $hash = derive($param_for_type{ $self->{type} }, $password, $salt, $self->{iterations});
return join '$', "\$pbkdf2-$self->{type}", $self->{iterations}, ab64_encode($salt), ab64_encode($hash);
}
my $decode_regex = qr/ \A \$ pbkdf2- (\w+) \$ (\d+) \$ ([^\$]+) \$ ([^\$]*) \z /x;
sub needs_rehash {
my ($self, $hash) = @_;
my ($type, $iterations, $salt64, $hash64) = $hash =~ $decode_regex or return 1;
return 1 if $type ne $self->{type} or $iterations != $self->{iterations};
return 1 if length ab64_decode($salt64) != $self->{salt_size};
return;
}
sub crypt_subtypes {
return map { "pbkdf2-$_" } keys %param_for_type;
}
sub verify_password {
my ($class, $password, $hash) = @_;
my ($type, $iterations, $salt64, $hash64) = $hash =~ $decode_regex or return 0;
return 0 unless exists $param_for_type{$type};
return verify(ab64_decode($hash64), $param_for_type{$type}, $password, ab64_decode($salt64), $iterations);
}
1;
# ABSTRACT: A PBKDF2 encoder for Crypt::Passphrase
__END__
=pod
lib/Crypt/Passphrase/PBKDF2.pm view on Meta::CPAN
=head1 VERSION
version 0.004
=head1 SYNOPSIS
my $passphrase = Crypt::Passphrase->new(
encoder => {
module => 'PBKDF2',
type => 'sha256',
iterations => 128_000,
},
);
=head1 DESCRIPTION
This class implements a PBKDF2 encoder for Crypt::Passphrase. It allows for any SHA-1 or SHA-2 hash, and any number of iterations.
=head2 Configuration
It accepts the following arguments:
=over 4
=item * type
This can be any of C<sha1>, C<sha224>, C<sha256> (default), C<sha384> or C<sha512>.
=item * iterations
This will be the iteration count, defaulting to C<100000>.
=item * salt_size
The size of the salt. This defaults to 16 bytes, which should be more than enough for any use-case.
=back
=head2 COMPATIBILITY
use warnings;
use Test::More;
use Crypt::Passphrase;
my $passphrase = Crypt::Passphrase->new(
encoder => {
module => 'PBKDF2',
type => 'sha256',
iterations => 6400,
},
);
my $password = 'password';
my $salt = "\0" x 16;
my $hash1 = $passphrase->hash_password($password);
ok($passphrase->verify_password($password, $hash1), 'Self-generated password validates');
ok(!$passphrase->needs_rehash($hash1), 'Self-generated password doesn\'t need to be regenerated');
( run in 0.855 second using v1.01-cache-2.11-cpan-96521ef73a4 )