Jonathan Turner 9 vuotta sitten
vanhempi
commit
af43470b75

+ 49 - 0
client/ASExchange.go

@@ -0,0 +1,49 @@
+package client
+
+import (
+	"github.com/jcmturner/gokrb5/messages"
+	"fmt"
+	"errors"
+	"github.com/jcmturner/gokrb5/iana/errorcode"
+)
+
+func (cl *Client) ASExchange() error {
+	if !cl.IsConfigured() {
+		return errors.New("Client is not configured correctly.")
+	}
+	a := messages.NewASReq(cl.Config, cl.Username)
+	b, err := a.Marshal()
+	if err != nil {
+		return fmt.Errorf("Error marshalling AS_REQ: %v", err)
+	}
+	rb, err := cl.SendToKDC(b)
+	if err != nil {
+		return fmt.Errorf("Error sending AS_REQ to KDC: %v", err)
+	}
+	var ar messages.ASRep
+	err = ar.Unmarshal(rb)
+	if err != nil {
+		//An KRBError may have been returned instead.
+		var krberr messages.KRBError
+		err = krberr.Unmarshal(rb)
+		if err != nil {
+			return fmt.Errorf("Could not unmarshal data returned from KDC: %v", err)
+		}
+		if krberr.ErrorCode = errorcode.KDC_ERR_PREAUTH_REQUIRED {
+			//TODO put PA TIMESTAMP here
+		}
+		return krberr
+	}
+	if len(cl.Keytab.Entries) > 1 {
+		err = ar.DecryptEncPartWithKeytab(cl.Keytab)
+		if err != nil {
+			return fmt.Errorf("Error decrypting AS_REP encPart with keytab: %v", err)
+		}
+	} else {
+		err = ar.DecryptEncPartWithPassword(cl.Password)
+		if err != nil {
+			return fmt.Errorf("Error decrypting AS_REP encPart with password: %v", err)
+		}
+	}
+	return nil
+}

+ 65 - 97
client/client.go

@@ -1,123 +1,91 @@
 package client
 
 import (
+	"bytes"
+	"encoding/hex"
 	"fmt"
+	"github.com/jcmturner/asn1"
 	"github.com/jcmturner/gokrb5/config"
+	"github.com/jcmturner/gokrb5/crypto"
+	"github.com/jcmturner/gokrb5/iana/keyusage"
+	"github.com/jcmturner/gokrb5/keytab"
+	"github.com/jcmturner/gokrb5/messages"
+	"github.com/jcmturner/gokrb5/types"
 	"math/rand"
 	"net"
-	"bytes"
+	"os"
 	"time"
 )
 
-func ASExchange() {
-
+type Client struct {
+	Username string
+	Password string
+	Keytab   keytab.Keytab
+	Config   *config.Config
 }
 
-func SendToKDC(c *config.Config, b []byte) ([]byte, error) {
-	var rb []byte
-	var kdcs []string
-	for _, r := range c.Realms {
-		if r.Realm == c.LibDefaults.Default_realm {
-			kdcs = r.Kdc
-			break
-		}
-	}
-	if len(kdcs) < 1 {
-		return rb, fmt.Errorf("No KDCs defined in configuration for realm %v", c.LibDefaults.Default_realm)
-	}
-	var kdc string
-	if len(kdcs) > 1 {
-		//Select one of the KDCs at random
-		kdc = kdcs[rand.Intn(len(kdcs))]
-	} else {
-		kdc = kdcs[0]
+func NewClientWithPassword(username, password string) Client {
+	return Client{
+		Username: username,
+		Password: password,
+		Keytab: keytab.NewKeytab(),
+		Config: config.NewConfig(),
 	}
+}
 
-	if c.LibDefaults.Udp_preference_limit == 1 {
-		//1 means we should always use TCP
-		rb, errtcp := sendTCP(kdc, b)
-		if errtcp != nil {
-			return rb, fmt.Errorf("Failed to communicate with KDC %v via TDP (%v)", kdc, errtcp)
-		}
-		if len(rb) < 1 {
-			return rb, fmt.Errorf("No response data from KDC %v", kdc)
-		}
-		return rb, nil
+func NewClientWithKeytab(username string, kt keytab.Keytab) Client {
+	return Client{
+		Username: username,
+		Keytab:   kt,
+		Config: config.NewConfig(),
 	}
-	if len(b) <= c.LibDefaults.Udp_preference_limit {
-		//Try UDP first, TCP second
-		rb, errudp := sendUDP(kdc, b)
-		if errudp != nil {
-			rb, errtcp := sendTCP(kdc, b)
-			if errtcp != nil {
-				return rb, fmt.Errorf("Failed to communicate with KDC %v via UDP (%v) and then via TDP (%v)", kdc, errudp, errtcp)
-			}
-		}
-		if len(rb) < 1 {
-			return rb, fmt.Errorf("No response data from KDC %v", kdc)
-		}
-		return rb, nil
-	}
-	//Try TCP first, UDP second
-	rb, errtcp := sendTCP(kdc, b)
-	if errtcp != nil {
-		rb, errudp := sendUDP(kdc, b)
-		if errudp != nil {
-			return rb, fmt.Errorf("Failed to communicate with KDC %v via TCP (%v) and then via UDP (%v)", kdc, errtcp, errudp)
-		}
-	}
-	if len(rb) < 1 {
-		return rb, fmt.Errorf("No response data from KDC %v", kdc)
-	}
-	return rb, nil
 }
 
-func sendUDP(kdc string, b []byte) ([]byte, error) {
-	var r []byte
-	udpAddr, err := net.ResolveUDPAddr("udp", kdc)
-	if err != nil {
-		return r, fmt.Errorf("Error resolving KDC address: %v", err)
-	}
-	conn, err := net.DialUDP("udp", nil, udpAddr)
-	if err != nil {
-		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
-	}
-	defer conn.Close()
-	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
-	_, err = conn.Write(b)
-	if err != nil {
-		return r, fmt.Errorf("Error sending to KDC: %v", err)
-	}
-	udpbuf := make([]byte, 4096)
-	n, _, err := conn.ReadFrom(udpbuf)
-	r = udpbuf[:n]
+func (cl *Client) WithPassword(p string) *Client {
+	cl.Password = p
+	return cl
+}
+
+func (cl *Client) WithKeytab(kt keytab.Keytab) *Client {
+	cl.Keytab = kt
+	return cl
+}
+
+func (cl *Client) WithConfig(cfg config.Config) *Client {
+	cl.Config = cfg
+	return cl
+}
+
+func (cl *Client) LoadConfig(cfgPath string) (*Client, error) {
+	cfg, err := config.Load(cfgPath)
 	if err != nil {
-		return r, fmt.Errorf("Sending over UDP failed: %v", err)
+		return cl, err
 	}
-	return r, nil
+	cl.Config = cfg
+	return cl, nil
 }
 
-func sendTCP(kdc string, b []byte) ([]byte, error) {
-	var r []byte
-	tcpAddr, err := net.ResolveTCPAddr("tcp", kdc)
-	if err != nil {
-		return r, fmt.Errorf("Error resolving KDC address: %v", err)
+func (cl *Client) IsConfigured() bool {
+	if cl.Password == "" && len(cl.Keytab.Entries) < 1 {
+		return false
 	}
-	conn, err := net.DialTCP("tcp", nil, tcpAddr)
-	if err != nil {
-		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
+	if cl.Username == "" {
+		return false
 	}
-	defer conn.Close()
-	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
-	_, err = conn.Write(b)
-	if err != nil {
-		return r, fmt.Errorf("Error sending to KDC: %v", err)
+	if cl.Config.LibDefaults.Default_realm == "" {
+		return false
 	}
-	tcpbuf := bytes.NewBuffer(make([]byte, 4096))
-	n, err := conn.ReadFrom(tcpbuf)
-	r = tcpbuf.Bytes()[:n]
-	if err != nil {
-		return r, fmt.Errorf("Sending over TCP failed: %v", err)
+	for _, r := range cl.Config.Realms {
+		if r.Realm == cl.Config.LibDefaults.Default_realm {
+			if len(r.Kdc) > 0 {
+				return true
+			} else {
+				return false
+			}
+		}
 	}
-	return r, nil
+	return false
 }
+
+
+

+ 119 - 0
client/network.go

@@ -0,0 +1,119 @@
+package client
+
+import (
+	"net"
+	"fmt"
+	"time"
+	"bytes"
+	"math/rand"
+)
+
+func (cl *Client) SendToKDC(b []byte) ([]byte, error) {
+	var rb []byte
+	var kdcs []string
+	for _, r := range cl.Config.Realms {
+		if r.Realm == cl.Config.LibDefaults.Default_realm {
+			kdcs = r.Kdc
+			break
+		}
+	}
+	if len(kdcs) < 1 {
+		return rb, fmt.Errorf("No KDCs defined in configuration for realm %v", cl.Config.LibDefaults.Default_realm)
+	}
+	var kdc string
+	if len(kdcs) > 1 {
+		//Select one of the KDCs at random
+		kdc = kdcs[rand.Intn(len(kdcs))]
+	} else {
+		kdc = kdcs[0]
+	}
+
+	if cl.Config.LibDefaults.Udp_preference_limit == 1 {
+		//1 means we should always use TCP
+		rb, errtcp := sendTCP(kdc, b)
+		if errtcp != nil {
+			return rb, fmt.Errorf("Failed to communicate with KDC %v via TDP (%v)", kdc, errtcp)
+		}
+		if len(rb) < 1 {
+			return rb, fmt.Errorf("No response data from KDC %v", kdc)
+		}
+		return rb, nil
+	}
+	if len(b) <= cl.Config.LibDefaults.Udp_preference_limit {
+		//Try UDP first, TCP second
+		rb, errudp := sendUDP(kdc, b)
+		if errudp != nil {
+			rb, errtcp := sendTCP(kdc, b)
+			if errtcp != nil {
+				return rb, fmt.Errorf("Failed to communicate with KDC %v via UDP (%v) and then via TDP (%v)", kdc, errudp, errtcp)
+			}
+		}
+		if len(rb) < 1 {
+			return rb, fmt.Errorf("No response data from KDC %v", kdc)
+		}
+		return rb, nil
+	}
+	//Try TCP first, UDP second
+	rb, errtcp := sendTCP(kdc, b)
+	if errtcp != nil {
+		rb, errudp := sendUDP(kdc, b)
+		if errudp != nil {
+			return rb, fmt.Errorf("Failed to communicate with KDC %v via TCP (%v) and then via UDP (%v)", kdc, errtcp, errudp)
+		}
+	}
+	if len(rb) < 1 {
+		return rb, fmt.Errorf("No response data from KDC %v", kdc)
+	}
+	return rb, nil
+}
+
+func sendUDP(kdc string, b []byte) ([]byte, error) {
+	var r []byte
+	udpAddr, err := net.ResolveUDPAddr("udp", kdc)
+	if err != nil {
+		return r, fmt.Errorf("Error resolving KDC address: %v", err)
+	}
+	conn, err := net.DialUDP("udp", nil, udpAddr)
+	if err != nil {
+		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
+	}
+	defer conn.Close()
+	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
+	_, err = conn.Write(b)
+	if err != nil {
+		return r, fmt.Errorf("Error sending to KDC: %v", err)
+	}
+	udpbuf := make([]byte, 4096)
+	n, _, err := conn.ReadFrom(udpbuf)
+	r = udpbuf[:n]
+	if err != nil {
+		return r, fmt.Errorf("Sending over UDP failed: %v", err)
+	}
+	return r, nil
+}
+
+func sendTCP(kdc string, b []byte) ([]byte, error) {
+	var r []byte
+	tcpAddr, err := net.ResolveTCPAddr("tcp", kdc)
+	if err != nil {
+		return r, fmt.Errorf("Error resolving KDC address: %v", err)
+	}
+	conn, err := net.DialTCP("tcp", nil, tcpAddr)
+	if err != nil {
+		return r, fmt.Errorf("Error establishing connection to KDC: %v", err)
+	}
+	defer conn.Close()
+	conn.SetDeadline(time.Now().Add(time.Duration(5) * time.Second))
+	_, err = conn.Write(b)
+	if err != nil {
+		return r, fmt.Errorf("Error sending to KDC: %v", err)
+	}
+	tcpbuf := bytes.NewBuffer(make([]byte, 4096))
+	n, err := conn.ReadFrom(tcpbuf)
+	r = tcpbuf.Bytes()[:n]
+	if err != nil {
+		return r, fmt.Errorf("Sending over TCP failed: %v", err)
+	}
+	return r, nil
+}
+

+ 4 - 1
client/session.go

@@ -3,9 +3,11 @@ package client
 import (
 	"github.com/jcmturner/gokrb5/types"
 	"time"
+	"github.com/jcmturner/gokrb5/keytab"
 )
 
-type session struct {
+
+type Session struct {
 	AuthTime  time.Time
 	EndTime   time.Time
 	RenewTill time.Time
@@ -13,3 +15,4 @@ type session struct {
 	TGT        types.Ticket
 	SessionKey types.EncryptionKey
 }
+

+ 10 - 10
crypto/EncryptionEngine.go

@@ -28,7 +28,7 @@ type EType interface {
 	GetConfounderByteSize() int                                 // This is the same as the cipher block size but in bytes.
 	DeriveKey(protocolKey, usage []byte) ([]byte, error)        // DK key-derivation (protocol-key, integer)->(specific-key)
 	DeriveRandom(protocolKey, usage []byte) ([]byte, error)     // DR pseudo-random (protocol-key, octet-string)->(octet-string)
-	VerifyChecksum(protocolKey, ct, pt []byte, usage int) bool
+	VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool
 	GetHash() hash.Hash
 }
 
@@ -142,8 +142,8 @@ func DecryptEncPart(key []byte, pe types.EncryptedData, etype EType, usage uint3
 		return nil, fmt.Errorf("Error decrypting: %v", err)
 	}
 	//Verify checksum
-	if !etype.VerifyChecksum(key, pe.Cipher, b, int(usage)) {
-		return nil, errors.New("Error decrypting encrypted part: checksum verification failed")
+	if !etype.VerifyIntegrity(key, pe.Cipher, b, usage) {
+		return nil, errors.New("Error decrypting encrypted part: integrity verification failed")
 	}
 	//Remove the confounder bytes
 	b = b[etype.GetConfounderByteSize():]
@@ -200,7 +200,7 @@ func GetKeyFromPassword(passwd string, cn types.PrincipalName, realm string, ety
 					return key, etype, fmt.Errorf("Error getting encryption type: %v", err)
 				}
 			}
-			if len(et2[0].S2KParams) == 8 {
+			if len(et2[0].S2KParams) == 4 {
 				sk2p = hex.EncodeToString(et2[0].S2KParams)
 			}
 			salt = et2[0].Salt
@@ -216,8 +216,8 @@ func GetKeyFromPassword(passwd string, cn types.PrincipalName, realm string, ety
 	return key, etype, nil
 }
 
-func GetChecksum(pt, key []byte, usage int, etype EType) ([]byte, error) {
-	k, err := etype.DeriveKey(key, GetUsageKi(uint32(usage)))
+func GetIntegrityHash(pt, key []byte, usage uint32, etype EType) ([]byte, error) {
+	k, err := etype.DeriveKey(key, GetUsageKi(usage))
 	if err != nil {
 		return nil, fmt.Errorf("Unable to derive key for checksum: %v", err)
 	}
@@ -230,10 +230,10 @@ func GetChecksum(pt, key []byte, usage int, etype EType) ([]byte, error) {
 	//	pt = append(pt, t...)
 	//}
 	mac.Write(pt)
-	return mac.Sum(nil), nil
+	return mac.Sum(nil)[1:etype.GetHMACBitLength()/8], nil
 }
 
-func VerifyChecksum(key, ct, pt []byte, usage int, etype EType) bool {
+func VerifyIntegrity(key, ct, pt []byte, usage uint32, etype EType) bool {
 	//The ciphertext output is the concatenation of the output of the basic
 	//encryption function E and a (possibly truncated) HMAC using the
 	//specified hash function H, both applied to the plaintext with a
@@ -241,8 +241,8 @@ func VerifyChecksum(key, ct, pt []byte, usage int, etype EType) bool {
 	//multiple of the message block size.  When the HMAC is computed, the
 	//key is used in the protocol key form.
 	h := ct[len(ct)-etype.GetHMACBitLength()/8+1:]
-	expectedMAC, _ := GetChecksum(pt, key, usage, etype)
-	return hmac.Equal(h, expectedMAC[1:etype.GetHMACBitLength()/8])
+	expectedMAC, _ := GetIntegrityHash(pt, key, usage, etype)
+	return hmac.Equal(h, expectedMAC)
 }
 
 /*

+ 2 - 2
crypto/aes128-cts-hmac-sha1-96.go

@@ -116,6 +116,6 @@ func (e Aes128CtsHmacSha96) DeriveRandom(protocolKey, usage []byte) ([]byte, err
 	return AESDeriveRandom(protocolKey, usage, e)
 }
 
-func (e Aes128CtsHmacSha96) VerifyChecksum(protocolKey, ct, pt []byte, usage int) bool {
-	return VerifyChecksum(protocolKey, ct, pt, usage, e)
+func (e Aes128CtsHmacSha96) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
+	return VerifyIntegrity(protocolKey, ct, pt, usage, e)
 }

+ 2 - 2
crypto/aes256-cts-hmac-sha1-96.go

@@ -116,6 +116,6 @@ func (e Aes256CtsHmacSha96) DeriveRandom(protocolKey, usage []byte) ([]byte, err
 	return AESDeriveRandom(protocolKey, usage, e)
 }
 
-func (e Aes256CtsHmacSha96) VerifyChecksum(protocolKey, ct, pt []byte, usage int) bool {
-	return VerifyChecksum(protocolKey, ct, pt, usage, e)
+func (e Aes256CtsHmacSha96) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
+	return VerifyIntegrity(protocolKey, ct, pt, usage, e)
 }

+ 2 - 2
crypto/des3-cbc-sha1-kd.go

@@ -164,6 +164,6 @@ func (e Des3CbcSha1Kd) Decrypt(key, ciphertext []byte) (message []byte, err erro
 	return
 }
 
-func (e Des3CbcSha1Kd) VerifyChecksum(protocolKey, ct, pt []byte, usage int) bool {
-	return VerifyChecksum(protocolKey, ct, pt, usage, e)
+func (e Des3CbcSha1Kd) VerifyIntegrity(protocolKey, ct, pt []byte, usage uint32) bool {
+	return VerifyIntegrity(protocolKey, ct, pt, usage, e)
 }

+ 27 - 2
debug.go

@@ -33,9 +33,35 @@ const krb5conf = `[libdefaults]
 [domain_realm]
  .test.gokrb5 = TEST.GOKRB5
  test.gokrb5 = TEST.GOKRB5`
+const noparep="6b8202bc308202b8a003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020100a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a2820106048201021ced05c1ad2bfcd32c14306cd0c2ed3499e0dbdff120f64151b0fc8fe15a5f4dcc185cd14a9d67570dc4a0410d1384172860e844cabfe8cc3172ac0f1c32e7290ca28fe3499a9ac144a1c8918424165a932711e3fccefb3fff4f599d753edc21c2ec005df65da2e66bac24dca69041af231cbaaf6e18c6799731e1bda62a2a774c4adebbb81b1cf87956418b9944a711e3910c26e5e8e60e069eea8c3ed7769c231614a9ca36fb8407b81b5e67c262795fff243869b44358b36510c4e3f46d281d45306fc01eb0975d01e02be17078450085d08007e0f231ee6264896b05a57d0fd5dd167a725de99891c23f05ad9ce891f714e0cdc73d8a1db441195d95e3bbb259a681f63081f3a003020112a281eb0481e8cdc7aeaa51ae78e2adabd140f0c28a21ca527dc6960cbad675564dcd54954ff4bfd96cb95ef7714f21d0c0d5c94f0f0970574488fdd8d519563e0d775607b084170c4959205c4dbc4f16fa0d4099546de7239d64194c92de073a53e2af868e823262926ffc01e488a306fe84e59ad375fea8debf2b864789d275412947508592bd5adac0d2ddf31f7d56be6bd1cf722a3bdae04d7514e8cd9c4460890afb901c75dd6659cced7e84a82446e8779ce5b7e740c61c149982936d37667191b4d0c28daafc66ddb4c71772800217bf1281109da55bda95f32eea02a06d00a87f91e2bdbfbb7906d5a143"
+const pa149rep= "6b8202f3308202efa003020105a10302010ba22e302c302aa103020113a2230421301f301da003020112a1161b14544553542e474f4b524235746573747573657231a30d1b0b544553542e474f4b524235a4163014a003020101a10d300b1b09746573747573657231a582015a6182015630820152a003020105a10d1b0b544553542e474f4b524235a220301ea003020102a11730151b066b72627467741b0b544553542e474f4b524235a382011830820114a003020112a103020101a28201060482010237e486e32cd18ab1ac9f8d42e93f8babd7b3497084cc5599f18ec61961c6d5242d350354d99d67a7604c451116188d16cb719e84377212eac2743440e8c504ef69c755e489cc6b65f935dd032bfc076f9b2c56d816197845b8fe857d738bc59712787631a50e86833d1b0e4732c8712c856417a6a257758e7d01d3182adb3233f0dde65d228c240ed26aa1af69f8d765dc0bc69096fdb037a75af220fea176839528d44b70f7dabfaa2ea506de1296f847176a60c501fd8cef8e0a51399bb6d5f753962d96292e93ffe344c6630db912931d46d88c0279f00719e22d0efcfd4ee33a702d0b660c1f13970a9beec12c0c8af3dda68bd81ac1fe3f126d2a24ebb445c5a682012c30820128a003020112a282011f0482011bb149cc16018072c4c18788d95a33aba540e52c11b54a93e67e788d05de75d8f3d4aa1afafbbfa6fde3eb40e5aa1890644cea2607efd5213a3fd00345b02eeb9ae1b589f36c74c689cd4ec1239dfe61e42ba6afa33f6240e3cfab291e4abb465d273302dbf7dbd148a299a9369044dd03377c1687e7dd36aa66501284a4ca50c0a7b08f4f87aecfa23b0dd0b11490e3ad330906dab715de81fc52f120d09c39990b8b5330d4601cc396b2ed258834329c4cc02c563a12de3ef9bf11e946258bc2ab5257f4caa4d443a7daf0fc25f6f531c2fcba88af8ca55c85300997cd05abbea52811fe2d038ba8f62fc8e3bc71ce04362d356ea2e1df8ac55c784c53cfb07817d48e39fe99fc8788040d98209c79dcf044d97e80de9f47824646"
+
 
 func main() {
 
+NoPA()
+
+}
+
+func NoPA() {
+	//kb, _ := hex.DecodeString(ktab)
+	//kt, _ := keytab.Parse(kb)
+	rb, _ := hex.DecodeString(noparep)
+	var ar messages.ASRep
+	err := ar.Unmarshal(rb)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unmarshal err: %v\n", err)
+	}
+	//err = ar.DecryptEncPartWithKeytab(kt)
+	err = ar.DecryptEncPartWithPassword("passwordvalue")
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "\nDecrypt err: %v\n%+v\n", err, ar)
+	} else {
+		fmt.Fprintf(os.Stdout, "\n\nAS REP decrypted with keytab: %+v\n", ar)
+	}
+}
+
+func Fast (){
 	c, err := config.NewConfigFromString(krb5conf)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Error creating config: %v", err)
@@ -70,12 +96,11 @@ func main() {
 		}
 		fmt.Fprintf(os.Stdout, "PAReqEncPARep: %+v\n", p)
 		var et crypto.Aes256CtsHmacSha96
-		cb, err := crypto.GetChecksum(b, ar.DecryptedEncPart.Key.KeyValue, keyusage.KEY_USAGE_AS_REQ, et)
+		cb, err := crypto.GetIntegrityHash(b, ar.DecryptedEncPart.Key.KeyValue, keyusage.KEY_USAGE_AS_REQ, et)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "Error getting checksum PAReqEncPARep: %v\n", err)
 		} else {
 			fmt.Fprintf(os.Stdout, "AS REQ checksum: %+v\n", cb[:et.GetHMACBitLength()/8])
 		}
 	}
-
 }