From e3c16d0e571d56e23e81c06441212b5c708e6be2 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Wed, 27 Oct 2021 08:46:00 +0300 Subject: [PATCH] implement sign flow --- examples/example-go/main.go | 1 + flow.go | 31 +++++++++++------- flow_commands.go | 65 +++++++++++++++++++++++++++++++++++-- types.go | 12 +++---- utils.go | 16 +++++++-- 5 files changed, 103 insertions(+), 22 deletions(-) diff --git a/examples/example-go/main.go b/examples/example-go/main.go index 7b0fcdd..f35e5d5 100644 --- a/examples/example-go/main.go +++ b/examples/example-go/main.go @@ -94,5 +94,6 @@ func main() { testFlow(skg.RecoverAccount, skg.FlowParams{skg.PIN: "234567"}) testFlow(skg.Login, skg.FlowParams{}) testFlow(skg.GetAppInfo, skg.FlowParams{}) + testFlow(skg.Sign, skg.FlowParams{skg.TXHash: "60a78c98d5dd659f714eb7072bfb2c0d8a65f74a8f6aff7bb27cf56ae1feec17", skg.BIP44Path: "m/44'/60'/0'/0/0"}) testFlow(skg.UnpairThis, skg.FlowParams{skg.PIN: correctPIN}) } diff --git a/flow.go b/flow.go index 01ca262..0bff424 100644 --- a/flow.go +++ b/flow.go @@ -326,17 +326,8 @@ func (f *KeycardFlow) exportPublicFlow(kc *keycardContext) (FlowStatus, error) { return nil, err } - path, ok := f.params[BIP44Path] + key, err := f.exportBIP44Key(kc) - if !ok { - err := f.pauseAndWait(EnterPath, ErrorExporting) - - if err != nil { - return nil, err - } - } - - key, err := f.exportKey(kc, path.(string), true) if err != nil { return nil, err } @@ -349,7 +340,25 @@ func (f *KeycardFlow) loadKeysFlow(kc *keycardContext) (FlowStatus, error) { } func (f *KeycardFlow) signFlow(kc *keycardContext) (FlowStatus, error) { - return nil, errors.New("not implemented yet") + err := f.requireKeys() + + if err != nil { + return nil, err + } + + err = f.openSCAndAuthenticate(kc, false) + + if err != nil { + return nil, err + } + + signature, err := f.sign(kc) + + if err != nil { + return nil, err + } + + return FlowStatus{KeyUID: f.cardInfo.keyUID, TXSignature: signature}, nil } func (f *KeycardFlow) changePINFlow(kc *keycardContext) (FlowStatus, error) { diff --git a/flow_commands.go b/flow_commands.go index 38debc4..6af7afb 100644 --- a/flow_commands.go +++ b/flow_commands.go @@ -12,8 +12,8 @@ func (f *KeycardFlow) factoryReset(kc *keycardContext) error { func (f *KeycardFlow) selectKeycard(kc *keycardContext) error { appInfo, err := kc.selectApplet() - f.cardInfo.instanceUID = tox(appInfo.InstanceUID) - f.cardInfo.keyUID = tox(appInfo.KeyUID) + f.cardInfo.instanceUID = btox(appInfo.InstanceUID) + f.cardInfo.keyUID = btox(appInfo.KeyUID) f.cardInfo.freeSlots = bytesToInt(appInfo.AvailableSlots) if err != nil { @@ -280,6 +280,22 @@ func (f *KeycardFlow) exportKey(kc *keycardContext, path string, onlyPublic bool return keyPair, err } +func (f *KeycardFlow) exportBIP44Key(kc *keycardContext) (*KeyPair, error) { + path, ok := f.params[BIP44Path] + + if ok { + return f.exportKey(kc, path.(string), true) + } + + err := f.pauseAndWait(EnterPath, ErrorExporting) + + if err != nil { + return nil, err + } + + return f.exportBIP44Key(kc) +} + func (f *KeycardFlow) changePIN(kc *keycardContext) error { if newPIN, ok := f.params[NewPIN]; ok { err := kc.changePin(newPIN.(string)) @@ -345,3 +361,48 @@ func (f *KeycardFlow) changePairing(kc *keycardContext) error { return f.changePairing(kc) } + +func (f *KeycardFlow) sign(kc *keycardContext) (*Signature, error) { + var err error + + path, pathOK := f.params[BIP44Path] + + if !pathOK { + err = f.pauseAndWait(EnterPath, ErrorSigning) + if err != nil { + return nil, err + } + + return f.sign(kc) + } + + hash, hashOK := f.params[TXHash] + + var rawHash []byte + + if hashOK { + rawHash, err = xtob(hash.(string)) + if err != nil { + hashOK = false + } + } + + if !hashOK { + err := f.pauseAndWait(EnterTXHash, ErrorSigning) + if err != nil { + return nil, err + } + + return f.sign(kc) + } + + signature, err := kc.signWithPath(rawHash, path.(string)) + + if isSCardError(err) { + return nil, restartErr() + } else if err != nil { + return nil, err + } + + return toSignature(signature), nil +} diff --git a/types.go b/types.go index 8a7dbdf..e7823d1 100644 --- a/types.go +++ b/types.go @@ -1,7 +1,6 @@ package statuskeycardgo import ( - "encoding/hex" "encoding/json" ) @@ -9,7 +8,7 @@ type hexString []byte // MarshalJSON serializes hexString to hex func (s hexString) MarshalJSON() ([]byte, error) { - bytes, err := json.Marshal(tox(s)) + bytes, err := json.Marshal(btox(s)) return bytes, err } @@ -20,7 +19,7 @@ func (s *hexString) UnmarshalJSON(data []byte) error { if err != nil { return err } - str, err := hex.DecodeString(x) + str, err := xtob(x) if err != nil { return err } @@ -79,10 +78,9 @@ type unpairParams struct { } type Signature struct { - PublicKey hexString `json:"publicKey"` - R hexString `json:"r"` - S hexString `json:"s"` - V byte `json:"v"` + R hexString `json:"r"` + S hexString `json:"s"` + V byte `json:"v"` } type Capability uint8 diff --git a/utils.go b/utils.go index 0b67eda..ac1bdff 100644 --- a/utils.go +++ b/utils.go @@ -29,7 +29,7 @@ func retValue(pairs ...interface{}) *C.char { } func isSCardError(err error) bool { - _, ok := err.(*scard.Error) + _, ok := err.(scard.Error) return ok } @@ -43,10 +43,14 @@ func getRetries(err error) (int, bool) { } } -func tox(bytes []byte) string { +func btox(bytes []byte) string { return hex.EncodeToString(bytes) } +func xtob(str string) ([]byte, error) { + return hex.DecodeString(str) +} + func bytesToInt(s []byte) int { if len(s) > 4 { return 0 @@ -73,3 +77,11 @@ func toPairInfo(r *ktypes.PairingInfo) *PairingInfo { Index: r.Index, } } + +func toSignature(r *ktypes.Signature) *Signature { + return &Signature{ + R: r.R(), + S: r.S(), + V: r.V(), + } +}