|
2 | 2 | // Use of this source code is governed by a BSD-style |
3 | 3 | // license that can be found in the LICENSE file. |
4 | 4 |
|
5 | | -/* |
6 | | -Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC |
7 | | -2898 / PKCS #5 v2.0. |
8 | | -
|
9 | | -A key derivation function is useful when encrypting data based on a password |
10 | | -or any other not-fully-random data. It uses a pseudorandom function to derive |
11 | | -a secure encryption key based on the password. |
12 | | -
|
13 | | -While v2.0 of the standard defines only one pseudorandom function to use, |
14 | | -HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved |
15 | | -Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To |
16 | | -choose, you can pass the `New` functions from the different SHA packages to |
17 | | -pbkdf2.Key. |
18 | | -*/ |
| 5 | +// Package pbkdf2 implements the key derivation function PBKDF2 as defined in |
| 6 | +// RFC 8018 (PKCS #5 v2.1). |
| 7 | +// |
| 8 | +// This package is a wrapper for the PBKDF2 implementation in the |
| 9 | +// [crypto/pbkdf2] package. It is [frozen] and is not accepting new features. |
| 10 | +// |
| 11 | +// [frozen]: https://go.dev/wiki/Frozen |
19 | 12 | package pbkdf2 |
20 | 13 |
|
21 | 14 | import ( |
22 | | - "crypto/hmac" |
| 15 | + "crypto/pbkdf2" |
23 | 16 | "hash" |
24 | 17 | ) |
25 | 18 |
|
26 | 19 | // Key derives a key from the password, salt and iteration count, returning a |
27 | 20 | // []byte of length keylen that can be used as cryptographic key. The key is |
28 | 21 | // derived based on the method described as PBKDF2 with the HMAC variant using |
29 | 22 | // the supplied hash function. |
30 | | -// |
31 | | -// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you |
32 | | -// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by |
33 | | -// doing: |
34 | | -// |
35 | | -// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) |
36 | | -// |
37 | | -// Remember to get a good random salt. At least 8 bytes is recommended by the |
38 | | -// RFC. |
39 | | -// |
40 | | -// Using a higher iteration count will increase the cost of an exhaustive |
41 | | -// search but will also make derivation proportionally slower. |
42 | 23 | func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { |
43 | | - prf := hmac.New(h, password) |
44 | | - hashLen := prf.Size() |
45 | | - numBlocks := (keyLen + hashLen - 1) / hashLen |
46 | | - |
47 | | - var buf [4]byte |
48 | | - dk := make([]byte, 0, numBlocks*hashLen) |
49 | | - U := make([]byte, hashLen) |
50 | | - for block := 1; block <= numBlocks; block++ { |
51 | | - // N.B.: || means concatenation, ^ means XOR |
52 | | - // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter |
53 | | - // U_1 = PRF(password, salt || uint(i)) |
54 | | - prf.Reset() |
55 | | - prf.Write(salt) |
56 | | - buf[0] = byte(block >> 24) |
57 | | - buf[1] = byte(block >> 16) |
58 | | - buf[2] = byte(block >> 8) |
59 | | - buf[3] = byte(block) |
60 | | - prf.Write(buf[:4]) |
61 | | - dk = prf.Sum(dk) |
62 | | - T := dk[len(dk)-hashLen:] |
63 | | - copy(U, T) |
64 | | - |
65 | | - // U_n = PRF(password, U_(n-1)) |
66 | | - for n := 2; n <= iter; n++ { |
67 | | - prf.Reset() |
68 | | - prf.Write(U) |
69 | | - U = U[:0] |
70 | | - U = prf.Sum(U) |
71 | | - for x := range U { |
72 | | - T[x] ^= U[x] |
73 | | - } |
74 | | - } |
| 24 | + out, err := pbkdf2.Key(h, string(password), salt, iter, keyLen) |
| 25 | + if err != nil { |
| 26 | + // FIPS 140 enforcement, or an invalid key length. |
| 27 | + panic(err) |
75 | 28 | } |
76 | | - return dk[:keyLen] |
| 29 | + return out |
77 | 30 | } |
0 commit comments