From 3727d89ae737e48f4747a7c9ce4c3da4726e97f4 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Thu, 28 Oct 2021 09:52:39 +0300 Subject: [PATCH] add load keys support --- examples/example-go/main.go | 34 ++++++++++++++++++----------- flow.go | 33 +++++++++++++++++++++++++++- flow_commands.go | 43 ++++++++++++++++++++++++++++--------- flow_types.go | 28 +++++++++++++----------- 4 files changed, 103 insertions(+), 35 deletions(-) diff --git a/examples/example-go/main.go b/examples/example-go/main.go index f35e5d5..bf29729 100644 --- a/examples/example-go/main.go +++ b/examples/example-go/main.go @@ -7,7 +7,6 @@ import ( "fmt" "os" "path/filepath" - "time" skg "github.com/status-im/status-keycard-go" "github.com/status-im/status-keycard-go/signal" @@ -15,9 +14,10 @@ import ( var flow *skg.KeycardFlow var finished chan (struct{}) -var ppIdx = 0 -var pairingPasses = [2]string{"WrongOne", "KeycardTest"} +var correctPairing = "KeycardTest" var correctPIN = "123456" +var correctPUK = "123456123456" +var keyUID = "136cbfc087cf7df6cf3248bce7563d4253b302b2f9e2b5eef8713fa5091409bc" func signalHandler(j []byte) { var sig signal.Envelope @@ -31,16 +31,23 @@ func signalHandler(j []byte) { case skg.CardInserted: fmt.Printf("Card inserted\n") case skg.SwapCard: - fmt.Printf("Swap card. You have 5 seconds\n") - time.Sleep(5 * time.Second) - flow.Resume(skg.FlowParams{}) + fmt.Printf("Swap card. Changing constraint\n") + flow.Resume(skg.FlowParams{skg.KeyUID: keyUID}) case skg.EnterPairing: - fmt.Printf("Entering pass: %+v\n", pairingPasses[ppIdx]) - flow.Resume(skg.FlowParams{skg.PairingPass: pairingPasses[ppIdx]}) - ppIdx = (ppIdx + 1) % 2 + fmt.Printf("Entering pass: %+v\n", correctPairing) + flow.Resume(skg.FlowParams{skg.PairingPass: correctPairing}) case skg.EnterPIN: fmt.Printf("Entering PIN: %+v\n", correctPIN) flow.Resume(skg.FlowParams{skg.PIN: correctPIN}) + case skg.EnterNewPIN: + fmt.Printf("Creating PIN: %+v\n", correctPIN) + flow.Resume(skg.FlowParams{skg.NewPIN: correctPIN}) + case skg.EnterNewPUK: + fmt.Printf("Creating PUK: %+v\n", correctPUK) + flow.Resume(skg.FlowParams{skg.NewPUK: correctPUK}) + case skg.EnterNewPair: + fmt.Printf("Creating pairing: %+v\n", correctPairing) + flow.Resume(skg.FlowParams{skg.NewPairing: correctPairing}) case skg.FlowResult: fmt.Printf("Flow result: %+v\n", sig.Event) close(finished) @@ -90,10 +97,13 @@ func main() { signal.SetKeycardSignalHandler(signalHandler) + testFlow(skg.GetAppInfo, skg.FlowParams{skg.FactoryReset: true}) + testFlow(skg.LoadAccount, skg.FlowParams{skg.Mnemonic: "receive fan copper bracket end train again sustain wet siren throw cigar"}) + testFlow(skg.UnpairThis, skg.FlowParams{skg.PIN: correctPIN}) + testFlow(skg.RecoverAccount, skg.FlowParams{skg.PairingPass: "WrongPass", skg.PIN: "234567"}) + testFlow(skg.Login, skg.FlowParams{skg.KeyUID: "60a78c98d5dd659f714eb7072bfb2c0d8a65f74a8f6aff7bb27cf56ae1feec17"}) testFlow(skg.GetAppInfo, skg.FlowParams{}) - testFlow(skg.RecoverAccount, skg.FlowParams{skg.PIN: "234567"}) - testFlow(skg.Login, skg.FlowParams{}) - testFlow(skg.GetAppInfo, skg.FlowParams{}) + testFlow(skg.ExportPublic, skg.FlowParams{skg.BIP44Path: "m/44'/60'/0'/0/1"}) 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 0bff424..d18d23d 100644 --- a/flow.go +++ b/flow.go @@ -101,6 +101,7 @@ func (f *KeycardFlow) runFlow() { signal.Send(FlowResult, result) } + f.params = nil f.state = Idle } @@ -158,6 +159,18 @@ func (f *KeycardFlow) requireKeys() error { return f.pauseAndRestart(SwapCard, ErrorNoKeys) } +func (f *KeycardFlow) requireNoKeys() error { + if f.cardInfo.keyUID == "" { + return nil + } + + if overwrite, ok := f.params[Overwrite]; ok && overwrite.(bool) { + return nil + } + + return f.pauseAndRestart(SwapCard, ErrorHasKeys) +} + func (f *KeycardFlow) closeKeycard(kc *keycardContext) { if kc != nil { kc.stop() @@ -336,7 +349,25 @@ func (f *KeycardFlow) exportPublicFlow(kc *keycardContext) (FlowStatus, error) { } func (f *KeycardFlow) loadKeysFlow(kc *keycardContext) (FlowStatus, error) { - return nil, errors.New("not implemented yet") + err := f.requireNoKeys() + + if err != nil { + return nil, err + } + + err = f.openSCAndAuthenticate(kc, false) + + if err != nil { + return nil, err + } + + err = f.loadKeys(kc) + + if err != nil { + return nil, err + } + + return FlowStatus{KeyUID: f.cardInfo.keyUID}, nil } func (f *KeycardFlow) signFlow(kc *keycardContext) (FlowStatus, error) { diff --git a/flow_commands.go b/flow_commands.go index e42d8a5..7a2ed44 100644 --- a/flow_commands.go +++ b/flow_commands.go @@ -101,15 +101,17 @@ func (f *KeycardFlow) initCard(kc *keycardContext) error { err := kc.init(newPIN.(string), newPUK.(string), newPairing.(string)) - if err == nil { - f.params[PIN] = newPIN - f.params[PairingPass] = newPairing - delete(f.params, NewPIN) - delete(f.params, NewPUK) - delete(f.params, NewPairing) + if err != nil { + return err } - return err + f.params[PIN] = newPIN + f.params[PairingPass] = newPairing + delete(f.params, NewPIN) + delete(f.params, NewPUK) + delete(f.params, NewPairing) + + return restartErr() } func (f *KeycardFlow) openSC(kc *keycardContext, giveup bool) error { @@ -283,9 +285,7 @@ func (f *KeycardFlow) exportKey(kc *keycardContext, path string, onlyPublic bool } func (f *KeycardFlow) exportBIP44Key(kc *keycardContext) (*KeyPair, error) { - path, ok := f.params[BIP44Path] - - if ok { + if path, ok := f.params[BIP44Path]; ok { return f.exportKey(kc, path.(string), true) } @@ -298,6 +298,29 @@ func (f *KeycardFlow) exportBIP44Key(kc *keycardContext) (*KeyPair, error) { return f.exportBIP44Key(kc) } +func (f *KeycardFlow) loadKeys(kc *keycardContext) error { + if mnemonic, ok := f.params[Mnemonic]; ok { + keyUID, err := kc.loadMnemonic(mnemonic.(string), "") + + if isSCardError(err) { + return restartErr() + } else if err != nil { + return err + } + + f.cardInfo.keyUID = btox(keyUID) + return nil + } + + err := f.pauseAndWait(EnterMnemonic, ErrorLoading) + + if err != nil { + return err + } + + return f.loadKeys(kc) +} + func (f *KeycardFlow) changePIN(kc *keycardContext) error { if newPIN, ok := f.params[NewPIN]; ok { err := kc.changePin(newPIN.(string)) diff --git a/flow_types.go b/flow_types.go index 6f5c8aa..786b575 100644 --- a/flow_types.go +++ b/flow_types.go @@ -48,18 +48,19 @@ const ( ) const ( - FlowResult = "keycard.flow-result" - InsertCard = "keycard.action.insert-card" - CardInserted = "keycard.action.card-inserted" - SwapCard = "keycard.action.swap-card" - EnterPairing = "keycard.action.enter-pairing" - EnterPIN = "keycard.action.enter-pin" - EnterPUK = "keycard.action.enter-puk" - EnterNewPair = "keycard.action.enter-new-pairing" - EnterNewPIN = "keycard.action.enter-new-pin" - EnterNewPUK = "keycard.action.enter-new-puk" - EnterTXHash = "keycard.action.enter-tx-hash" - EnterPath = "keycard.action.enter-bip44-path" + FlowResult = "keycard.flow-result" + InsertCard = "keycard.action.insert-card" + CardInserted = "keycard.action.card-inserted" + SwapCard = "keycard.action.swap-card" + EnterPairing = "keycard.action.enter-pairing" + EnterPIN = "keycard.action.enter-pin" + EnterPUK = "keycard.action.enter-puk" + EnterNewPair = "keycard.action.enter-new-pairing" + EnterNewPIN = "keycard.action.enter-new-pin" + EnterNewPUK = "keycard.action.enter-new-puk" + EnterTXHash = "keycard.action.enter-tx-hash" + EnterPath = "keycard.action.enter-bip44-path" + EnterMnemonic = "keycard.action.enter-mnemonic" ) const ( @@ -70,12 +71,14 @@ const ( ErrorUnknownFlow = "unknown-flow" ErrorNotAKeycard = "not-a-keycard" ErrorNoKeys = "no-keys" + ErrorHasKeys = "has-keys" ErrorRequireInit = "require-init" ErrorPairing = "pairing" ErrorUnblocking = "unblocking" ErrorSigning = "signing" ErrorExporting = "exporting" ErrorChanging = "changing-credentials" + ErrorLoading = "loading-keys" ) const ( @@ -104,6 +107,7 @@ const ( TXHash = "tx-hash" BIP44Path = "bip44-path" TXSignature = "tx-signature" + Overwrite = "overwrite" ) const (