Crypt-PBKDF2-Lite

Lamawiki の htpasswd MD5 crypt 形式から乗り換えようと、 RFC 2898 の Password-Based Key Derivation Function 2 (PBKDF2) を実装した CPAN モジュール Crypt-PBKDF2 を調べてみたら Moose ウェアになっていて使える場所が限られてしまうので、 レガシーなモジュールを組んでみました。 RFC 6070 のテスト・ベクタで検証済みです。

pbkdf2 関数を定義してあります。

一応、 最低限のパッケージの体裁をしていますが、 pbkdf2 関数自体は 1 つの関数にまとまっており、 短い上に依存関係がなく利用できるので、 コピー & ペーストして使うのが良いと思います。 pbkdf2 関数には、 HMAC 関数へのリファレンス、 パスワード、 ソルト、 繰り返し回数、 出力オクテット長さを引数に与えて呼び出します。 結果はオクテットで返ってきます。

package Crypt::PBKDF2::Lite;
use strict;
use warnings;
use Exporter ();

our $VERSION = '0.01';

our @ISA = qw(Exporter);
our @EXPORT_OK = qw(pbkdf2);

sub pbkdf2 {
    my($prf, $password, $salt, $c, $dklen) = @_;
    my $dk = q();
    my $i = 0;
    while ($dklen > 0) {
        my $u = $prf->($salt . pack('N', ++$i), $password);
        my $t = $u;
        for (2 .. $c) {
            $u = $prf->($u, $password);
            $t ^= $u;
        }
        my $n = $dklen < (length $t) ? $dklen : (length $t);
        $dk .= substr $t, 0, $n;
        $dklen -= $n;
    }
    return $dk;
}

1;

__END__

=head1 VERSION

0.01

=head1 NAME

Crypt::PBKDF2::Lite - Password-Based Key Derivation Function 2

=head1 SYNOPSIS

    use Crypt::PBKDF2::Lite qw(pbkdf2);
    use Digest::SHA qw(hmac_sha1);
    
    # RFC 6070 PKCS #5: Password-Based Key Derivation Function 2 (PBKDF2)
    # Test Vectors
    my $octets = pbkdf2(\&hmac_sha1, "password", "salt", 4096, 20);
    print q(), (join q( ), map { unpack('H2', $_) } split //, $octets), "\n";
    #=> 4b 00 79 01 b7 65 48 9a be ad 49 d9 26 f7 21 d0 65 a4 29 c1

=head1 SEE ALSO

RFC 2898, PKCS#5 version 2.0: L<https://www.ietf.org/rfc/rfc2898.txt>

=head1 AUTHOR

MIZUTANI Tociyuki C<< <tociyuki@gmail.com> >>.

=head1 LICENSE AND COPYRIGHT

Copyright (c) 2015, MIZUTANI Tociyuki.
All rights reserved.

This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

=cut