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  }