github.com/jcmturner/gokrb5/v8@v8.4.4/crypto/rfc3962/encryption.go (about) 1 // Package rfc3962 provides encryption and checksum methods as specified in RFC 3962 2 package rfc3962 3 4 import ( 5 "crypto/rand" 6 "errors" 7 "fmt" 8 9 "github.com/jcmturner/aescts/v2" 10 "github.com/jcmturner/gokrb5/v8/crypto/common" 11 "github.com/jcmturner/gokrb5/v8/crypto/etype" 12 ) 13 14 // EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 3962. 15 func EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) { 16 if len(key) != e.GetKeyByteSize() { 17 return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key)) 18 } 19 ivz := make([]byte, e.GetCypherBlockBitLength()/8) 20 return aescts.Encrypt(key, ivz, data) 21 } 22 23 // EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 3962. 24 // The encrypted data is concatenated with its integrity hash to create an encrypted message. 25 func EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) { 26 if len(key) != e.GetKeyByteSize() { 27 return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key)) 28 } 29 //confounder 30 c := make([]byte, e.GetConfounderByteSize()) 31 _, err := rand.Read(c) 32 if err != nil { 33 return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err) 34 } 35 plainBytes := append(c, message...) 36 37 // Derive key for encryption from usage 38 var k []byte 39 if usage != 0 { 40 k, err = e.DeriveKey(key, common.GetUsageKe(usage)) 41 if err != nil { 42 return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err) 43 } 44 } 45 46 // Encrypt the data 47 iv, b, err := e.EncryptData(k, plainBytes) 48 if err != nil { 49 return iv, b, fmt.Errorf("error encrypting data: %v", err) 50 } 51 52 // Generate and append integrity hash 53 ih, err := common.GetIntegrityHash(plainBytes, key, usage, e) 54 if err != nil { 55 return iv, b, fmt.Errorf("error encrypting data: %v", err) 56 } 57 b = append(b, ih...) 58 return iv, b, nil 59 } 60 61 // DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 3962. 62 func DecryptData(key, data []byte, e etype.EType) ([]byte, error) { 63 if len(key) != e.GetKeyByteSize() { 64 return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key)) 65 } 66 ivz := make([]byte, e.GetCypherBlockBitLength()/8) 67 return aescts.Decrypt(key, ivz, data) 68 } 69 70 // DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 3962. 71 // The integrity of the message is also verified. 72 func DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) { 73 //Derive the key 74 k, err := e.DeriveKey(key, common.GetUsageKe(usage)) 75 if err != nil { 76 return nil, fmt.Errorf("error deriving key: %v", err) 77 } 78 // Strip off the checksum from the end 79 b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8]) 80 if err != nil { 81 return nil, err 82 } 83 //Verify checksum 84 if !e.VerifyIntegrity(key, ciphertext, b, usage) { 85 return nil, errors.New("integrity verification failed") 86 } 87 //Remove the confounder bytes 88 return b[e.GetConfounderByteSize():], nil 89 }