hkdf.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // Copyright 2014 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. package qtls
  5. // Mostly derived from golang.org/x/crypto/hkdf, but with an exposed
  6. // Extract API.
  7. //
  8. // HKDF is a cryptographic key derivation function (KDF) with the goal of
  9. // expanding limited input keying material into one or more cryptographically
  10. // strong secret keys.
  11. //
  12. // RFC 5869: https://tools.ietf.org/html/rfc5869
  13. import (
  14. "crypto"
  15. "crypto/hmac"
  16. )
  17. func hkdfExpand(hash crypto.Hash, prk, info []byte, l int) []byte {
  18. var (
  19. expander = hmac.New(hash.New, prk)
  20. res = make([]byte, l)
  21. counter = byte(1)
  22. prev []byte
  23. )
  24. if l > 255*expander.Size() {
  25. panic("hkdf: requested too much output")
  26. }
  27. p := res
  28. for len(p) > 0 {
  29. expander.Reset()
  30. expander.Write(prev)
  31. expander.Write(info)
  32. expander.Write([]byte{counter})
  33. prev = expander.Sum(prev[:0])
  34. counter++
  35. n := copy(p, prev)
  36. p = p[n:]
  37. }
  38. return res
  39. }
  40. // HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
  41. func HkdfExtract(hash crypto.Hash, secret, salt []byte) []byte {
  42. return hkdfExtract(hash, secret, salt)
  43. }
  44. func hkdfExtract(hash crypto.Hash, secret, salt []byte) []byte {
  45. if salt == nil {
  46. salt = make([]byte, hash.Size())
  47. }
  48. if secret == nil {
  49. secret = make([]byte, hash.Size())
  50. }
  51. extractor := hmac.New(hash.New, salt)
  52. extractor.Write(secret)
  53. return extractor.Sum(nil)
  54. }