pbkdf2.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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 RFC
  6. 2898 / PKCS #5 v2.0.
  7. A key derivation function is useful when encrypting data based on a password
  8. or any other not-fully-random data. It uses a pseudorandom function to derive
  9. a secure encryption key based on the password.
  10. While v2.0 of the standard defines only one pseudorandom function to use,
  11. HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
  12. Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
  13. choose, you can pass the `New` functions from the different SHA packages to
  14. pbkdf2.Key.
  15. */
  16. package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
  17. import (
  18. "crypto/hmac"
  19. "hash"
  20. )
  21. // Key derives a key from the password, salt and iteration count, returning a
  22. // []byte of length keylen 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([]byte("some password"), salt, 4096, 32, sha1.New)
  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. func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
  38. prf := hmac.New(h, password)
  39. hashLen := prf.Size()
  40. numBlocks := (keyLen + hashLen - 1) / hashLen
  41. var buf [4]byte
  42. dk := make([]byte, 0, numBlocks*hashLen)
  43. U := make([]byte, hashLen)
  44. for block := 1; block <= numBlocks; block++ {
  45. // N.B.: || means concatenation, ^ means XOR
  46. // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
  47. // U_1 = PRF(password, salt || uint(i))
  48. prf.Reset()
  49. prf.Write(salt)
  50. buf[0] = byte(block >> 24)
  51. buf[1] = byte(block >> 16)
  52. buf[2] = byte(block >> 8)
  53. buf[3] = byte(block)
  54. prf.Write(buf[:4])
  55. dk = prf.Sum(dk)
  56. T := dk[len(dk)-hashLen:]
  57. copy(U, T)
  58. // U_n = PRF(password, U_(n-1))
  59. for n := 2; n <= iter; n++ {
  60. prf.Reset()
  61. prf.Write(U)
  62. U = U[:0]
  63. U = prf.Sum(U)
  64. for x := range U {
  65. T[x] ^= U[x]
  66. }
  67. }
  68. }
  69. return dk[:keyLen]
  70. }