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   129737 use strict;
  2         4  
  2         68  
4 2     2   13 use warnings;
  2         3  
  2         263  
5             our $VERSION = '0.089_001';
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   23 use Carp;
  2         4  
  2         138  
13             $Carp::Internal{(__PACKAGE__)}++;
14 2     2   625 use CryptX;
  2         5  
  2         212  
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             I
243              
244             bcrypt-based key derivation as defined by the OpenBSD project.
245              
246             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds, $hash_name, $len);
247             #or
248             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds, $hash_name);
249             #or
250             my $derived_key = bcrypt_pbkdf($password, $salt, $rounds);
251             #or
252             my $derived_key = bcrypt_pbkdf($password, $salt);
253              
254             # $password ... [binary string] input keying material (password)
255             # $salt ....... [binary string] salt/nonce
256             # $rounds ..... [integer] optional, number of rounds, DEFAULT: 16
257             # $hash_name .. [string] optional, DEFAULT: 'SHA512'
258             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
259              
260             Larger C<$rounds> values increase CPU cost linearly.
261              
262             =head2 scrypt_pbkdf
263              
264             I
265              
266             scrypt key derivation according to L.
267              
268             my $derived_key = scrypt_pbkdf($password, $salt, $N, $r, $p, $len);
269             #or
270             my $derived_key = scrypt_pbkdf($password, $salt, $N, $r, $p);
271             #or
272             my $derived_key = scrypt_pbkdf($password, $salt, $N);
273             #or
274             my $derived_key = scrypt_pbkdf($password, $salt);
275              
276             # $password ... [binary string] input keying material (password)
277             # $salt ....... [binary string] salt/nonce
278             # $N .......... [integer] optional, CPU/memory cost (must be power of 2), DEFAULT: 1024
279             # $r .......... [integer] optional, block size, DEFAULT: 8
280             # $p .......... [integer] optional, parallelization parameter, DEFAULT: 1
281             # $len ........ [integer] optional, derived key len in bytes, DEFAULT: 32
282              
283             Use only power-of-two values for C<$N>. Larger C<$N>, C<$r>, and C<$p>
284             increase resource usage substantially; invalid combinations croak.
285              
286             =head2 argon2_pbkdf
287              
288             I
289              
290             Argon2 key derivation according to L.
291              
292             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism, $len, $secret, $ad);
293             #or
294             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism, $len);
295             #or
296             my $derived_key = argon2_pbkdf($type, $password, $salt, $t_cost, $m_factor, $parallelism);
297             #or
298             my $derived_key = argon2_pbkdf($type, $password, $salt);
299              
300             # $type ... [string] one of 'argon2d', 'argon2i', 'argon2id'
301             # $password ... [binary string] input keying material (password)
302             # $salt ... [binary string] salt/nonce (recommended: at least 16 bytes)
303             # $t_cost ... [integer] optional, time cost (number of iterations), DEFAULT: 3
304             # $m_factor ... [integer] optional, memory cost in kibibytes (1 KiB = 1024 B), DEFAULT: 65536 (= 64 MiB)
305             # $parallelism ... [integer] optional, degree of parallelism, DEFAULT: 1
306             # $len ... [integer] optional, derived key len in bytes, DEFAULT: 32
307             # $secret ... [binary string] optional, secret value, DEFAULT: ''
308             # $ad ... [binary string] optional, associated data, DEFAULT: ''
309              
310             Increasing C<$t_cost>, C<$m_factor>, or C<$parallelism> increases work and
311             memory requirements. Invalid combinations croak. Optional C<$secret> and
312             C<$ad> may be C; otherwise they must be string or stringifiable scalars.
313              
314             =head1 SEE ALSO
315              
316             =over
317              
318             =item * L
319              
320             =item * L, L, L
321              
322             =item * L
323              
324             =item * L
325              
326             =item * L
327              
328             =item * L
329              
330             =back
331              
332             =cut