File Coverage

blib/lib/Crypt/KeyDerivation.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             package Crypt::KeyDerivation;
2              
3 2     2   134264 use strict;
  2         5  
  2         84  
4 2     2   17 use warnings;
  2         3  
  2         396  
5             our $VERSION = '0.089';
6              
7             require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
8             our %EXPORT_TAGS = ( all => [qw(pbkdf1 pbkdf1_openssl pbkdf2 hkdf hkdf_expand hkdf_extract bcrypt_pbkdf scrypt_pbkdf argon2_pbkdf)] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw();
11              
12 2     2   18 use Carp;
  2         5  
  2         173  
13             $Carp::Internal{(__PACKAGE__)}++;
14 2     2   641 use CryptX;
  2         5  
  2         248  
15              
16             1;
17              
18             =pod
19              
20             =head1 NAME
21              
22             Crypt::KeyDerivation - PBKDF1, PBKDF2, HKDF, Bcrypt, Scrypt, Argon2 key derivation functions
23              
24             =head1 SYNOPSIS
25              
26             use Crypt::KeyDerivation ':all';
27              
28             my $password = 'secret';
29             my $salt = '12345678';
30             my $iteration_count = 5000;
31             my $hash_name = 'SHA256';
32             my $len = 32;
33             my $keying_material = 'input keying material';
34             my $info = 'context';
35             my $rounds = 16;
36             my $N = 1024;
37             my $r = 8;
38             my $p = 1;
39             my $type = 'argon2id';
40             my $t_cost = 3;
41             my $m_factor = 65536;
42             my $parallelism = 1;
43             my $secret = '';
44             my $ad = '';
45              
46             ### PBKDF1/2
47             my $pbkdf1_key = pbkdf1($password, $salt, $iteration_count, $hash_name, $len);
48             my $openssl_pbkdf1_key = pbkdf1_openssl($password, $salt, $iteration_count, $hash_name, $len);
49             my $pbkdf2_key = pbkdf2($password, $salt, $iteration_count, $hash_name, $len);
50              
51             ### HKDF & co.
52             my $hkdf_okm = hkdf($keying_material, $salt, $hash_name, $len, $info);
53             my $prk = hkdf_extract($keying_material, $salt, $hash_name);
54             my $expanded_okm = hkdf_expand($prk, $hash_name, $len, $info);
55              
56             ### bcrypt / scrypt / argon2
57             my $bcrypt_key = bcrypt_pbkdf($password, $salt, $rounds, $hash_name, $len);
58             my $scrypt_key = scrypt_pbkdf($password, $salt, $N, $r, $p, $len);
59             my $argon2_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism, $len, $secret, $ad);
60              
61             =head1 DESCRIPTION
62              
63             Provides an interface to key derivation functions:
64              
65             =over
66              
67             =item * PBKDF1 and PBKDF2 according to PKCS #5 v2.0
68             L
69              
70             =item * HKDF (+ related) according to
71             L
72              
73             =item * Bcrypt-PBKDF as defined by the OpenBSD project
74              
75             =item * Scrypt according to L
76              
77             =item * Argon2 according to L
78              
79             =back
80              
81             While primarily designed for key derivation, the functions PBKDF2, Bcrypt, Scrypt and Argon2
82             are also widely used for password hashing. In that use case the derived key serves as the
83             stored password hash.
84              
85             All functions return raw bytes. Passing an output length of C<0> returns an
86             empty string in this wrapper API. Argument validation still happens first:
87             required password / input-keying-material arguments reject C, invalid
88             hash names and invalid Argon2 type names are still rejected, and malformed
89             optional scalar arguments still return C where applicable.
90              
91             This zero-length behaviour is a C wrapper policy. The
92             underlying libtomcrypt functions do not all behave the same way: some accept
93             zero-length outputs, while others reject them with algorithm-specific checks.
94             Code calling libtomcrypt directly should not assume the wrapper behaviour.
95              
96             =head1 EXPORT
97              
98             Nothing is exported by default.
99              
100             You can export selected functions:
101              
102             use Crypt::KeyDerivation qw(
103             pbkdf1 pbkdf1_openssl pbkdf2
104             hkdf hkdf_expand hkdf_extract
105             bcrypt_pbkdf scrypt_pbkdf argon2_pbkdf
106             );
107              
108             Or all of them at once:
109              
110             use Crypt::KeyDerivation ':all';
111              
112             =head1 FUNCTIONS
113              
114             =head2 pbkdf1
115              
116             B If you are not sure, do not use C - choose C instead.
117              
118             my $derived_key = pbkdf1($password, $salt, $iteration_count, $hash_name, $len);
119             #or
120             my $derived_key = pbkdf1($password, $salt, $iteration_count, $hash_name);
121             #or
122             my $derived_key = pbkdf1($password, $salt, $iteration_count);
123             #or
124             my $derived_key = pbkdf1($password, $salt);
125              
126             # $password ......... [binary string] input keying material (password)
127             # $salt ............. [binary string] salt/nonce (expected length: 8 bytes)
128             # $iteration_count .. [integer] optional, DEFAULT: 5000
129             # $hash_name ........ [string] optional, DEFAULT: 'SHA256'
130             # $len .............. [integer] optional, derived key len in bytes, DEFAULT: 32
131              
132             In strict PKCS #5 v1 mode, the derived key length must not exceed the selected
133             hash output size. For example, C allows at most 20 bytes.
134              
135             The underlying algorithm uses only the first 8 bytes of C<$salt>. Shorter salts
136             are rejected; longer salts are accepted but truncated to 8 bytes.
137              
138             =head2 pbkdf1_openssl
139              
140             I
141              
142             OpenSSL-compatible variant of PBKDF1 (implements C). Unlike strict
143             C, the output length is not limited to the hash size -- it can be arbitrarily
144             long by chaining hash blocks.
145              
146             B this function implements the OpenSSL-compatible algorithm, but its
147             default parameters do B match the historical C defaults.
148             OpenSSL traditionally uses C and C, while this wrapper
149             defaults to C and C<5000>. If you need output compatible with the
150             traditional OpenSSL default behaviour, pass both values explicitly:
151              
152             my $derived_key = pbkdf1_openssl($password, $salt, 1, 'MD5', $len);
153              
154             my $derived_key = pbkdf1_openssl($password, $salt, $iteration_count, $hash_name, $len);
155             #or
156             my $derived_key = pbkdf1_openssl($password, $salt, $iteration_count, $hash_name);
157             #or
158             my $derived_key = pbkdf1_openssl($password, $salt, $iteration_count);
159             #or
160             my $derived_key = pbkdf1_openssl($password, $salt);
161              
162             # $password ......... [binary string] input keying material (password)
163             # $salt ............. [binary string] salt/nonce (expected length: 8 bytes)
164             # $iteration_count .. [integer] optional, DEFAULT: 5000
165             # $hash_name ........ [string] optional, DEFAULT: 'SHA256'
166             # $len .............. [integer] optional, derived key len in bytes, DEFAULT: 32
167              
168             The underlying algorithm uses only the first 8 bytes of C<$salt>. Shorter salts
169             are rejected; longer salts are accepted but truncated to 8 bytes.
170              
171             =head2 pbkdf2
172              
173             my $derived_key = pbkdf2($password, $salt, $iteration_count, $hash_name, $len);
174             #or
175             my $derived_key = pbkdf2($password, $salt, $iteration_count, $hash_name);
176             #or
177             my $derived_key = pbkdf2($password, $salt, $iteration_count);
178             #or
179             my $derived_key = pbkdf2($password, $salt);
180              
181             # $password ......... [binary string] input keying material (password)
182             # $salt ............. [binary string] salt/nonce (any length; longer is better)
183             # $iteration_count .. [integer] optional, DEFAULT: 5000
184             # $hash_name ........ [string] optional, DEFAULT: 'SHA256'
185             # $len .............. [integer] optional, derived key len in bytes, DEFAULT: 32
186              
187             =head2 hkdf
188              
189             my $okm = hkdf($password, $salt, $hash_name, $len, $info);
190             #or
191             my $okm = hkdf($password, $salt, $hash_name, $len);
192             #or
193             my $okm = hkdf($password, $salt, $hash_name);
194             #or
195             my $okm = hkdf($password, $salt);
196              
197             # $password ... [binary string] input keying material
198             # $salt ....... [binary string | undef] salt; if undef defaults to HashLen zero octets
199             # $hash_name .. [string] optional, DEFAULT: 'SHA256'
200             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
201             # $info ....... [binary string] optional context/application info, DEFAULT: ''
202              
203             Use C for one-shot extract+expand. For multi-step workflows, use
204             C followed by C.
205              
206             The input keying material / pseudokey arguments must be string or
207             stringifiable scalars. Optional C<$salt> and C<$info> may be C.
208              
209             =head2 hkdf_extract
210              
211             my $prk = hkdf_extract($password, $salt, $hash_name);
212             #or
213             my $prk = hkdf_extract($password, $salt);
214              
215             # $password ... [binary string] input keying material
216             # $salt ....... [binary string | undef] salt; if undef defaults to HashLen zero octets
217             # $hash_name .. [string] optional, DEFAULT: 'SHA256'
218              
219             Returns the pseudorandom key (PRK). Its length is the digest size of the
220             selected hash and it is intended to be passed to C.
221              
222              
223             =head2 hkdf_expand
224              
225             my $okm = hkdf_expand($pseudokey, $hash_name, $len, $info);
226             #or
227             my $okm = hkdf_expand($pseudokey, $hash_name, $len);
228             #or
229             my $okm = hkdf_expand($pseudokey, $hash_name);
230             #or
231             my $okm = hkdf_expand($pseudokey);
232              
233             # $pseudokey .. [binary string] input keying material (normally from hkdf_extract)
234             # $hash_name .. [string] optional, DEFAULT: 'SHA256'
235             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
236             # $info ....... [binary string] optional context/application info, DEFAULT: ''
237              
238             C<$pseudokey> is normally the PRK returned by C.
239              
240             =head2 bcrypt_pbkdf
241              
242             bcrypt-based key derivation as defined by the OpenBSD project.
243              
244             I
245              
246              
247             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds, $hash_name, $len);
248             #or
249             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds, $hash_name);
250             #or
251             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds);
252             #or
253             my $derived_key = bcrypt_pbkdf($password, $salt);
254              
255             # $password ... [binary string] input keying material (password)
256             # $salt ....... [binary string] salt/nonce
257             # $rounds ..... [integer] optional, number of rounds, DEFAULT: 16
258             # $hash_name .. [string] optional, DEFAULT: 'SHA512'
259             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
260              
261             Larger C<$rounds> values increase CPU cost linearly.
262              
263             =head2 scrypt_pbkdf
264              
265             scrypt key derivation according to L.
266              
267             I
268              
269              
270             my $derived_key = scrypt_pbkdf($password, $salt, $N, $r, $p, $len);
271             #or
272             my $derived_key = scrypt_pbkdf($password, $salt, $N, $r, $p);
273             #or
274             my $derived_key = scrypt_pbkdf($password, $salt, $N);
275             #or
276             my $derived_key = scrypt_pbkdf($password, $salt);
277              
278             # $password ... [binary string] input keying material (password)
279             # $salt ....... [binary string] salt/nonce
280             # $N .......... [integer] optional, CPU/memory cost (must be power of 2), DEFAULT: 1024
281             # $r .......... [integer] optional, block size, DEFAULT: 8
282             # $p .......... [integer] optional, parallelization parameter, DEFAULT: 1
283             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
284              
285             Use only power-of-two values for C<$N>. Larger C<$N>, C<$r>, and C<$p>
286             increase resource usage substantially; invalid combinations croak.
287              
288             =head2 argon2_pbkdf
289              
290             Argon2 key derivation according to L.
291              
292             I
293              
294              
295             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism, $len, $secret, $ad);
296             #or
297             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism, $len);
298             #or
299             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism);
300             #or
301             my $derived_key = argon2_pbkdf($type, $password, $salt);
302              
303             # $type ... [string] one of 'argon2d', 'argon2i', 'argon2id'
304             # $password ... [binary string] input keying material (password)
305             # $salt ... [binary string] salt/nonce (recommended: at least 16 bytes)
306             # $t_cost ... [integer] optional, time cost (number of iterations), DEFAULT: 3
307             # $m_factor ... [integer] optional, memory cost in kibibytes (1 KiB = 1024 B), DEFAULT: 65536 (= 64 MiB)
308             # $parallelism ... [integer] optional, degree of parallelism, DEFAULT: 1
309             # $len ... [integer] optional, derived key len in bytes, DEFAULT: 32
310             # $secret ... [binary string] optional, secret value, DEFAULT: ''
311             # $ad ... [binary string] optional, associated data, DEFAULT: ''
312              
313             Increasing C<$t_cost>, C<$m_factor>, or C<$parallelism> increases work and
314             memory requirements. Invalid combinations croak. Optional C<$secret> and
315             C<$ad> may be C; otherwise they must be string or stringifiable scalars.
316              
317             =head1 SEE ALSO
318              
319             =over
320              
321             =item * L
322              
323             =item * L, L, L
324              
325             =item * L
326              
327             =item * L
328              
329             =item * L
330              
331             =item * L
332              
333             =back
334              
335             =cut