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