keyDerivation.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package rfc3962
  2. import (
  3. "encoding/binary"
  4. "encoding/hex"
  5. "errors"
  6. "github.com/jcmturner/gofork/x/crypto/pbkdf2"
  7. "github.com/jcmturner/gokrb5/v8/crypto/etype"
  8. )
  9. const (
  10. s2kParamsZero = 4294967296
  11. )
  12. // StringToKey returns a key derived from the string provided according to the definition in RFC 3961.
  13. func StringToKey(secret, salt, s2kparams string, e etype.EType) ([]byte, error) {
  14. i, err := S2KparamsToItertions(s2kparams)
  15. if err != nil {
  16. return nil, err
  17. }
  18. return StringToKeyIter(secret, salt, i, e)
  19. }
  20. // StringToPBKDF2 generates an encryption key from a pass phrase and salt string using the PBKDF2 function from PKCS #5 v2.0
  21. func StringToPBKDF2(secret, salt string, iterations int64, e etype.EType) []byte {
  22. return pbkdf2.Key64([]byte(secret), []byte(salt), iterations, int64(e.GetKeyByteSize()), e.GetHashFunc())
  23. }
  24. // StringToKeyIter returns a key derived from the string provided according to the definition in RFC 3961.
  25. func StringToKeyIter(secret, salt string, iterations int64, e etype.EType) ([]byte, error) {
  26. tkey := e.RandomToKey(StringToPBKDF2(secret, salt, iterations, e))
  27. return e.DeriveKey(tkey, []byte("kerberos"))
  28. }
  29. // S2KparamsToItertions converts the string representation of iterations to an integer
  30. func S2KparamsToItertions(s2kparams string) (int64, error) {
  31. //The s2kparams string should be hex string representing 4 bytes
  32. //The 4 bytes represent a number in big endian order
  33. //If the value is zero then the number of iterations should be 4,294,967,296 (2^32)
  34. var i uint32
  35. if len(s2kparams) != 8 {
  36. return int64(s2kParamsZero), errors.New("invalid s2kparams length")
  37. }
  38. b, err := hex.DecodeString(s2kparams)
  39. if err != nil {
  40. return int64(s2kParamsZero), errors.New("invalid s2kparams, cannot decode string to bytes")
  41. }
  42. i = binary.BigEndian.Uint32(b)
  43. return int64(i), nil
  44. }