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 .