[keycard] Allow to restore kk multiacc using pairing

This commit is contained in:
Roman Volosovskyi 2020-07-06 15:08:26 +03:00
parent 79cf87be86
commit 5101d4d6a5
No known key found for this signature in database
GPG Key ID: 0238A4B5ECEE70DE
5 changed files with 165 additions and 55 deletions

View File

@ -19,6 +19,7 @@
keycard-match? (= keycard-instance-uid instance-uid) keycard-match? (= keycard-instance-uid instance-uid)
hash (get-in db [:hardwallet :hash]) hash (get-in db [:hardwallet :hash])
data (get-in db [:hardwallet :data]) data (get-in db [:hardwallet :data])
typed? (get-in db [:hardwallet :typed?])
pin (common/vector->string (get-in db [:hardwallet :pin :sign])) pin (common/vector->string (get-in db [:hardwallet :pin :sign]))
from (get-in db [:signing/tx :from :address]) from (get-in db [:signing/tx :from :address])
path (reduce path (reduce
@ -35,6 +36,7 @@
:hardwallet/sign {:hash (ethereum/naked-address hash) :hardwallet/sign {:hash (ethereum/naked-address hash)
:data data :data data
:pairing pairing :pairing pairing
:typed? typed?
:pin pin :pin pin
:path path}} :path path}}
(fx/merge cofx (fx/merge cofx

View File

@ -9,7 +9,8 @@
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[clojure.string :as string] [clojure.string :as string]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[status-im.multiaccounts.create.core :as multiaccounts.create]))
(def initial-state (def initial-state
{:card-connected? false {:card-connected? false
@ -36,6 +37,23 @@
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])}) :key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
(connect-card)) (connect-card))
(def initialization (atom false))
(defn connect-pairing-card []
(reset! initialization false)
(swap! state assoc :application-info
{:free-pairing-slots 5
:app-version "2.2"
:secure-channel-pub-key "04c3071768912a515c00aeab7ceb8a5bfda91d036f4a4e60b7944cee3ca7fb67b6d118e8df1e2480b87fd636c6615253245bbbc93a6a407f155f2c58f76c96ef0e",
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:paired? true
:has-master-key? true
:initialized? true
:pin-retry-counter 3
:puk-retry-counter 5
:key-uid "0x16839e8b1b8a395acb18100c7e2b161701c225adf31eefa02114099b4d81a30b"})
(connect-card))
(defn disconnect-card [] (defn disconnect-card []
(swap! state assoc :card-connected? false) (swap! state assoc :card-connected? false)
(doseq [callback (vals (get @state :on-card-disconnected))] (doseq [callback (vals (get @state :on-card-disconnected))]
@ -45,7 +63,8 @@
(reset! state initial-state)) (reset! state initial-state))
(defn- later [f] (defn- later [f]
(utils/set-timeout f 500)) (when f
(utils/set-timeout f 500)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -88,6 +107,7 @@
(def kk1-password "000000") (def kk1-password "000000")
(def default-puk "000000000000") (def default-puk "000000000000")
(defn init-card [{:keys [pin on-success]}] (defn init-card [{:keys [pin on-success]}]
(reset! initialization true)
(swap! state assoc :application-info (swap! state assoc :application-info
{:free-pairing-slots 5 {:free-pairing-slots 5
:app-version "2.2" :app-version "2.2"
@ -107,48 +127,84 @@
(def kk1-pair "ADEol+GCD67EO7zU6ko0DNK7XrNs9w2+h9GxcibNY4yf") (def kk1-pair "ADEol+GCD67EO7zU6ko0DNK7XrNs9w2+h9GxcibNY4yf")
(def derived-acc (atom nil))
(defn multiaccount->keys [pin data]
(let [{:keys [selected-id multiaccounts root-key derived]}
data
{:keys [id address public-key derived key-uid]}
(or (->> multiaccounts
(filter #(= (:id %) selected-id))
first)
(assoc root-key :derived derived))
whisper (get derived constants/path-whisper-keyword)
wallet (get derived constants/path-default-wallet-keyword)
wallet-root (get derived constants/path-wallet-root-keyword)
password (ethereum/sha3 pin)
response {:key-uid key-uid
:encryption-public-key password
:address address
:whisper-public-key (:public-key whisper)
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:wallet-root-public-key (:public-key wallet-root)
:wallet-root-address (:address wallet-root)
:whisper-address (:address whisper)
:public-key public-key
:whisper-private-key "34bc7d0c258c4f2ac1dac4fd6c55c9478bac1f4a9d8b9f1152c8551ab7187b43"
:wallet-address (:address wallet)
:wallet-public-key (:public-key wallet)}]
[id response]))
(defn pair [{:keys [password on-success]}] (defn pair [{:keys [password on-success]}]
(when (and (not @initialization)
(not @derived-acc))
(status/multiaccount-import-mnemonic
"night fortune spider version version armed amused winner matter tonight cave flag"
nil
(fn [result]
(let [{:keys [id] :as root-data}
(multiaccounts.create/normalize-multiaccount-data-keys
(types/json->clj result))]
(status-im.native-module.core/multiaccount-derive-addresses
id
[constants/path-wallet-root
constants/path-eip1581
constants/path-whisper
constants/path-default-wallet]
(fn [result]
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
(types/json->clj result))
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
public-key
(fn [name photo-path]
(let [derived-data-extended
(update derived-data
constants/path-whisper-keyword
merge {:name name :photo-path photo-path})]
(reset! derived-acc
{:root-key root-data
:derived derived-data-extended})))))))))))
(when (= password kk1-password) (when (= password kk1-password)
(later #(on-success kk1-pair)))) (later #(on-success (str (rand-int 10000000))))))
(defn generate-and-load-key (defn generate-and-load-key
[{:keys [pin pairing on-success]}] [{:keys [pin on-success]}]
(when (and (= pin (get @state :pin)) (when (= pin (get @state :pin))
(= pairing kk1-pair)) (let [[id response] (multiaccount->keys
(let [{:keys [selected-id multiaccounts root-key derived]} pin
(:intro-wizard @re-frame.db/app-db) (:intro-wizard @re-frame.db/app-db))]
{:keys [id address public-key derived key-uid]}
(or (->> multiaccounts
(filter #(= (:id %) selected-id))
first)
(assoc root-key :derived derived))
whisper (get derived constants/path-whisper-keyword)
wallet (get derived constants/path-default-wallet-keyword)
wallet-root (get derived constants/path-wallet-root-keyword)
password (ethereum/sha3 pin)
response {:key-uid key-uid
:encryption-public-key (ethereum/sha3 pin)
:address address
:whisper-public-key (:public-key whisper)
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:wallet-root-public-key (:public-key wallet-root)
:wallet-root-address (:address wallet-root)
:whisper-address (:address whisper)
:public-key public-key
:whisper-private-key "34bc7d0c258c4f2ac1dac4fd6c55c9478bac1f4a9d8b9f1152c8551ab7187b43"
:wallet-address (:address wallet)
:wallet-public-key (:public-key wallet)}]
(log/debug "[simulated kk] generate-and-load-key response" response) (log/debug "[simulated kk] generate-and-load-key response" response)
(status/multiaccount-store-derived (status/multiaccount-store-derived
id id
key-uid (:key-uid response)
[constants/path-wallet-root [constants/path-wallet-root
constants/path-eip1581 constants/path-eip1581
constants/path-whisper constants/path-whisper
constants/path-default-wallet] constants/path-default-wallet]
password (ethereum/sha3 pin)
#(on-success response))))) #(on-success response)))))
(defn unblock-pin (defn unblock-pin
@ -168,9 +224,8 @@
#js {:code "EUNSPECIFIED" #js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"}))))) :message "Unexpected error SW, 0x63C2"})))))
(defn verify-pin [{:keys [pin pairing on-success on-failure]}] (defn verify-pin [{:keys [pin on-success on-failure]}]
(if (and (= pairing kk1-pair) (if (= pin (get @state :pin))
(= pin (get @state :pin)))
(later #(on-success 3)) (later #(on-success 3))
(do (do
(swap! state update-in (swap! state update-in
@ -242,9 +297,20 @@
(do (do
(swap! state assoc :pin pin) (swap! state assoc :pin pin)
(later (later
#(on-success (if @derived-acc
{:key-uid (get-in @state [:application-info :key-uid]) (let [[id keys] (multiaccount->keys pin @derived-acc)]
:encryption-public-key (ethereum/sha3 pin)}))) (status/multiaccount-store-derived
id
(:key-uid keys)
[constants/path-wallet-root
constants/path-eip1581
constants/path-whisper
constants/path-default-wallet]
(ethereum/sha3 pin)
#(on-success keys)))
#(on-success
{:key-uid (get-in @state [:application-info :key-uid])
:encryption-public-key (ethereum/sha3 pin)}))))
(do (do
(log/debug "Incorrect PIN" pin) (log/debug "Incorrect PIN" pin)
(swap! state update-in (swap! state update-in
@ -255,7 +321,7 @@
#js {:code "EUNSPECIFIED" #js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"}))))) :message "Unexpected error SW, 0x63C2"})))))
(defn sign [{:keys [pin hash data path on-success on-failure]}] (defn sign [{:keys [pin hash data path typed? on-success on-failure]}]
(if (= pin (get @state :pin)) (if (= pin (get @state :pin))
(later (later
#(let [address #(let [address
@ -269,18 +335,30 @@
(-> (:multiaccount/accounts @re-frame.db/app-db) (-> (:multiaccount/accounts @re-frame.db/app-db)
first first
:address)) :address))
params (types/clj->json password (ethereum/sha3 pin)]
{:account address (if-not typed?
:password (ethereum/sha3 pin) (let [params (types/clj->json
:data (or data (str "0x" hash))})] {:account address
(status/sign-message :password password
params :data (or data (str "0x" hash))})]
(fn [res] (status/sign-message
(let [signature (-> res params
types/json->clj (fn [res]
:result (let [signature (-> res
ethereum/normalized-hex)] types/json->clj
(on-success signature)))))) :result
ethereum/normalized-hex)]
(on-success signature)))))
(status/sign-typed-data
data
address
password
(fn [res]
(let [signature (-> res
types/json->clj
:result
ethereum/normalized-hex)]
(on-success signature)))))))
(do (do
(swap! state update-in (swap! state update-in
[:application-info :pin-retry-counter] [:application-info :pin-retry-counter]
@ -313,58 +391,86 @@
(defrecord SimulatedKeycard [] (defrecord SimulatedKeycard []
keycard/Keycard keycard/Keycard
(keycard/check-nfc-support [this args] (keycard/check-nfc-support [this args]
(log/debug "simulated card check-nfc-support")
(check-nfc-support args)) (check-nfc-support args))
(keycard/check-nfc-enabled [this args] (keycard/check-nfc-enabled [this args]
(log/debug "simulated card check-nfc-enabled")
(check-nfc-enabled args)) (check-nfc-enabled args))
(keycard/open-nfc-settings [this] (keycard/open-nfc-settings [this]
(log/debug "simulated card open-nfc-setting")
(open-nfc-settings)) (open-nfc-settings))
(keycard/register-card-events [this args] (keycard/register-card-events [this args]
(log/debug "simulated card register-card-event")
(register-card-events args)) (register-card-events args))
(keycard/on-card-connected [this callback] (keycard/on-card-connected [this callback]
(log/debug "simulated card on-card-connected")
(on-card-connected callback)) (on-card-connected callback))
(keycard/on-card-disconnected [this callback] (keycard/on-card-disconnected [this callback]
(log/debug "simulated card on-card-disconnected")
(on-card-disconnected callback)) (on-card-disconnected callback))
(keycard/remove-event-listener [this event] (keycard/remove-event-listener [this event]
(log/debug "simulated card remove-event-listener")
(remove-event-listener event)) (remove-event-listener event))
(keycard/remove-event-listeners [this] (keycard/remove-event-listeners [this]
(log/debug "simulated card remove-event-listener")
(remove-event-listeners)) (remove-event-listeners))
(keycard/get-application-info [this args] (keycard/get-application-info [this args]
(log/debug "simulated card get-application-info")
(get-application-info args)) (get-application-info args))
(keycard/install-applet [this args] (keycard/install-applet [this args]
(log/debug "simulated card install-applet")
(install-applet args)) (install-applet args))
(keycard/init-card [this args] (keycard/init-card [this args]
(log/debug "simulated card init-card")
(init-card args)) (init-card args))
(keycard/install-applet-and-init-card [this args] (keycard/install-applet-and-init-card [this args]
(log/debug "simulated card install-applet-and-init-card")
(install-applet-and-init-card args)) (install-applet-and-init-card args))
(keycard/pair [this args] (keycard/pair [this args]
(log/debug "simulated card pair")
(pair args)) (pair args))
(keycard/generate-and-load-key [this args] (keycard/generate-and-load-key [this args]
(log/debug "simulated card generate-and-load-key")
(generate-and-load-key args)) (generate-and-load-key args))
(keycard/unblock-pin [this args] (keycard/unblock-pin [this args]
(log/debug "simulated card unblock-pin")
(unblock-pin args)) (unblock-pin args))
(keycard/verify-pin [this args] (keycard/verify-pin [this args]
(log/debug "simulated card verify-pin")
(verify-pin args)) (verify-pin args))
(keycard/change-pin [this args] (keycard/change-pin [this args]
(log/debug "simulated card change-pin")
(change-pin args)) (change-pin args))
(keycard/unpair [this args] (keycard/unpair [this args]
(log/debug "simulated card unpair")
(unpair args)) (unpair args))
(keycard/delete [this args] (keycard/delete [this args]
(log/debug "simulated card delete")
(delete args)) (delete args))
(keycard/remove-key [this args] (keycard/remove-key [this args]
(log/debug "simulated card remove-key")
(remove-key args)) (remove-key args))
(keycard/remove-key-with-unpair [this args] (keycard/remove-key-with-unpair [this args]
(log/debug "simulated card remove-key-with-unpair")
(remove-key-with-unpair args)) (remove-key-with-unpair args))
(keycard/export-key [this args] (keycard/export-key [this args]
(log/debug "simulated card export-key")
(export-key args)) (export-key args))
(keycard/unpair-and-delete [this args] (keycard/unpair-and-delete [this args]
(log/debug "simulated card unpair-and-delete")
(unpair-and-delete args)) (unpair-and-delete args))
(keycard/get-keys [this args] (keycard/get-keys [this args]
(log/debug "simulated card get-keys")
(get-keys args)) (get-keys args))
(keycard/sign [this args] (keycard/sign [this args]
(log/debug "simulated card sign")
(sign args)) (sign args))
(keycard/save-multiaccount-and-login [this args] (keycard/save-multiaccount-and-login [this args]
(log/debug "simulated card save-multiaccount-and-login")
(save-multiaccount-and-login args)) (save-multiaccount-and-login args))
(keycard/login [this args] (keycard/login [this args]
(log/debug "simulated card login")
(login args)) (login args))
(keycard/send-transaction-with-signature [this args] (keycard/send-transaction-with-signature [this args]
(log/debug "simulated card send-transaction-with-signature")
(send-transaction-with-signature args))) (send-transaction-with-signature args)))

View File

@ -23,6 +23,7 @@
:align-items :center}} :align-items :center}}
[button "conn" :connect-card simulated-keycard/connect-card] [button "conn" :connect-card simulated-keycard/connect-card]
[button "conn sell" :connect-selected-card simulated-keycard/connect-selected-card] [button "conn sell" :connect-selected-card simulated-keycard/connect-selected-card]
[button "pair" :connect-pairing-card simulated-keycard/connect-pairing-card]
[button "disc" :disconnect-card simulated-keycard/disconnect-card] [button "disc" :disconnect-card simulated-keycard/disconnect-card]
[button "res" :keycard-reset-state simulated-keycard/reset-state]]) [button "res" :keycard-reset-state simulated-keycard/reset-state]])

View File

@ -61,7 +61,7 @@
(let [{:keys [result error]} (types/json->clj result)] (let [{:keys [result error]} (types/json->clj result)]
{:db (update db :hardwallet assoc {:db (update db :hardwallet assoc
:hash result :hash result
:type? typed? :typed? typed?
:data data)})) :data data)}))
(fx/defn hash-transaction (fx/defn hash-transaction

View File

@ -1,6 +1,7 @@
(ns status-im.ui.screens.hardwallet.setup.subs (ns status-im.ui.screens.hardwallet.setup.subs
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[clojure.string :as string])) [clojure.string :as string]
[status-im.ethereum.core :as ethereum]))
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet-setup-step :hardwallet-setup-step
@ -101,4 +102,4 @@
(re-frame/reg-sub (re-frame/reg-sub
:hardwallet-multiaccount-whisper-public-key :hardwallet-multiaccount-whisper-public-key
(fn [db] (fn [db]
(str "0x" (get-in db [:hardwallet :multiaccount-whisper-public-key])))) (ethereum/normalized-hex (get-in db [:hardwallet :multiaccount-whisper-public-key]))))