implement applet secure channel
This commit is contained in:
parent
8be3d6ebcb
commit
6e7e217179
|
@ -2,10 +2,12 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
stdlog "log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ebfe/scard"
|
||||
|
@ -51,6 +53,7 @@ func init() {
|
|||
"delete": commandDelete,
|
||||
"init": commandInit,
|
||||
"pair": commandPair,
|
||||
"status": commandStatus,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +153,30 @@ func ask(description string) string {
|
|||
return strings.TrimSpace(text)
|
||||
}
|
||||
|
||||
func askHex(description string) []byte {
|
||||
s := ask(description)
|
||||
if s[:2] == "0x" {
|
||||
s = s[2:]
|
||||
}
|
||||
|
||||
data, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func askUint8(description string) uint8 {
|
||||
s := ask(description)
|
||||
i, err := strconv.ParseUint(s, 10, 8)
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
return uint8(i)
|
||||
}
|
||||
|
||||
func commandInstall(i *actionsets.Installer) error {
|
||||
if *flagCapFile == "" {
|
||||
logger.Error("you must specify a cap file path with the -f flag\n")
|
||||
|
@ -221,8 +248,15 @@ func commandPair(i *actionsets.Installer) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Pairing key %x\n", info.Key)
|
||||
fmt.Printf("Pairing key 0x%x\n", info.Key)
|
||||
fmt.Printf("Pairing Index %d\n", info.Index)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func commandStatus(i *actionsets.Installer) error {
|
||||
index := askUint8("Pairing index")
|
||||
key := askHex("Pairing key")
|
||||
|
||||
return i.Status(index, key)
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package crypto
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
|
||||
/* #nosec */
|
||||
"crypto/des"
|
||||
)
|
||||
|
||||
|
@ -25,7 +23,6 @@ func DeriveKey(cardKey []byte, seq []byte, purpose []byte) ([]byte, error) {
|
|||
copy(derivation, purpose[:2])
|
||||
copy(derivation[2:], seq[:2])
|
||||
|
||||
/* #nosec */
|
||||
block, err := des.NewTripleDESCipher(key24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -57,13 +54,11 @@ func VerifyCryptogram(encKey, hostChallenge, cardChallenge, cardCryptogram []byt
|
|||
func MacFull3DES(key, data, iv []byte) ([]byte, error) {
|
||||
data = AppendDESPadding(data)
|
||||
|
||||
/* #nosec */
|
||||
desBlock, err := des.NewCipher(resizeKey8(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/* #nosec */
|
||||
des3Block, err := des.NewTripleDESCipher(resizeKey24(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -90,7 +85,6 @@ func MacFull3DES(key, data, iv []byte) ([]byte, error) {
|
|||
// EncryptICV encrypts an ICV with the specified macKey.
|
||||
// The ICV is usually the mac of the previous command sent in the current session.
|
||||
func EncryptICV(macKey, icv []byte) ([]byte, error) {
|
||||
/* #nosec */
|
||||
block, err := des.NewCipher(resizeKey8(macKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -107,7 +101,6 @@ func EncryptICV(macKey, icv []byte) ([]byte, error) {
|
|||
func Mac3DES(key, data, iv []byte) ([]byte, error) {
|
||||
key24 := resizeKey24(key)
|
||||
|
||||
/* #nosec */
|
||||
block, err := des.NewTripleDESCipher(key24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -123,13 +116,11 @@ func Mac3DES(key, data, iv []byte) ([]byte, error) {
|
|||
|
||||
// AppendDESPadding appends an 0x80 bytes to data and other zero bytes to make the result length multiple of 8.
|
||||
func AppendDESPadding(data []byte) []byte {
|
||||
length := len(data) + 1
|
||||
for ; length%8 != 0; length++ {
|
||||
}
|
||||
|
||||
newData := make([]byte, length)
|
||||
blockSize := 8
|
||||
paddingSize := blockSize - (len(data) % blockSize)
|
||||
newData := make([]byte, len(data)+paddingSize)
|
||||
copy(newData, data)
|
||||
copy(newData[len(data):], []byte{0x80})
|
||||
newData[len(data)] = 0x80
|
||||
|
||||
return newData
|
||||
}
|
||||
|
|
|
@ -30,6 +30,16 @@ func TestAppendDESPadding(t *testing.T) {
|
|||
result := AppendDESPadding(data)
|
||||
expected := "AABB800000000000"
|
||||
assert.Equal(t, expected, hexutils.BytesToHex(result))
|
||||
|
||||
data = hexutils.HexToBytes("01020304050607")
|
||||
result = AppendDESPadding(data)
|
||||
expected = "0102030405060780"
|
||||
assert.Equal(t, expected, hexutils.BytesToHex(result))
|
||||
|
||||
data = hexutils.HexToBytes("0102030405060708")
|
||||
result = AppendDESPadding(data)
|
||||
expected = "01020304050607088000000000000000"
|
||||
assert.Equal(t, expected, hexutils.BytesToHex(result))
|
||||
}
|
||||
|
||||
func TestVerifyCryptogram(t *testing.T) {
|
||||
|
|
|
@ -3,7 +3,6 @@ package actions
|
|||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
@ -142,23 +141,33 @@ func OpenSecureChannel(c globalplatform.Channel, appInfo *lightwallet.Applicatio
|
|||
return nil, err
|
||||
}
|
||||
|
||||
salt := resp.Data[:32]
|
||||
iv := resp.Data[32:]
|
||||
|
||||
h := sha512.New()
|
||||
h.Write(sc.Secret())
|
||||
h.Write(pairingKey)
|
||||
h.Write(salt)
|
||||
data := h.Sum(nil)
|
||||
|
||||
encKey := data[:32]
|
||||
macKey := data[32:]
|
||||
|
||||
encKey, macKey, iv := crypto.DeriveSessionKeys(sc.Secret(), pairingKey, resp.Data)
|
||||
sc.Init(iv, encKey, macKey)
|
||||
|
||||
err = mutualAuthenticate(sc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
func mutualAuthenticate(sc *lightwallet.SecureChannel) error {
|
||||
data := make([]byte, 32)
|
||||
if _, err := rand.Read(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := lightwallet.NewCommandMutuallyAuthenticate(data)
|
||||
resp, err := sc.Send(cmd)
|
||||
|
||||
return checkOKResponse(err, resp)
|
||||
}
|
||||
|
||||
func Status(index uint8, key []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseApplicationInfo(data []byte, info *lightwallet.ApplicationInfo) (*lightwallet.ApplicationInfo, error) {
|
||||
if data[0] != lightwallet.TagApplicationInfoTemplate {
|
||||
return nil, ErrUnknownApplicationInfoTemplate
|
||||
|
|
|
@ -21,6 +21,10 @@ var (
|
|||
walletAID = []byte{0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x41, 0x70, 0x70}
|
||||
ndefAppletAID = []byte{0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x57, 0x61, 0x6C, 0x6C, 0x65, 0x74, 0x4E, 0x46, 0x43}
|
||||
ndefInstanceAID = []byte{0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01}
|
||||
|
||||
errAppletNotInstalled = errors.New("applet not installed")
|
||||
errCardNotInitialized = errors.New("card not initialized")
|
||||
errCardAlreadyInitialized = errors.New("card already initialized")
|
||||
)
|
||||
|
||||
// Installer defines a struct with methods to install an applet to a smartcard.
|
||||
|
@ -76,11 +80,11 @@ func (i *Installer) Init() (*lightwallet.Secrets, error) {
|
|||
}
|
||||
|
||||
if !info.Installed {
|
||||
return nil, fmt.Errorf("applet not installed")
|
||||
return nil, errAppletNotInstalled
|
||||
}
|
||||
|
||||
if info.Initialized {
|
||||
return nil, fmt.Errorf("card already initialized")
|
||||
return nil, errCardAlreadyInitialized
|
||||
}
|
||||
|
||||
err = actions.Init(i.c, info.PublicKey, secrets, walletAID)
|
||||
|
@ -100,11 +104,34 @@ func (i *Installer) Pair(pairingPass, pin string) (*lightwallet.PairingInfo, err
|
|||
return actions.Pair(i.c, pairingPass, pin)
|
||||
}
|
||||
|
||||
// Info returns if the applet is already installed in the card.
|
||||
// Info returns a lightwallet.ApplicationInfo struct with info about the card.
|
||||
func (i *Installer) Info() (*lightwallet.ApplicationInfo, error) {
|
||||
return actions.Select(i.c, walletAID)
|
||||
}
|
||||
|
||||
// Status returns
|
||||
func (i *Installer) Status(index uint8, key []byte) error {
|
||||
info, err := actions.Select(i.c, walletAID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.Installed {
|
||||
return errAppletNotInstalled
|
||||
}
|
||||
|
||||
if !info.Initialized {
|
||||
return errCardNotInitialized
|
||||
}
|
||||
|
||||
sc, err := actions.OpenSecureChannel(i.c, info, index, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes the applet and related package from the card.
|
||||
func (i *Installer) Delete() error {
|
||||
err := i.initGPSecureChannel(cardManagerAID)
|
||||
|
|
|
@ -6,9 +6,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
InsInit = uint8(0xFE)
|
||||
InsOpenSecureChannel = uint8(0x10)
|
||||
InsPair = uint8(0x12)
|
||||
InsInit = uint8(0xFE)
|
||||
InsOpenSecureChannel = uint8(0x10)
|
||||
InsMutuallyAuthenticate = uint8(0x11)
|
||||
InsPair = uint8(0x12)
|
||||
|
||||
TagSelectResponsePreInitialized = uint8(0x80)
|
||||
TagApplicationInfoTemplate = uint8(0xA4)
|
||||
|
@ -56,3 +57,13 @@ func NewCommandOpenSecureChannel(pairingIndex uint8, pubKey []byte) *apdu.Comman
|
|||
pubKey,
|
||||
)
|
||||
}
|
||||
|
||||
func NewCommandMutuallyAuthenticate(data []byte) *apdu.Command {
|
||||
return apdu.NewCommand(
|
||||
globalplatform.ClaGp,
|
||||
InsMutuallyAuthenticate,
|
||||
uint8(0x00),
|
||||
uint8(0x00),
|
||||
data,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
@ -63,10 +64,83 @@ func OneShotEncrypt(pubKeyData, secret, data []byte) ([]byte, error) {
|
|||
return encrypted, nil
|
||||
}
|
||||
|
||||
func appendPadding(blockSize int, data []byte) []byte {
|
||||
paddingSize := blockSize - (len(data)+1)%blockSize
|
||||
zeroes := bytes.Repeat([]byte{0x00}, paddingSize)
|
||||
padding := append([]byte{0x80}, zeroes...)
|
||||
func DeriveSessionKeys(secret, pairingKey, cardData []byte) ([]byte, []byte, []byte) {
|
||||
salt := cardData[:32]
|
||||
iv := cardData[32:]
|
||||
|
||||
return append(data, padding...)
|
||||
h := sha512.New()
|
||||
h.Write(secret)
|
||||
h.Write(pairingKey)
|
||||
h.Write(salt)
|
||||
data := h.Sum(nil)
|
||||
|
||||
encKey := data[:32]
|
||||
macKey := data[32:]
|
||||
|
||||
return encKey, macKey, iv
|
||||
}
|
||||
|
||||
func EncryptData(data []byte, encKey []byte, iv []byte) ([]byte, error) {
|
||||
data = appendPadding(16, data)
|
||||
|
||||
block, err := aes.NewCipher(encKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := make([]byte, len(data))
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(ciphertext, data)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func DecryptData(data []byte, encKey []byte, iv []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(encKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
plaintext := make([]byte, len(data))
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(plaintext, data)
|
||||
|
||||
return removePadding(16, plaintext), nil
|
||||
}
|
||||
|
||||
func CalculateMac(meta []byte, data []byte, macKey []byte) ([]byte, error) {
|
||||
data = appendPadding(16, data)
|
||||
|
||||
block, err := aes.NewCipher(macKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, make([]byte, 16))
|
||||
mode.CryptBlocks(meta, meta)
|
||||
mode.CryptBlocks(data, data)
|
||||
|
||||
mac := data[len(data)-32 : len(data)-16]
|
||||
|
||||
return mac, nil
|
||||
}
|
||||
|
||||
func appendPadding(blockSize int, data []byte) []byte {
|
||||
paddingSize := blockSize - (len(data) % blockSize)
|
||||
newData := make([]byte, len(data)+paddingSize)
|
||||
copy(newData, data)
|
||||
newData[len(data)] = 0x80
|
||||
|
||||
return newData
|
||||
}
|
||||
|
||||
func removePadding(blockSize int, data []byte) []byte {
|
||||
i := len(data) - 1
|
||||
for ; i > len(data)-blockSize; i-- {
|
||||
if data[i] == 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return data[:i]
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/status-im/hardware-wallet-go/hexutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -18,3 +19,68 @@ func TestECDH(t *testing.T) {
|
|||
|
||||
assert.Equal(t, sharedSecret1, sharedSecret2)
|
||||
}
|
||||
|
||||
func TestDeriveSessionKeys(t *testing.T) {
|
||||
secret := hexutils.HexToBytes("B410E816DA313545151807E25A830201FA389913A977066AB0C6DE0E8631E400")
|
||||
pairingKey := hexutils.HexToBytes("544FF0B9B0737E4BFC4ECDFCE09F522B837051BBE4FFCEC494FA420D8525670E")
|
||||
cardData := hexutils.HexToBytes("1D7C033E75E10EC578AB538F69F1B02538571BA3831441F1649E3F24B5B3E3E71D7BC2D6A3D02FC8CB2FBB3FD8711BB5")
|
||||
|
||||
encKey, macKey, iv := DeriveSessionKeys(secret, pairingKey, cardData)
|
||||
|
||||
expectedIV := "1D7BC2D6A3D02FC8CB2FBB3FD8711BB5"
|
||||
expectedEncKey := "4FF496554C01BAE0A52323E3481B448C99D43982118D95C6918FE0354D224B90"
|
||||
expectedMacKey := "185811013138EA1B4FFDBBFA7343EF2DBE3E54C2C231885E867F792448AC2FE5"
|
||||
|
||||
assert.Equal(t, expectedIV, hexutils.BytesToHex(iv))
|
||||
assert.Equal(t, expectedEncKey, hexutils.BytesToHex(encKey))
|
||||
assert.Equal(t, expectedMacKey, hexutils.BytesToHex(macKey))
|
||||
}
|
||||
|
||||
func TestEncryptData(t *testing.T) {
|
||||
data := hexutils.HexToBytes("A8A686D0E3290459BCB36088A8FD04A76BF13283BE4B1EAE2E1248EF609F94DC")
|
||||
encKey := hexutils.HexToBytes("44D689AB4B18206F7EEE5439FB9A71A8A617406BA5259728D1EBC2786D24896C")
|
||||
iv := hexutils.HexToBytes("9D3EF41EF1D221DD98A54AD5470F58F2")
|
||||
|
||||
encryptedData, err := EncryptData(data, encKey, iv)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := "FFB41FED5F71A2B57A6AE62D5D5ECD1C12616F6464637DD0A7A930920ACBA55867A7E12CC4F06B089AF34FF4ED4BAB08"
|
||||
assert.Equal(t, expected, hexutils.BytesToHex(encryptedData))
|
||||
}
|
||||
|
||||
func TestDecryptData(t *testing.T) {
|
||||
encData := hexutils.HexToBytes("73B58B66372E3446E14A9F54BA59666DB432E9DD87D24F9B0525180EE52DA2106E0C70EED7CD42B5B313E4443D6AC90D")
|
||||
encKey := hexutils.HexToBytes("D93D8E6164196D5C5B5F84F10E4B90D98F8D282ED145513ED666AA55C9871E79")
|
||||
iv := hexutils.HexToBytes("F959B1220333046D3C47D61B1E1B891B")
|
||||
|
||||
data, err := DecryptData(encData, encKey, iv)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := "2E21F9F2B2C2CC9038D518A5C6B490613E7955BD19D19108B77786986B7ABFE69000"
|
||||
assert.Equal(t, expected, hexutils.BytesToHex(data))
|
||||
}
|
||||
|
||||
func TestRemovePadding(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
data string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
"0180000000000000",
|
||||
"01",
|
||||
},
|
||||
{
|
||||
"0102800000000000",
|
||||
"0102",
|
||||
},
|
||||
{
|
||||
"01020304050607080102030405800000",
|
||||
"01020304050607080102030405",
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
res := removePadding(8, hexutils.HexToBytes(s.data))
|
||||
assert.Equal(t, s.expected, hexutils.BytesToHex(res))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package lightwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/status-im/hardware-wallet-go/apdu"
|
||||
|
@ -9,6 +11,8 @@ import (
|
|||
"github.com/status-im/hardware-wallet-go/lightwallet/crypto"
|
||||
)
|
||||
|
||||
var ErrInvalidResponseMAC = errors.New("invalid response MAC")
|
||||
|
||||
type SecureChannel struct {
|
||||
c globalplatform.Channel
|
||||
secret []byte
|
||||
|
@ -57,7 +61,52 @@ func (sc *SecureChannel) RawPublicKey() []byte {
|
|||
}
|
||||
|
||||
func (sc *SecureChannel) Send(cmd *apdu.Command) (*apdu.Response, error) {
|
||||
return sc.c.Send(cmd)
|
||||
encData, err := crypto.EncryptData(cmd.Data, sc.encKey, sc.iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
meta := []byte{cmd.Cla, cmd.Ins, cmd.P1, cmd.P2, byte(len(encData) + 16), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
if err = sc.updateIV(meta, encData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newData := append(sc.iv, encData...)
|
||||
cmd.Data = newData
|
||||
|
||||
resp, err := sc.c.Send(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.Sw != globalplatform.SwOK {
|
||||
return nil, apdu.NewErrBadResponse(resp.Sw, "unexpected sw in secure channel")
|
||||
}
|
||||
|
||||
rmeta := []byte{byte(len(resp.Data)), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
rmac := resp.Data[:len(sc.iv)]
|
||||
rdata := resp.Data[len(sc.iv):]
|
||||
plainData, err := crypto.DecryptData(rdata, sc.encKey, sc.iv)
|
||||
if err = sc.updateIV(rmeta, rdata); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !bytes.Equal(sc.iv, rmac) {
|
||||
return nil, ErrInvalidResponseMAC
|
||||
}
|
||||
|
||||
return apdu.ParseResponse(plainData)
|
||||
}
|
||||
|
||||
func (sc *SecureChannel) updateIV(meta, data []byte) error {
|
||||
mac, err := crypto.CalculateMac(meta, data, sc.macKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sc.iv = mac
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sc *SecureChannel) OneShotEncrypt(secrets *Secrets) ([]byte, error) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package lightwallet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/status-im/hardware-wallet-go/apdu"
|
||||
"github.com/status-im/hardware-wallet-go/hexutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type fakeChannel struct {
|
||||
lastCmd *apdu.Command
|
||||
}
|
||||
|
||||
func (fc *fakeChannel) Send(cmd *apdu.Command) (*apdu.Response, error) {
|
||||
fc.lastCmd = cmd
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestSecureChannel_Send(t *testing.T) {
|
||||
c := &fakeChannel{}
|
||||
sc := &SecureChannel{
|
||||
c: c,
|
||||
encKey: hexutils.HexToBytes("FDBCB1637597CF3F8F5E8263007D4E45F64C12D44066D4576EB1443D60AEF441"),
|
||||
macKey: hexutils.HexToBytes("2FB70219E6635EE0958AB3F7A428BA87E8CD6E6F873A5725A55F25B102D0F1F7"),
|
||||
iv: hexutils.HexToBytes("627E64358FA9BDCDAD4442BD8006E0A5"),
|
||||
}
|
||||
|
||||
data := hexutils.HexToBytes("D545A5E95963B6BCED86A6AE826D34C5E06AC64A1217EFFA1415A96674A82500")
|
||||
|
||||
cmd := NewCommandMutuallyAuthenticate(data)
|
||||
sc.Send(cmd)
|
||||
|
||||
expectedData := "BA796BF8FAD1FD50407B87127B94F5023EF8903AE926EAD8A204F961B8A0EDAEE7CCCFE7F7F6380CE2C6F188E598E4468B7DEDD0E807C18CCBDA71A55F3E1F9A"
|
||||
assert.Equal(t, expectedData, hexutils.BytesToHex(c.lastCmd.Data))
|
||||
|
||||
expectedIV := "BA796BF8FAD1FD50407B87127B94F502"
|
||||
assert.Equal(t, expectedIV, hexutils.BytesToHex(sc.iv))
|
||||
}
|
Loading…
Reference in New Issue