1=head1 NAME 2 3Crypt::Eksblowfish::Bcrypt - Blowfish-based Unix crypt() password hash 4 5=head1 SYNOPSIS 6 7 use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash); 8 9 $hash = bcrypt_hash({ 10 key_nul => 1, 11 cost => 8, 12 salt => $salt, 13 }, $password); 14 15 use Crypt::Eksblowfish::Bcrypt qw(en_base64 de_base64); 16 17 $text = en_base64($octets); 18 $octets = de_base64($text); 19 20 use Crypt::Eksblowfish::Bcrypt qw(bcrypt); 21 22 $hashed_password = bcrypt($password, $settings); 23 24=head1 DESCRIPTION 25 26This module implements the Blowfish-based Unix crypt() password hashing 27algorithm, known as "bcrypt". This hash uses a variant of Blowfish, 28known as "Eksblowfish", modified to have particularly expensive key 29scheduling. Eksblowfish and bcrypt were devised by Niels Provos and 30David Mazieres for OpenBSD. The design is described in a paper at 31L<http://www.usenix.org/events/usenix99/provos.html>. 32 33=cut 34 35package Crypt::Eksblowfish::Bcrypt; 36 37{ use 5.006; } 38use warnings; 39use strict; 40 41use Carp qw(croak); 42use Crypt::Eksblowfish 0.005; 43use MIME::Base64 2.21 qw(encode_base64 decode_base64); 44 45our $VERSION = "0.009"; 46 47use parent "Exporter"; 48our @EXPORT_OK = qw(bcrypt_hash en_base64 de_base64 bcrypt); 49 50=head1 FUNCTIONS 51 52=over 53 54=item bcrypt_hash(SETTINGS, PASSWORD) 55 56Hashes PASSWORD according to the supplied SETTINGS, and returns the 5723-octet hash. SETTINGS must be a reference to a hash, with these keys: 58 59=over 60 61=item B<key_nul> 62 63Truth value: whether to append a NUL to the password before using it as a key. 64The algorithm as originally devised does not do this, but it was later 65modified to do it. The version that does append NUL is to be preferred; 66not doing so is supported only for backward compatibility. 67 68=item B<cost> 69 70Non-negative integer controlling the cost of the hash function. 71The number of operations is proportional to 2^cost. 72 73=item B<salt> 74 75Exactly sixteen octets of salt. 76 77=back 78 79=cut 80 81sub bcrypt_hash($$) { 82 my($settings, $password) = @_; 83 $password .= "\0" if $settings->{key_nul} || $password eq ""; 84 my $cipher = Crypt::Eksblowfish->new($settings->{cost}, 85 $settings->{salt}, substr($password, 0, 72)); 86 my $hash = join("", map { 87 my $blk = $_; 88 for(my $i = 64; $i--; ) { 89 $blk = $cipher->encrypt($blk); 90 } 91 $blk; 92 } qw(OrpheanB eholderS cryDoubt)); 93 chop $hash; 94 return $hash; 95} 96 97=item en_base64(BYTES) 98 99Encodes the octet string textually using the form of base 64 that is 100conventionally used with bcrypt. 101 102=cut 103 104sub en_base64($) { 105 my($octets) = @_; 106 my $text = encode_base64($octets, ""); 107 $text =~ tr#A-Za-z0-9+/=#./A-Za-z0-9#d; 108 return $text; 109} 110 111=item de_base64(TEXT) 112 113Decodes an octet string that was textually encoded using the form of 114base 64 that is conventionally used with bcrypt. 115 116=cut 117 118sub de_base64($) { 119 my($text) = @_; 120 croak "bad base64 encoding" 121 unless $text =~ m#\A(?>(?:[./A-Za-z0-9]{4})*) 122 (?:|[./A-Za-z0-9]{2}[.CGKOSWaeimquy26]| 123 [./A-Za-z0-9][.Oeu])\z#x; 124 $text =~ tr#./A-Za-z0-9#A-Za-z0-9+/#; 125 $text .= "=" x (3 - (length($text) + 3) % 4); 126 return decode_base64($text); 127} 128 129=item bcrypt(PASSWORD, SETTINGS) 130 131This is a version of C<crypt> (see L<perlfunc/crypt>) that implements the 132bcrypt algorithm. It does not implement any other hashing algorithms, 133so if others are desired then it necessary to examine the algorithm 134prefix in SETTINGS and dispatch between more than one version of C<crypt>. 135 136SETTINGS must be a string which encodes the algorithm parameters, 137including salt. It must begin with "$2", optional "a", "$", two 138digits, "$", and 22 base 64 digits. The rest of the string is ignored. 139The presence of the optional "a" means that a NUL is to be appended 140to the password before it is used as a key. The two digits set the 141cost parameter. The 22 base 64 digits encode the salt. The function 142will C<die> if SETTINGS does not have this format. 143 144The PASSWORD is hashed according to the SETTINGS. The value returned 145is a string which encodes the algorithm parameters and the hash: the 146parameters are in the same format required in SETTINGS, and the hash is 147appended in the form of 31 base 64 digits. This result is suitable to 148be used as a SETTINGS string for input to this function: the hash part 149of the string is ignored on input. 150 151=cut 152 153sub bcrypt($$) { 154 my($password, $settings) = @_; 155 croak "bad bcrypt settings" 156 unless $settings =~ m#\A\$2(a?)\$([0-9]{2})\$ 157 ([./A-Za-z0-9]{22})#x; 158 my($key_nul, $cost, $salt_base64) = ($1, $2, $3); 159 my $hash = bcrypt_hash({ 160 key_nul => $key_nul, 161 cost => $cost, 162 salt => de_base64($salt_base64), 163 }, $password); 164 return "\$2${key_nul}\$${cost}\$${salt_base64}".en_base64($hash); 165} 166 167=back 168 169=head1 SEE ALSO 170 171L<Crypt::Eksblowfish>, 172L<http://www.usenix.org/events/usenix99/provos.html> 173 174=head1 AUTHOR 175 176Andrew Main (Zefram) <zefram@fysh.org> 177 178=head1 COPYRIGHT 179 180Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 181Andrew Main (Zefram) <zefram@fysh.org> 182 183=head1 LICENSE 184 185This module is free software; you can redistribute it and/or modify it 186under the same terms as Perl itself. 187 188=cut 189 1901; 191