github.com/jcmturner/gokrb5/v8@v8.4.4/crypto/crypto.go (about) 1 // Package crypto implements cryptographic functions for Kerberos 5 implementation. 2 package crypto 3 4 import ( 5 "encoding/hex" 6 "fmt" 7 8 "github.com/jcmturner/gokrb5/v8/crypto/etype" 9 "github.com/jcmturner/gokrb5/v8/iana/chksumtype" 10 "github.com/jcmturner/gokrb5/v8/iana/etypeID" 11 "github.com/jcmturner/gokrb5/v8/iana/patype" 12 "github.com/jcmturner/gokrb5/v8/types" 13 ) 14 15 // GetEtype returns an instances of the required etype struct for the etype ID. 16 func GetEtype(id int32) (etype.EType, error) { 17 switch id { 18 case etypeID.AES128_CTS_HMAC_SHA1_96: 19 var et Aes128CtsHmacSha96 20 return et, nil 21 case etypeID.AES256_CTS_HMAC_SHA1_96: 22 var et Aes256CtsHmacSha96 23 return et, nil 24 case etypeID.AES128_CTS_HMAC_SHA256_128: 25 var et Aes128CtsHmacSha256128 26 return et, nil 27 case etypeID.AES256_CTS_HMAC_SHA384_192: 28 var et Aes256CtsHmacSha384192 29 return et, nil 30 case etypeID.DES3_CBC_SHA1_KD: 31 var et Des3CbcSha1Kd 32 return et, nil 33 case etypeID.RC4_HMAC: 34 var et RC4HMAC 35 return et, nil 36 default: 37 return nil, fmt.Errorf("unknown or unsupported EType: %d", id) 38 } 39 } 40 41 // GetChksumEtype returns an instances of the required etype struct for the checksum ID. 42 func GetChksumEtype(id int32) (etype.EType, error) { 43 switch id { 44 case chksumtype.HMAC_SHA1_96_AES128: 45 var et Aes128CtsHmacSha96 46 return et, nil 47 case chksumtype.HMAC_SHA1_96_AES256: 48 var et Aes256CtsHmacSha96 49 return et, nil 50 case chksumtype.HMAC_SHA256_128_AES128: 51 var et Aes128CtsHmacSha256128 52 return et, nil 53 case chksumtype.HMAC_SHA384_192_AES256: 54 var et Aes256CtsHmacSha384192 55 return et, nil 56 case chksumtype.HMAC_SHA1_DES3_KD: 57 var et Des3CbcSha1Kd 58 return et, nil 59 case chksumtype.KERB_CHECKSUM_HMAC_MD5: 60 var et RC4HMAC 61 return et, nil 62 //case chksumtype.KERB_CHECKSUM_HMAC_MD5_UNSIGNED: 63 // var et RC4HMAC 64 // return et, nil 65 default: 66 return nil, fmt.Errorf("unknown or unsupported checksum type: %d", id) 67 } 68 } 69 70 // GetKeyFromPassword generates an encryption key from the principal's password. 71 func GetKeyFromPassword(passwd string, cname types.PrincipalName, realm string, etypeID int32, pas types.PADataSequence) (types.EncryptionKey, etype.EType, error) { 72 var key types.EncryptionKey 73 et, err := GetEtype(etypeID) 74 if err != nil { 75 return key, et, fmt.Errorf("error getting encryption type: %v", err) 76 } 77 sk2p := et.GetDefaultStringToKeyParams() 78 var salt string 79 var paID int32 80 for _, pa := range pas { 81 switch pa.PADataType { 82 case patype.PA_PW_SALT: 83 if paID > pa.PADataType { 84 continue 85 } 86 salt = string(pa.PADataValue) 87 case patype.PA_ETYPE_INFO: 88 if paID > pa.PADataType { 89 continue 90 } 91 var eti types.ETypeInfo 92 err := eti.Unmarshal(pa.PADataValue) 93 if err != nil { 94 return key, et, fmt.Errorf("error unmashaling PA Data to PA-ETYPE-INFO2: %v", err) 95 } 96 if etypeID != eti[0].EType { 97 et, err = GetEtype(eti[0].EType) 98 if err != nil { 99 return key, et, fmt.Errorf("error getting encryption type: %v", err) 100 } 101 } 102 salt = string(eti[0].Salt) 103 case patype.PA_ETYPE_INFO2: 104 if paID > pa.PADataType { 105 continue 106 } 107 var et2 types.ETypeInfo2 108 err := et2.Unmarshal(pa.PADataValue) 109 if err != nil { 110 return key, et, fmt.Errorf("error unmashalling PA Data to PA-ETYPE-INFO2: %v", err) 111 } 112 if etypeID != et2[0].EType { 113 et, err = GetEtype(et2[0].EType) 114 if err != nil { 115 return key, et, fmt.Errorf("error getting encryption type: %v", err) 116 } 117 } 118 if len(et2[0].S2KParams) == 4 { 119 sk2p = hex.EncodeToString(et2[0].S2KParams) 120 } 121 salt = et2[0].Salt 122 } 123 } 124 if salt == "" { 125 salt = cname.GetSalt(realm) 126 } 127 k, err := et.StringToKey(passwd, salt, sk2p) 128 if err != nil { 129 return key, et, fmt.Errorf("error deriving key from string: %+v", err) 130 } 131 key = types.EncryptionKey{ 132 KeyType: etypeID, 133 KeyValue: k, 134 } 135 return key, et, nil 136 } 137 138 // GetEncryptedData encrypts the data provided and returns and EncryptedData type. 139 // Pass a usage value of zero to use the key provided directly rather than deriving one. 140 func GetEncryptedData(plainBytes []byte, key types.EncryptionKey, usage uint32, kvno int) (types.EncryptedData, error) { 141 var ed types.EncryptedData 142 et, err := GetEtype(key.KeyType) 143 if err != nil { 144 return ed, fmt.Errorf("error getting etype: %v", err) 145 } 146 _, b, err := et.EncryptMessage(key.KeyValue, plainBytes, usage) 147 if err != nil { 148 return ed, err 149 } 150 151 ed = types.EncryptedData{ 152 EType: key.KeyType, 153 Cipher: b, 154 KVNO: kvno, 155 } 156 return ed, nil 157 } 158 159 // DecryptEncPart decrypts the EncryptedData. 160 func DecryptEncPart(ed types.EncryptedData, key types.EncryptionKey, usage uint32) ([]byte, error) { 161 return DecryptMessage(ed.Cipher, key, usage) 162 } 163 164 // DecryptMessage decrypts the ciphertext and verifies the integrity. 165 func DecryptMessage(ciphertext []byte, key types.EncryptionKey, usage uint32) ([]byte, error) { 166 et, err := GetEtype(key.KeyType) 167 if err != nil { 168 return []byte{}, fmt.Errorf("error decrypting: %v", err) 169 } 170 b, err := et.DecryptMessage(key.KeyValue, ciphertext, usage) 171 if err != nil { 172 return nil, fmt.Errorf("error decrypting: %v", err) 173 } 174 return b, nil 175 }