mirror of
https://github.com/status-im/keycard-cli.git
synced 2025-02-28 11:50:43 +00:00
add keycard-sign-with-path command
This commit is contained in:
parent
9ab74c9fb1
commit
5d79f7868f
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -42,7 +42,7 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "develop"
|
||||
digest = "1:641843b5cf82353b41cdd2e93f7d9009ea761434b2a085279455036c4d10c95e"
|
||||
digest = "1:428d2c2f86c07c78f39d379b809c317b3792d0248e76d60bf78dcf101596c770"
|
||||
name = "github.com/status-im/keycard-go"
|
||||
packages = [
|
||||
".",
|
||||
@ -57,7 +57,7 @@
|
||||
"types",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "f383a0d5830c5eee07e25cdd2d38ed76a19ec7f1"
|
||||
revision = "9d48af884d5b92339229bf57df18d0f882ba70be"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
24
shell.go
24
shell.go
@ -138,6 +138,7 @@ func NewShell(t keycardio.Transmitter) *Shell {
|
||||
"keycard-remove-key": s.commandKeycardRemoveKey,
|
||||
"keycard-derive-key": s.commandKeycardDeriveKey,
|
||||
"keycard-sign": s.commandKeycardSign,
|
||||
"keycard-sign-with-path": s.commandKeycardSignWithPath,
|
||||
"keycard-sign-message": s.commandKeycardSignMessage,
|
||||
"keycard-sign-pinless": s.commandKeycardSignPinless,
|
||||
"keycard-sign-message-pinless": s.commandKeycardSignMessagePinless,
|
||||
@ -680,6 +681,29 @@ func (s *Shell) commandKeycardSign(args ...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Shell) commandKeycardSignWithPath(args ...string) error {
|
||||
if err := s.requireArgs(args, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := s.parseHex(args[0])
|
||||
if err != nil {
|
||||
logger.Error("failed parsing hex data", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("sign with path")
|
||||
sig, err := s.kCmdSet.SignWithPath(data, args[1])
|
||||
if err != nil {
|
||||
logger.Error("sign with path failed", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
s.writeSignatureInfo(sig)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Shell) commandKeycardSignMessage(args ...string) error {
|
||||
if len(args) < 1 {
|
||||
return errors.New("keycard-sign-message require at least 1 parameter")
|
||||
|
47
vendor/github.com/status-im/keycard-go/command_set.go
generated
vendored
47
vendor/github.com/status-im/keycard-go/command_set.go
generated
vendored
@ -229,6 +229,35 @@ func (cs *CommandSet) DeriveKey(path string) error {
|
||||
return cs.checkOK(resp, err)
|
||||
}
|
||||
|
||||
func (cs *CommandSet) ExportKey(derive bool, makeCurrent bool, onlyPublic bool, path string) ([]byte, error) {
|
||||
var p1 uint8
|
||||
if derive == false {
|
||||
p1 = P1ExportKeyCurrent
|
||||
} else if makeCurrent == false {
|
||||
p1 = P1ExportKeyDerive
|
||||
} else {
|
||||
p1 = P1ExportKeyDeriveAndMakeCurrent
|
||||
}
|
||||
var p2 uint8
|
||||
if onlyPublic == true {
|
||||
p2 = P2ExportKeyPublicOnly
|
||||
} else {
|
||||
p2 = P2ExportKeyPrivateAndPublic
|
||||
}
|
||||
cmd, err := NewCommandExportKey(p1, p2, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := cs.sc.Send(cmd)
|
||||
err = cs.checkOK(resp, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Data, nil
|
||||
|
||||
}
|
||||
|
||||
func (cs *CommandSet) SetPinlessPath(path string) error {
|
||||
cmd, err := NewCommandSetPinlessPath(path)
|
||||
if err != nil {
|
||||
@ -240,7 +269,21 @@ func (cs *CommandSet) SetPinlessPath(path string) error {
|
||||
}
|
||||
|
||||
func (cs *CommandSet) Sign(data []byte) (*types.Signature, error) {
|
||||
cmd, err := NewCommandSign(data, P1SignCurrentKey)
|
||||
cmd, err := NewCommandSign(data, P1SignCurrentKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := cs.sc.Send(cmd)
|
||||
if err = cs.checkOK(resp, err); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return types.ParseSignature(data, resp.Data)
|
||||
}
|
||||
|
||||
func (cs *CommandSet) SignWithPath(data []byte, path string) (*types.Signature, error) {
|
||||
cmd, err := NewCommandSign(data, P1SignDerive, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -254,7 +297,7 @@ func (cs *CommandSet) Sign(data []byte) (*types.Signature, error) {
|
||||
}
|
||||
|
||||
func (cs *CommandSet) SignPinless(data []byte) (*types.Signature, error) {
|
||||
cmd, err := NewCommandSign(data, P1SignPinless)
|
||||
cmd, err := NewCommandSign(data, P1SignPinless, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
118
vendor/github.com/status-im/keycard-go/commands.go
generated
vendored
118
vendor/github.com/status-im/keycard-go/commands.go
generated
vendored
@ -22,23 +22,30 @@ const (
|
||||
InsVerifyPIN = 0x20
|
||||
InsChangePIN = 0x21
|
||||
InsDeriveKey = 0xD1
|
||||
InsExportKey = 0xC2
|
||||
InsSign = 0xC0
|
||||
InsSetPinlessPath = 0xC1
|
||||
|
||||
P1PairingFirstStep = 0x00
|
||||
P1PairingFinalStep = 0x01
|
||||
P1GetStatusApplication = 0x00
|
||||
P1GetStatusKeyPath = 0x01
|
||||
P1DeriveKeyFromMaster = 0x00
|
||||
P1DeriveKeyFromParent = 0x40
|
||||
P1DeriveKeyFromCurrent = 0x80
|
||||
P1ChangePinPIN = 0x00
|
||||
P1ChangePinPUK = 0x01
|
||||
P1ChangePinPairingSecret = 0x02
|
||||
P1SignCurrentKey = 0x00
|
||||
P1SignDerive = 0x01
|
||||
P1SignDeriveAndMakeCurrent = 0x02
|
||||
P1SignPinless = 0x03
|
||||
P1PairingFirstStep = 0x00
|
||||
P1PairingFinalStep = 0x01
|
||||
P1GetStatusApplication = 0x00
|
||||
P1GetStatusKeyPath = 0x01
|
||||
P1DeriveKeyFromMaster = 0x00
|
||||
P1DeriveKeyFromParent = 0x40
|
||||
P1DeriveKeyFromCurrent = 0x80
|
||||
P1ChangePinPIN = 0x00
|
||||
P1ChangePinPUK = 0x01
|
||||
P1ChangePinPairingSecret = 0x02
|
||||
P1SignCurrentKey = 0x00
|
||||
P1SignDerive = 0x01
|
||||
P1SignDeriveAndMakeCurrent = 0x02
|
||||
P1SignPinless = 0x03
|
||||
P1ExportKeyCurrent = uint8(0x00)
|
||||
P1ExportKeyDerive = uint8(0x01)
|
||||
P1ExportKeyDeriveAndMakeCurrent = uint8(0x02)
|
||||
|
||||
P2ExportKeyPrivateAndPublic = uint8(0x00)
|
||||
P2ExportKeyPublicOnly = uint8(0x01)
|
||||
|
||||
SwNoAvailablePairingSlots = 0x6A84
|
||||
)
|
||||
@ -179,16 +186,9 @@ func NewCommandDeriveKey(pathStr string) (*apdu.Command, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var p1 uint8
|
||||
switch startingPoint {
|
||||
case derivationpath.StartingPointMaster:
|
||||
p1 = P1DeriveKeyFromMaster
|
||||
case derivationpath.StartingPointParent:
|
||||
p1 = P1DeriveKeyFromParent
|
||||
case derivationpath.StartingPointCurrent:
|
||||
p1 = P1DeriveKeyFromCurrent
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid startingPoint %d", startingPoint)
|
||||
p1, err := derivationP1FromStartingPoint(startingPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := new(bytes.Buffer)
|
||||
@ -207,6 +207,43 @@ func NewCommandDeriveKey(pathStr string) (*apdu.Command, error) {
|
||||
), nil
|
||||
}
|
||||
|
||||
// Export a key
|
||||
// @param {p1}
|
||||
// 0x00: current key - returns the key that is currently loaded and ready for signing. Does not use derivation path
|
||||
// 0x01: derive - returns derived key
|
||||
// 0x02: derive and make current - returns derived key and also sets it to the current key
|
||||
// @param {p2}
|
||||
// 0x00: return public and private key pair
|
||||
// 0x01: return only the public key
|
||||
// @param {pathStr}
|
||||
// Derivation path of format "m/x/x/x/x/x", e.g. "m/44'/0'/0'/0/0"
|
||||
func NewCommandExportKey(p1 uint8, p2 uint8, pathStr string) (*apdu.Command, error) {
|
||||
startingPoint, path, err := derivationpath.Decode(pathStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deriveP1, err := derivationP1FromStartingPoint(startingPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := new(bytes.Buffer)
|
||||
for _, segment := range path {
|
||||
if err := binary.Write(data, binary.BigEndian, segment); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return apdu.NewCommand(
|
||||
globalplatform.ClaGp,
|
||||
InsExportKey,
|
||||
p1|deriveP1,
|
||||
p2,
|
||||
data.Bytes(),
|
||||
), nil
|
||||
}
|
||||
|
||||
func NewCommandSetPinlessPath(pathStr string) (*apdu.Command, error) {
|
||||
startingPoint, path, err := derivationpath.Decode(pathStr)
|
||||
if err != nil {
|
||||
@ -233,11 +270,27 @@ func NewCommandSetPinlessPath(pathStr string) (*apdu.Command, error) {
|
||||
), nil
|
||||
}
|
||||
|
||||
func NewCommandSign(data []byte, p1 uint8) (*apdu.Command, error) {
|
||||
func NewCommandSign(data []byte, p1 uint8, pathStr string) (*apdu.Command, error) {
|
||||
if len(data) != 32 {
|
||||
return nil, fmt.Errorf("data length must be 32, got %d", len(data))
|
||||
}
|
||||
|
||||
if p1 == P1SignDerive || p1 == P1SignDeriveAndMakeCurrent {
|
||||
_, path, err := derivationpath.Decode(pathStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pathData := new(bytes.Buffer)
|
||||
for _, segment := range path {
|
||||
if err := binary.Write(pathData, binary.BigEndian, segment); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
data = append(data, pathData.Bytes()...)
|
||||
}
|
||||
|
||||
return apdu.NewCommand(
|
||||
globalplatform.ClaGp,
|
||||
InsSign,
|
||||
@ -246,3 +299,18 @@ func NewCommandSign(data []byte, p1 uint8) (*apdu.Command, error) {
|
||||
data,
|
||||
), nil
|
||||
}
|
||||
|
||||
// Internal function. Get the type of starting point for the derivation path.
|
||||
// Used for both DeriveKey and ExportKey
|
||||
func derivationP1FromStartingPoint(s derivationpath.StartingPoint) (uint8, error) {
|
||||
switch s {
|
||||
case derivationpath.StartingPointMaster:
|
||||
return P1DeriveKeyFromMaster, nil
|
||||
case derivationpath.StartingPointParent:
|
||||
return P1DeriveKeyFromParent, nil
|
||||
case derivationpath.StartingPointCurrent:
|
||||
return P1DeriveKeyFromCurrent, nil
|
||||
default:
|
||||
return uint8(0), fmt.Errorf("invalid startingPoint %d", s)
|
||||
}
|
||||
}
|
||||
|
2
vendor/github.com/status-im/keycard-go/types/types.go
generated
vendored
2
vendor/github.com/status-im/keycard-go/types/types.go
generated
vendored
@ -10,4 +10,4 @@ type Channel interface {
|
||||
type PairingInfo struct {
|
||||
Key []byte
|
||||
Index int
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user