1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 // Package pbkdf2 implements the key derivation function PBKDF2 as defined in
6 // RFC 8018 (PKCS #5 v2.1).
7 //
8 // A key derivation function is useful when encrypting data based on a password
9 // or any other not-fully-random data. It uses a pseudorandom function to derive
10 // a secure encryption key based on the password.
11 package pbkdf2
12 13 import (
14 "crypto/internal/fips140/pbkdf2"
15 "crypto/internal/fips140hash"
16 "crypto/internal/fips140only"
17 "errors"
18 "hash"
19 )
20 21 // Key derives a key from the password, salt and iteration count, returning a
22 // []byte of length keyLength that can be used as cryptographic key. The key is
23 // derived based on the method described as PBKDF2 with the HMAC variant using
24 // the supplied hash function.
25 //
26 // For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
27 // can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
28 // doing:
29 //
30 // dk := pbkdf2.Key(sha1.New, "some password", salt, 4096, 32)
31 //
32 // Remember to get a good random salt. At least 8 bytes is recommended by the
33 // RFC.
34 //
35 // Using a higher iteration count will increase the cost of an exhaustive
36 // search but will also make derivation proportionally slower.
37 //
38 // keyLength must be a positive integer between 1 and (2^32 - 1) * h.Size().
39 // Setting keyLength to a value outside of this range will result in an error.
40 func Key[Hash hash.Hash](h func() Hash, password []byte, salt []byte, iter, keyLength int) ([]byte, error) {
41 fh := fips140hash.UnwrapNew(h)
42 if fips140only.Enabled {
43 if keyLength < 112/8 {
44 return nil, errors.New("crypto/pbkdf2: use of keys shorter than 112 bits is not allowed in FIPS 140-only mode")
45 }
46 if len(salt) < 128/8 {
47 return nil, errors.New("crypto/pbkdf2: use of salts shorter than 128 bits is not allowed in FIPS 140-only mode")
48 }
49 if !fips140only.ApprovedHash(fh()) {
50 return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
51 }
52 }
53 return pbkdf2.Key(fh, password, salt, iter, keyLength)
54 }
55