blob: a5f45c1c5fead80563499859a69a0fc8551258f7 [file] [log] [blame]
Takahiro Suzukid7bf8202020-12-17 20:21:59 +09001package rfc3962
2
3import (
4 "encoding/binary"
5 "encoding/hex"
6 "errors"
7
8 "github.com/jcmturner/gofork/x/crypto/pbkdf2"
9 "gopkg.in/jcmturner/gokrb5.v7/crypto/etype"
10)
11
12const (
13 s2kParamsZero = 4294967296
14)
15
16// StringToKey returns a key derived from the string provided according to the definition in RFC 3961.
17func 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
26func 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.
31func 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
37func S2KparamsToItertions(s2kparams string) (int64, error) {
38 //process s2kparams string
39 //The parameter string is four octets indicating an unsigned
40 //number in big-endian order. This is the number of iterations to be
41 //performed. If the value is 00 00 00 00, the number of iterations to
42 //be performed is 4,294,967,296 (2**32).
43 var i uint32
44 if len(s2kparams) != 8 {
45 return int64(s2kParamsZero), errors.New("invalid s2kparams length")
46 }
47 b, err := hex.DecodeString(s2kparams)
48 if err != nil {
49 return int64(s2kParamsZero), errors.New("invalid s2kparams, cannot decode string to bytes")
50 }
51 i = binary.BigEndian.Uint32(b)
52 //buf := bytes.NewBuffer(b)
53 //err = binary.Read(buf, binary.BigEndian, &i)
54 if err != nil {
55 return int64(s2kParamsZero), errors.New("invalid s2kparams, cannot convert to big endian int32")
56 }
57 return int64(i), nil
58}