Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

pbkdf2.go 2.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright 2021 by David A. Golden. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. // Package pbkdf2 implements password-based key derivation using the PBKDF2
  7. // algorithm described in RFC 2898 and RFC 8018.
  8. //
  9. // It provides a drop-in replacement for `golang.org/x/crypto/pbkdf2`, with
  10. // the following benefits:
  11. //
  12. // - Released as a module with semantic versioning
  13. //
  14. // - Does not pull in dependencies for unrelated `x/crypto/*` packages
  15. //
  16. // - Supports Go 1.9+
  17. //
  18. // See https://tools.ietf.org/html/rfc8018#section-4 for security considerations
  19. // in the selection of a salt and iteration count.
  20. package pbkdf2
  21. import (
  22. "crypto/hmac"
  23. "encoding/binary"
  24. "hash"
  25. )
  26. // Key generates a derived key from a password using the PBKDF2 algorithm. The
  27. // inputs include salt bytes, the iteration count, desired key length, and a
  28. // constructor for a hashing function. For example, for a 32-byte key using
  29. // SHA-256:
  30. //
  31. // key := Key([]byte("trustNo1"), salt, 10000, 32, sha256.New)
  32. func Key(password, salt []byte, iterCount, keyLen int, h func() hash.Hash) []byte {
  33. prf := hmac.New(h, password)
  34. hLen := prf.Size()
  35. numBlocks := keyLen / hLen
  36. // Get an extra block if keyLen is not an even number of hLen blocks.
  37. if keyLen%hLen > 0 {
  38. numBlocks++
  39. }
  40. Ti := make([]byte, hLen)
  41. Uj := make([]byte, hLen)
  42. dk := make([]byte, 0, hLen*numBlocks)
  43. buf := make([]byte, 4)
  44. for i := uint32(1); i <= uint32(numBlocks); i++ {
  45. // Initialize Uj for j == 1 from salt and block index.
  46. // Initialize Ti = U1.
  47. binary.BigEndian.PutUint32(buf, i)
  48. prf.Reset()
  49. prf.Write(salt)
  50. prf.Write(buf)
  51. Uj = Uj[:0]
  52. Uj = prf.Sum(Uj)
  53. // Ti = U1 ^ U2 ^ ... ^ Ux
  54. copy(Ti, Uj)
  55. for j := 2; j <= iterCount; j++ {
  56. prf.Reset()
  57. prf.Write(Uj)
  58. Uj = Uj[:0]
  59. Uj = prf.Sum(Uj)
  60. for k := range Uj {
  61. Ti[k] ^= Uj[k]
  62. }
  63. }
  64. // DK = concat(T1, T2, ... Tn)
  65. dk = append(dk, Ti...)
  66. }
  67. return dk[0:keyLen]
  68. }