package rfc3961
import (
"crypto/cipher"
"crypto/des"
"crypto/hmac"
"crypto/rand"
"errors"
"fmt"
"github.com/jcmturner/gokrb5/v8/crypto/common"
"github.com/jcmturner/gokrb5/v8/crypto/etype"
)
func DES3EncryptData (key , data []byte , e etype .EType ) ([]byte , []byte , error ) {
if len (key ) != e .GetKeyByteSize () {
return nil , nil , fmt .Errorf ("incorrect keysize: expected: %v actual: %v" , e .GetKeyByteSize (), len (key ))
}
data , _ = common .ZeroPad (data , e .GetMessageBlockByteSize ())
block , err := des .NewTripleDESCipher (key )
if err != nil {
return nil , nil , fmt .Errorf ("error creating cipher: %v" , err )
}
ivz := make ([]byte , des .BlockSize )
ct := make ([]byte , len (data ))
mode := cipher .NewCBCEncrypter (block , ivz )
mode .CryptBlocks (ct , data )
return ct [len (ct )-e .GetMessageBlockByteSize ():], ct , nil
}
func DES3EncryptMessage (key , message []byte , usage uint32 , e etype .EType ) ([]byte , []byte , error ) {
c := make ([]byte , e .GetConfounderByteSize ())
_ , err := rand .Read (c )
if err != nil {
return []byte {}, []byte {}, fmt .Errorf ("could not generate random confounder: %v" , err )
}
plainBytes := append (c , message ...)
plainBytes , _ = common .ZeroPad (plainBytes , e .GetMessageBlockByteSize ())
var k []byte
if usage != 0 {
k , err = e .DeriveKey (key , common .GetUsageKe (usage ))
if err != nil {
return []byte {}, []byte {}, fmt .Errorf ("error deriving key for encryption: %v" , err )
}
}
iv , b , err := e .EncryptData (k , plainBytes )
if err != nil {
return iv , b , fmt .Errorf ("error encrypting data: %v" , err )
}
ih , err := common .GetIntegrityHash (plainBytes , key , usage , e )
if err != nil {
return iv , b , fmt .Errorf ("error encrypting data: %v" , err )
}
b = append (b , ih ...)
return iv , b , nil
}
func DES3DecryptData (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 ))
}
if len (data ) < des .BlockSize || len (data )%des .BlockSize != 0 {
return []byte {}, errors .New ("ciphertext is not a multiple of the block size" )
}
block , err := des .NewTripleDESCipher (key )
if err != nil {
return []byte {}, fmt .Errorf ("error creating cipher: %v" , err )
}
pt := make ([]byte , len (data ))
ivz := make ([]byte , des .BlockSize )
mode := cipher .NewCBCDecrypter (block , ivz )
mode .CryptBlocks (pt , data )
return pt , nil
}
func DES3DecryptMessage (key , ciphertext []byte , usage uint32 , e etype .EType ) ([]byte , error ) {
k , err := e .DeriveKey (key , common .GetUsageKe (usage ))
if err != nil {
return nil , fmt .Errorf ("error deriving key: %v" , err )
}
b , err := e .DecryptData (k , ciphertext [:len (ciphertext )-e .GetHMACBitLength ()/8 ])
if err != nil {
return nil , fmt .Errorf ("error decrypting: %v" , err )
}
if !e .VerifyIntegrity (key , ciphertext , b , usage ) {
return nil , errors .New ("error decrypting: integrity verification failed" )
}
return b [e .GetConfounderByteSize ():], nil
}
func VerifyIntegrity (key , ct , pt []byte , usage uint32 , etype etype .EType ) bool {
h := make ([]byte , etype .GetHMACBitLength ()/8 )
copy (h , ct [len (ct )-etype .GetHMACBitLength ()/8 :])
expectedMAC , _ := common .GetIntegrityHash (pt , key , usage , etype )
return hmac .Equal (h , expectedMAC )
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .