// Package rfc3961 provides encryption and checksum methods as specified in RFC 3961
package rfc3961 import ( ) // DES3EncryptData encrypts the data provided using DES3 and methods specific to the etype provided. func (, []byte, etype.EType) ([]byte, []byte, error) { if len() != .GetKeyByteSize() { return nil, nil, fmt.Errorf("incorrect keysize: expected: %v actual: %v", .GetKeyByteSize(), len()) } , _ = common.ZeroPad(, .GetMessageBlockByteSize()) , := des.NewTripleDESCipher() if != nil { return nil, nil, fmt.Errorf("error creating cipher: %v", ) } //RFC 3961: initial cipher state All bits zero := make([]byte, des.BlockSize) := make([]byte, len()) := cipher.NewCBCEncrypter(, ) .CryptBlocks(, ) return [len()-.GetMessageBlockByteSize():], , nil } // DES3EncryptMessage encrypts the message provided using DES3 and methods specific to the etype provided. // The encrypted data is concatenated with its integrity hash to create an encrypted message. func (, []byte, uint32, etype.EType) ([]byte, []byte, error) { //confounder := make([]byte, .GetConfounderByteSize()) , := rand.Read() if != nil { return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", ) } := append(, ...) , _ = common.ZeroPad(, .GetMessageBlockByteSize()) // Derive key for encryption from usage var []byte if != 0 { , = .DeriveKey(, common.GetUsageKe()) if != nil { return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", ) } } , , := .EncryptData(, ) if != nil { return , , fmt.Errorf("error encrypting data: %v", ) } // Generate and append integrity hash , := common.GetIntegrityHash(, , , ) if != nil { return , , fmt.Errorf("error encrypting data: %v", ) } = append(, ...) return , , nil } // DES3DecryptData decrypts the data provided using DES3 and methods specific to the etype provided. func (, []byte, etype.EType) ([]byte, error) { if len() != .GetKeyByteSize() { return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", .GetKeyByteSize(), len()) } if len() < des.BlockSize || len()%des.BlockSize != 0 { return []byte{}, errors.New("ciphertext is not a multiple of the block size") } , := des.NewTripleDESCipher() if != nil { return []byte{}, fmt.Errorf("error creating cipher: %v", ) } := make([]byte, len()) := make([]byte, des.BlockSize) := cipher.NewCBCDecrypter(, ) .CryptBlocks(, ) return , nil } // DES3DecryptMessage decrypts the message provided using DES3 and methods specific to the etype provided. // The integrity of the message is also verified. func (, []byte, uint32, etype.EType) ([]byte, error) { //Derive the key , := .DeriveKey(, common.GetUsageKe()) if != nil { return nil, fmt.Errorf("error deriving key: %v", ) } // Strip off the checksum from the end , := .DecryptData(, [:len()-.GetHMACBitLength()/8]) if != nil { return nil, fmt.Errorf("error decrypting: %v", ) } //Verify checksum if !.VerifyIntegrity(, , , ) { return nil, errors.New("error decrypting: integrity verification failed") } //Remove the confounder bytes return [.GetConfounderByteSize():], nil } // VerifyIntegrity verifies the integrity of cipertext bytes ct. func (, , []byte, uint32, etype.EType) bool { := make([]byte, .GetHMACBitLength()/8) copy(, [len()-.GetHMACBitLength()/8:]) , := common.GetIntegrityHash(, , , ) return hmac.Equal(, ) }