support exporting xpub keys

This commit is contained in:
Michele Balistreri 2024-11-29 11:22:11 +09:00
parent 5bb74ca24f
commit c87945d752
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
2 changed files with 49 additions and 17 deletions

View File

@ -316,6 +316,23 @@ func (cs *CommandSet) DeriveKey(path string) error {
}
func (cs *CommandSet) ExportKey(derive bool, makeCurrent bool, onlyPublic bool, path string) ([]byte, []byte, error) {
var p2 uint8
if onlyPublic {
p2 = P2ExportKeyPublicOnly
} else {
p2 = P2ExportKeyPrivateAndPublic
}
key, err := cs.ExportKeyExtended(derive, makeCurrent, p2, path)
if err != nil {
return nil, nil, err
}
return key.PrivKey(), key.PubKey(), err
}
func (cs *CommandSet) ExportKeyExtended(derive bool, makeCurrent bool, p2 uint8, path string) (*types.ExportedKey, error) {
var p1 uint8
if !derive {
p1 = P1ExportKeyCurrent
@ -324,22 +341,16 @@ func (cs *CommandSet) ExportKey(derive bool, makeCurrent bool, onlyPublic bool,
} else {
p1 = P1ExportKeyDeriveAndMakeCurrent
}
var p2 uint8
if onlyPublic {
p2 = P2ExportKeyPublicOnly
} else {
p2 = P2ExportKeyPrivateAndPublic
}
cmd, err := NewCommandExportKey(p1, p2, path)
if err != nil {
return nil, nil, err
return nil, err
}
resp, err := cs.sc.Send(cmd)
err = cs.checkOK(resp, err)
if err != nil {
return nil, nil, err
return nil, err
}
return types.ParseExportKeyResponse(resp.Data)

View File

@ -8,29 +8,50 @@ import (
)
var (
TagExportKeyTemplate = uint8(0xA1)
TagExportKeyPublic = uint8(0x81)
TagExportKeyTemplate = apdu.Tag{0xA1}
TagExportKeyPublic = apdu.Tag{0x80}
TagExportKeyPrivate = apdu.Tag{0x81}
TagExportKeyPublicChain = apdu.Tag{0x82}
)
func ParseExportKeyResponse(data []byte) ([]byte, []byte, error) {
tpl, err := apdu.FindTag(data, apdu.Tag{0xA1})
type ExportedKey struct {
pubKey []byte
privKey []byte
chainCode []byte
}
func (k *ExportedKey) PubKey() []byte {
return k.pubKey
}
func (k *ExportedKey) PrivKey() []byte {
return k.privKey
}
func (k *ExportedKey) ChainCode() []byte {
return k.chainCode
}
func ParseExportKeyResponse(data []byte) (*ExportedKey, error) {
tpl, err := apdu.FindTag(data, TagExportKeyTemplate)
if err != nil {
return nil, nil, err
return nil, err
}
pubKey := tryFindTag(tpl, apdu.Tag{0x80})
privKey := tryFindTag(tpl, apdu.Tag{0x81})
pubKey := tryFindTag(tpl, TagExportKeyPublic)
privKey := tryFindTag(tpl, TagExportKeyPrivate)
chainCode := tryFindTag(tpl, TagExportKeyPublicChain)
if len(pubKey) == 0 && len(privKey) > 0 {
ecdsaKey, err := ethcrypto.HexToECDSA(fmt.Sprintf("%x", privKey))
if err != nil {
return nil, nil, err
return nil, err
}
pubKey = ethcrypto.FromECDSAPub(&ecdsaKey.PublicKey)
}
return privKey, pubKey, nil
return &ExportedKey{pubKey, privKey, chainCode}, nil
}
func tryFindTag(tpl []byte, tags ...apdu.Tag) []byte {