Filename | /usr/lib/x86_64-linux-gnu/perl5/5.20/Crypt/Eksblowfish/Bcrypt.pm |
Statements | Executed 20 statements in 8.65ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 8.15ms | 9.72ms | BEGIN@42 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 21µs | 21µs | BEGIN@37 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 15µs | 49µs | BEGIN@43 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 10µs | 18µs | BEGIN@38 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 8µs | 33µs | BEGIN@41 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 7µs | 37µs | BEGIN@47 | Crypt::Eksblowfish::Bcrypt::
1 | 1 | 1 | 6µs | 17µs | BEGIN@39 | Crypt::Eksblowfish::Bcrypt::
0 | 0 | 0 | 0s | 0s | bcrypt | Crypt::Eksblowfish::Bcrypt::
0 | 0 | 0 | 0s | 0s | bcrypt_hash | Crypt::Eksblowfish::Bcrypt::
0 | 0 | 0 | 0s | 0s | de_base64 | Crypt::Eksblowfish::Bcrypt::
0 | 0 | 0 | 0s | 0s | en_base64 | Crypt::Eksblowfish::Bcrypt::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | =head1 NAME | ||||
2 | |||||
3 | Crypt::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 | |||||
26 | This module implements the Blowfish-based Unix crypt() password hashing | ||||
27 | algorithm, known as "bcrypt". This hash uses a variant of Blowfish, | ||||
28 | known as "Eksblowfish", modified to have particularly expensive key | ||||
29 | scheduling. Eksblowfish and bcrypt were devised by Niels Provos and | ||||
30 | David Mazieres for OpenBSD. The design is described in a paper at | ||||
31 | L<http://www.usenix.org/events/usenix99/provos.html>. | ||||
32 | |||||
33 | =cut | ||||
34 | |||||
35 | package Crypt::Eksblowfish::Bcrypt; | ||||
36 | |||||
37 | 3 | 51µs | 1 | 21µs | # spent 21µs within Crypt::Eksblowfish::Bcrypt::BEGIN@37 which was called:
# once (21µs+0s) by Koha::AuthUtils::BEGIN@21 at line 37 # spent 21µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@37 |
38 | 2 | 23µs | 2 | 26µs | # spent 18µs (10+8) within Crypt::Eksblowfish::Bcrypt::BEGIN@38 which was called:
# once (10µs+8µs) by Koha::AuthUtils::BEGIN@21 at line 38 # spent 18µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@38
# spent 8µs making 1 call to warnings::import |
39 | 2 | 26µs | 2 | 29µs | # spent 17µs (6+12) within Crypt::Eksblowfish::Bcrypt::BEGIN@39 which was called:
# once (6µs+12µs) by Koha::AuthUtils::BEGIN@21 at line 39 # spent 17µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@39
# spent 12µs making 1 call to strict::import |
40 | |||||
41 | 2 | 27µs | 2 | 58µs | # spent 33µs (8+25) within Crypt::Eksblowfish::Bcrypt::BEGIN@41 which was called:
# once (8µs+25µs) by Koha::AuthUtils::BEGIN@21 at line 41 # spent 33µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@41
# spent 25µs making 1 call to Exporter::import |
42 | 3 | 8.03ms | 2 | 9.73ms | # spent 9.72ms (8.15+1.56) within Crypt::Eksblowfish::Bcrypt::BEGIN@42 which was called:
# once (8.15ms+1.56ms) by Koha::AuthUtils::BEGIN@21 at line 42 # spent 9.72ms making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@42
# spent 9µs making 1 call to version::_VERSION |
43 | 3 | 48µs | 3 | 83µs | # spent 49µs (15+34) within Crypt::Eksblowfish::Bcrypt::BEGIN@43 which was called:
# once (15µs+34µs) by Koha::AuthUtils::BEGIN@21 at line 43 # spent 49µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@43
# spent 28µs making 1 call to Exporter::import
# spent 6µs making 1 call to version::_VERSION |
44 | |||||
45 | 1 | 300ns | our $VERSION = "0.009"; | ||
46 | |||||
47 | 2 | 436µs | 2 | 68µs | # spent 37µs (7+30) within Crypt::Eksblowfish::Bcrypt::BEGIN@47 which was called:
# once (7µs+30µs) by Koha::AuthUtils::BEGIN@21 at line 47 # spent 37µs making 1 call to Crypt::Eksblowfish::Bcrypt::BEGIN@47
# spent 30µs making 1 call to parent::import |
48 | 1 | 800ns | our @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 | |||||
56 | Hashes PASSWORD according to the supplied SETTINGS, and returns the | ||||
57 | 23-octet hash. SETTINGS must be a reference to a hash, with these keys: | ||||
58 | |||||
59 | =over | ||||
60 | |||||
61 | =item B<key_nul> | ||||
62 | |||||
63 | Truth value: whether to append a NUL to the password before using it as a key. | ||||
64 | The algorithm as originally devised does not do this, but it was later | ||||
65 | modified to do it. The version that does append NUL is to be preferred; | ||||
66 | not doing so is supported only for backward compatibility. | ||||
67 | |||||
68 | =item B<cost> | ||||
69 | |||||
70 | Non-negative integer controlling the cost of the hash function. | ||||
71 | The number of operations is proportional to 2^cost. | ||||
72 | |||||
73 | =item B<salt> | ||||
74 | |||||
75 | Exactly sixteen octets of salt. | ||||
76 | |||||
77 | =back | ||||
78 | |||||
79 | =cut | ||||
80 | |||||
81 | sub 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 | |||||
99 | Encodes the octet string textually using the form of base 64 that is | ||||
100 | conventionally used with bcrypt. | ||||
101 | |||||
102 | =cut | ||||
103 | |||||
104 | sub 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 | |||||
113 | Decodes an octet string that was textually encoded using the form of | ||||
114 | base 64 that is conventionally used with bcrypt. | ||||
115 | |||||
116 | =cut | ||||
117 | |||||
118 | sub 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 | |||||
131 | This is a version of C<crypt> (see L<perlfunc/crypt>) that implements the | ||||
132 | bcrypt algorithm. It does not implement any other hashing algorithms, | ||||
133 | so if others are desired then it necessary to examine the algorithm | ||||
134 | prefix in SETTINGS and dispatch between more than one version of C<crypt>. | ||||
135 | |||||
136 | SETTINGS must be a string which encodes the algorithm parameters, | ||||
137 | including salt. It must begin with "$2", optional "a", "$", two | ||||
138 | digits, "$", and 22 base 64 digits. The rest of the string is ignored. | ||||
139 | The presence of the optional "a" means that a NUL is to be appended | ||||
140 | to the password before it is used as a key. The two digits set the | ||||
141 | cost parameter. The 22 base 64 digits encode the salt. The function | ||||
142 | will C<die> if SETTINGS does not have this format. | ||||
143 | |||||
144 | The PASSWORD is hashed according to the SETTINGS. The value returned | ||||
145 | is a string which encodes the algorithm parameters and the hash: the | ||||
146 | parameters are in the same format required in SETTINGS, and the hash is | ||||
147 | appended in the form of 31 base 64 digits. This result is suitable to | ||||
148 | be used as a SETTINGS string for input to this function: the hash part | ||||
149 | of the string is ignored on input. | ||||
150 | |||||
151 | =cut | ||||
152 | |||||
153 | sub 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 | |||||
171 | L<Crypt::Eksblowfish>, | ||||
172 | L<http://www.usenix.org/events/usenix99/provos.html> | ||||
173 | |||||
174 | =head1 AUTHOR | ||||
175 | |||||
176 | Andrew Main (Zefram) <zefram@fysh.org> | ||||
177 | |||||
178 | =head1 COPYRIGHT | ||||
179 | |||||
180 | Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 | ||||
181 | Andrew Main (Zefram) <zefram@fysh.org> | ||||
182 | |||||
183 | =head1 LICENSE | ||||
184 | |||||
185 | This module is free software; you can redistribute it and/or modify it | ||||
186 | under the same terms as Perl itself. | ||||
187 | |||||
188 | =cut | ||||
189 | |||||
190 | 1 | 3µs | 1; |