1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- // Package rfc4757 provides encryption and checksum methods as specified in RFC 4757
- package rfc4757
- import (
- "crypto/hmac"
- "crypto/rand"
- "crypto/rc4"
- "errors"
- "fmt"
- "github.com/jcmturner/gokrb5/v8/crypto/etype"
- )
- // EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 4757.
- func EncryptData(key, data []byte, e etype.EType) ([]byte, error) {
- if len(key) != e.GetKeyByteSize() {
- return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
- }
- rc4Cipher, err := rc4.NewCipher(key)
- if err != nil {
- return []byte{}, fmt.Errorf("error creating RC4 cipher: %v", err)
- }
- ed := make([]byte, len(data))
- copy(ed, data)
- rc4Cipher.XORKeyStream(ed, ed)
- rc4Cipher.Reset()
- return ed, nil
- }
- // DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 4757.
- func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
- return EncryptData(key, data, e)
- }
- // EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
- // The encrypted data is concatenated with its RC4 header containing integrity checksum and confounder to create an encrypted message.
- func EncryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
- confounder := make([]byte, e.GetConfounderByteSize()) // size = 8
- _, err := rand.Read(confounder)
- if err != nil {
- return []byte{}, fmt.Errorf("error generating confounder: %v", err)
- }
- k1 := key
- k2 := HMAC(k1, UsageToMSMsgType(usage))
- toenc := append(confounder, data...)
- chksum := HMAC(k2, toenc)
- k3 := HMAC(k2, chksum)
- ed, err := EncryptData(k3, toenc, e)
- if err != nil {
- return []byte{}, fmt.Errorf("error encrypting data: %v", err)
- }
- msg := append(chksum, ed...)
- return msg, nil
- }
- // DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 4757.
- // The integrity of the message is also verified.
- func DecryptMessage(key, data []byte, usage uint32, export bool, e etype.EType) ([]byte, error) {
- checksum := data[:e.GetHMACBitLength()/8]
- ct := data[e.GetHMACBitLength()/8:]
- _, k2, k3 := deriveKeys(key, checksum, usage, export)
- pt, err := DecryptData(k3, ct, e)
- if err != nil {
- return []byte{}, fmt.Errorf("error decrypting data: %v", err)
- }
- if !VerifyIntegrity(k2, pt, data, e) {
- return []byte{}, errors.New("integrity checksum incorrect")
- }
- return pt[e.GetConfounderByteSize():], nil
- }
- // VerifyIntegrity checks the integrity checksum of the data matches that calculated from the decrypted data.
- func VerifyIntegrity(key, pt, data []byte, e etype.EType) bool {
- chksum := HMAC(key, pt)
- return hmac.Equal(chksum, data[:e.GetHMACBitLength()/8])
- }
|