package rfc8009
import (
"crypto/aes"
"crypto/hmac"
"crypto/rand"
"errors"
"fmt"
"github.com/jcmturner/aescts/v2"
"github.com/jcmturner/gokrb5/v8/crypto/common"
"github.com/jcmturner/gokrb5/v8/crypto/etype"
"github.com/jcmturner/gokrb5/v8/iana/etypeID"
)
func EncryptData (key , data []byte , e etype .EType ) ([]byte , []byte , error ) {
kl := e .GetKeyByteSize ()
if e .GetETypeID () == etypeID .AES256_CTS_HMAC_SHA384_192 {
kl = 32
}
if len (key ) != kl {
return []byte {}, []byte {}, fmt .Errorf ("incorrect keysize: expected: %v actual: %v" , e .GetKeyByteSize (), len (key ))
}
ivz := make ([]byte , aes .BlockSize )
return aescts .Encrypt (key , ivz , data )
}
func EncryptMessage (key , message []byte , usage uint32 , e etype .EType ) ([]byte , []byte , error ) {
kl := e .GetKeyByteSize ()
if e .GetETypeID () == etypeID .AES256_CTS_HMAC_SHA384_192 {
kl = 32
}
if len (key ) != kl {
return []byte {}, []byte {}, fmt .Errorf ("incorrect keysize: expected: %v actual: %v" , kl , len (key ))
}
if len (key ) != e .GetKeyByteSize () {
}
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 ...)
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 )
}
ivz := make ([]byte , e .GetConfounderByteSize ())
ih , err := GetIntegityHash (ivz , b , 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 DecryptData (key , data []byte , e etype .EType ) ([]byte , error ) {
kl := e .GetKeyByteSize ()
if e .GetETypeID () == etypeID .AES256_CTS_HMAC_SHA384_192 {
kl = 32
}
if len (key ) != kl {
return []byte {}, fmt .Errorf ("incorrect keysize: expected: %v actual: %v" , kl , len (key ))
}
ivz := make ([]byte , aes .BlockSize )
return aescts .Decrypt (key , ivz , data )
}
func DecryptMessage (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 , err
}
if !e .VerifyIntegrity (key , ciphertext , b , usage ) {
return nil , errors .New ("integrity verification failed" )
}
return b [e .GetConfounderByteSize ():], nil
}
func GetIntegityHash (iv , c , key []byte , usage uint32 , e etype .EType ) ([]byte , error ) {
ib := append (iv , c ...)
return common .GetIntegrityHash (ib , key , usage , e )
}
func VerifyIntegrity (key , ct []byte , usage uint32 , etype etype .EType ) bool {
h := make ([]byte , etype .GetHMACBitLength ()/8 )
copy (h , ct [len (ct )-etype .GetHMACBitLength ()/8 :])
ivz := make ([]byte , etype .GetConfounderByteSize ())
ib := append (ivz , ct [:len (ct )-(etype .GetHMACBitLength ()/8 )]...)
expectedMAC , _ := common .GetIntegrityHash (ib , 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 .