save keycard key-uid to account and use it to login

Signed-off-by: Dmitry Novotochinov <dmitry.novot@gmail.com>
This commit is contained in:
Dmitry Novotochinov 2019-05-23 14:45:50 +03:00
parent 7b8bf647e2
commit fd061833f5
No known key found for this signature in database
GPG Key ID: 43D1DAF5AD39C927
10 changed files with 97 additions and 57 deletions

View File

@ -56,7 +56,7 @@
"react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2", "react-native-securerandom": "git+https://github.com/status-im/react-native-securerandom.git#0.1.1-2",
"react-native-shake": "^3.3.1", "react-native-shake": "^3.3.1",
"react-native-splash-screen": "3.1.1", "react-native-splash-screen": "3.1.1",
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.4", "react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#v2.5.5",
"react-native-svg": "^9.2.4", "react-native-svg": "^9.2.4",
"react-native-svg-transformer": "^0.12.1", "react-native-svg-transformer": "^0.12.1",
"react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status", "react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status",

View File

@ -5593,9 +5593,9 @@ react-native-splash-screen@3.1.1:
resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30" resolved "https://registry.yarnpkg.com/react-native-splash-screen/-/react-native-splash-screen-3.1.1.tgz#1a4e46c9fdce53ff52af2a2cb4181788c4e30b30"
integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q== integrity sha512-PU2YocOSGbLjL9Vgcq/cwMNuHHKNjjuPpa1IPMuWo+6EB/fSZ5VOmxSa7+eucQe3631s3NhGuk3eHKahU03a4Q==
"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.4": "react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.5":
version "2.5.4" version "2.5.5"
resolved "git+https://github.com/status-im/react-native-status-keycard.git#5a4e9206bbe7e1a30aad0bc254b5e370a63643cc" resolved "git+https://github.com/status-im/react-native-status-keycard.git#fdf2f0e50a9b1d7eb0c46ddc6a33ab562f4c5c53"
react-native-svg-transformer@^0.12.1: react-native-svg-transformer@^0.12.1:
version "0.12.1" version "0.12.1"

View File

@ -64,7 +64,7 @@
status status
db] :as cofx} db] :as cofx}
{:keys [pubkey address mnemonic installation-id {:keys [pubkey address mnemonic installation-id
keycard-instance-uid keycard-pairing keycard-paired-on]} keycard-instance-uid keycard-key-uid keycard-pairing keycard-paired-on]}
password password
{:keys [seed-backed-up? login? new-account?] :or {login? true}}] {:keys [seed-backed-up? login? new-account?] :or {login? true}}]
(let [normalized-address (utils.hex/normalize-hex address) (let [normalized-address (utils.hex/normalize-hex address)
@ -80,6 +80,7 @@
:seed-backed-up? seed-backed-up? :seed-backed-up? seed-backed-up?
:mnemonic mnemonic :mnemonic mnemonic
:keycard-instance-uid keycard-instance-uid :keycard-instance-uid keycard-instance-uid
:keycard-key-uid keycard-key-uid
:keycard-pairing keycard-pairing :keycard-pairing keycard-pairing
:keycard-paired-on keycard-paired-on :keycard-paired-on keycard-paired-on
:settings (constants/default-account-settings) :settings (constants/default-account-settings)

View File

@ -58,6 +58,7 @@
(spec/def :account/mainnet-warning-shown-version (spec/nilable string?)) (spec/def :account/mainnet-warning-shown-version (spec/nilable string?))
(spec/def :account/desktop-alpha-release-warning-shown? (spec/nilable boolean?)) (spec/def :account/desktop-alpha-release-warning-shown? (spec/nilable boolean?))
(spec/def :account/keycard-instance-uid (spec/nilable string?)) (spec/def :account/keycard-instance-uid (spec/nilable string?))
(spec/def :account/keycard-key-uid (spec/nilable string?))
(spec/def :account/keycard-pairing (spec/nilable string?)) (spec/def :account/keycard-pairing (spec/nilable string?))
(spec/def :account/keycard-paired-on (spec/nilable int?)) (spec/def :account/keycard-paired-on (spec/nilable int?))
@ -74,6 +75,7 @@
:account/mainnet-warning-shown-version :account/mainnet-warning-shown-version
:account/desktop-alpha-release-warning-shown? :account/desktop-alpha-release-warning-shown?
:account/keycard-instance-uid :account/keycard-instance-uid
:account/keycard-key-uid
:account/keycard-pairing :account/keycard-pairing
:account/keycard-paired-on])) :account/keycard-paired-on]))

View File

@ -74,9 +74,9 @@
;;;; Handlers ;;;; Handlers
(fx/defn login [cofx] (fx/defn login [cofx]
(if (get-in cofx [:db :hardwallet :whisper-private-key]) (if (get-in cofx [:db :hardwallet :account :whisper-private-key])
{:hardwallet/login-with-keycard (-> cofx {:hardwallet/login-with-keycard (-> cofx
(get-in [:db :hardwallet]) (get-in [:db :hardwallet :account])
(select-keys [:whisper-private-key :encryption-public-key]) (select-keys [:whisper-private-key :encryption-public-key])
(assoc :on-result #(re-frame/dispatch [:accounts.login.callback/login-success %])))} (assoc :on-result #(re-frame/dispatch [:accounts.login.callback/login-success %])))}
(let [{:keys [address password]} (accounts.db/credentials cofx)] (let [{:keys [address password]} (accounts.db/credentials cofx)]
@ -159,8 +159,7 @@
:on-card-read :on-card-read
:card-read-in-progress? :card-read-in-progress?
:pin :pin
:whisper-private-key :account))
:encryption-public-key))
:web3/set-default-account [web3 address] :web3/set-default-account [web3 address]
:web3/fetch-node-version [web3 :web3/fetch-node-version [web3
#(re-frame/dispatch #(re-frame/dispatch

View File

@ -242,3 +242,7 @@
(def v22 (update (update v21 :properties dissoc :mainnet-warning-shown?) (def v22 (update (update v21 :properties dissoc :mainnet-warning-shown?)
:properties merge :properties merge
{:mainnet-warning-shown-version {:type :string :optional true}})) {:mainnet-warning-shown-version {:type :string :optional true}}))
(def v23 (assoc-in v22
[:properties :keycard-key-uid]
{:type :string :optional true}))

View File

@ -108,6 +108,11 @@
extension/v12 extension/v12
account/v22]) account/v22])
(def v28 [network/v1
bootnode/v4
extension/v12
account/v23])
;; put schemas ordered by version ;; put schemas ordered by version
(def schemas [{:schema v1 (def schemas [{:schema v1
:schemaVersion 1 :schemaVersion 1
@ -189,4 +194,7 @@
:migration (constantly nil)} :migration (constantly nil)}
{:schema v27 {:schema v27
:schemaVersion 27 :schemaVersion 27
:migration (constantly nil)}
{:schema v28
:schemaVersion 28
:migration (constantly nil)}]) :migration (constantly nil)}])

View File

@ -30,6 +30,14 @@
(filter #(= keycard-instance-uid (:keycard-instance-uid %))) (filter #(= keycard-instance-uid (:keycard-instance-uid %)))
first))) first)))
(defn- find-account-by-keycard-key-uid
[db keycard-key-uid]
(when keycard-key-uid
(->> (:accounts/accounts db)
vals
(filter #(= keycard-key-uid (:keycard-key-uid %)))
first)))
(defn get-pairing (defn get-pairing
([db] ([db]
(get-pairing db (get-in db [:hardwallet :application-info :instance-uid]))) (get-pairing db (get-in db [:hardwallet :application-info :instance-uid])))
@ -257,20 +265,35 @@
:hardwallet/get-keys {:pairing pairing :hardwallet/get-keys {:pairing pairing
:pin pin}}))) :pin pin}})))
(defn- get-account-for-login
"Finds account by key-uid.
Temporary, it also searches by instance-uid which was used before key-uid was introduced -
workaround should be removed before release."
[db key-uid instance-uid auto-login?]
(if auto-login?
(or
(find-account-by-keycard-key-uid db key-uid)
; TODO: remove before release
(let [acc (find-account-by-keycard-instance-uid db instance-uid)]
(when-not (:keycard-key-uid acc)
acc)))
(get-in db [:accounts/accounts (get-in db [:accounts/login :address])])))
(fx/defn login-with-keycard (fx/defn login-with-keycard
[{:keys [db] :as cofx} auto-login?] [{:keys [db] :as cofx} auto-login?]
(let [account-login-address (get-in db [:accounts/login :address]) (let [keycard-key-uid (get-in db [:hardwallet :application-info :key-uid])
account-was-manually-selected? account-login-address
account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid])
keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid]) keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid])
account (find-account-by-keycard-instance-uid db keycard-instance-uid) account (get-account-for-login db keycard-key-uid keycard-instance-uid auto-login?)
account-mismatch? (if account-was-manually-selected? account-key-uid (get account :keycard-key-uid)
(not= account-instance-uid keycard-instance-uid) account-instance-uid (get account :keycard-instance-uid)
(nil? account)) account-mismatch? (if auto-login?
(nil? account)
(if (:keycard-key-uid account)
(not= account-key-uid keycard-key-uid)
(not= account-instance-uid keycard-instance-uid)))
pairing (:keycard-pairing account)] pairing (:keycard-pairing account)]
(cond (cond
(empty? keycard-instance-uid) (empty? keycard-key-uid)
(fx/merge cofx (fx/merge cofx
{:utils/show-popup {:title (i18n/label :t/no-account-on-card) {:utils/show-popup {:title (i18n/label :t/no-account-on-card)
:content (i18n/label :t/no-account-on-card-text)}} :content (i18n/label :t/no-account-on-card-text)}}
@ -693,6 +716,23 @@
{:hardwallet/get-application-info {:pairing pairing' {:hardwallet/get-application-info {:pairing pairing'
:on-success on-card-read}})) :on-success on-card-read}}))
; TODO: remove before release
(fx/defn save-key-uid-to-account
"Migrate old accounts without keycard-key-uid stored in account.
Runs after keycard login"
{:events [:hardwallet/save-key-uid-to-account]}
[{:keys [db]}]
(let [keycard-key-uid (get-in db [:hardwallet :application-info :key-uid])
account (:account/account db)
account-key-uid (:keycard-key-uid account)]
(when (and (nil? account-key-uid)
(< 2 (count keycard-key-uid)))
(let [account' (assoc account :keycard-key-uid keycard-key-uid)]
{:db (-> db
(assoc-in [:account/account :keycard-key-uid] keycard-key-uid)
(assoc-in [:accounts/accounts (:address account') :keycard-key-uid] keycard-key-uid))
:data-store/base-tx [(accounts-store/save-account-tx account')]}))))
(defn- tag-lost-exception? [code error] (defn- tag-lost-exception? [code error]
(or (or
(= code "android.nfc.TagLostException") (= code "android.nfc.TagLostException")
@ -939,7 +979,7 @@
pin (vector->string (get-in db [:hardwallet :pin :import-account]))] pin (vector->string (get-in db [:hardwallet :pin :import-account]))]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :keycard-instance-uid] instance-uid) (assoc-in [:hardwallet :account :instance-uid] instance-uid)
(assoc-in [:hardwallet :secrets] {:pairing pairing' (assoc-in [:hardwallet :secrets] {:pairing pairing'
:paired-on (utils.datetime/timestamp)})) :paired-on (utils.datetime/timestamp)}))
:hardwallet/get-keys {:pairing pairing' :hardwallet/get-keys {:pairing pairing'
@ -1287,11 +1327,12 @@
(fx/defn create-keycard-account (fx/defn create-keycard-account
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [{{:keys [whisper-public-key (let [{{:keys [account secrets]} :hardwallet} db
wallet-address {:keys [whisper-public-key
encryption-public-key wallet-address
keycard-instance-uid encryption-public-key
secrets]} :hardwallet} db instance-uid
key-uid]} account
{:keys [pairing paired-on]} secrets] {:keys [pairing paired-on]} secrets]
(fx/merge (-> cofx (fx/merge (-> cofx
(accounts.create/get-signing-phrase) (accounts.create/get-signing-phrase)
@ -1300,7 +1341,8 @@
(accounts.create/on-account-created {:pubkey whisper-public-key (accounts.create/on-account-created {:pubkey whisper-public-key
:address wallet-address :address wallet-address
:mnemonic "" :mnemonic ""
:keycard-instance-uid keycard-instance-uid :keycard-instance-uid instance-uid
:keycard-key-uid key-uid
:keycard-pairing pairing :keycard-pairing pairing
:keycard-paired-on paired-on} :keycard-paired-on paired-on}
encryption-public-key encryption-public-key
@ -1310,22 +1352,13 @@
(fx/defn on-generate-and-load-key-success (fx/defn on-generate-and-load-key-success
[{:keys [db random-guid-generator] :as cofx} data] [{:keys [db random-guid-generator] :as cofx} data]
(let [{:keys [whisper-public-key (let [account-data (js->clj data :keywordize-keys true)]
whisper-private-key
whisper-address
wallet-address
instance-uid
encryption-public-key]} (js->clj data :keywordize-keys true)
whisper-public-key' (str "0x" whisper-public-key)
instance-uid' (get-in db [:hardwallet :keycard-instance-uid])]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :whisper-public-key] whisper-public-key') (assoc-in [:hardwallet :account] (-> account-data
(assoc-in [:hardwallet :whisper-private-key] whisper-private-key) (update :whisper-public-key #(str "0x" %))
(assoc-in [:hardwallet :whisper-address] whisper-address) (update :instance-uid #(get-in db [:hardwallet :account :instance-uid] %))))
(assoc-in [:hardwallet :wallet-address] wallet-address) (assoc-in [:hardwallet :application-info :key-uid] (:key-uid account-data))
(assoc-in [:hardwallet :encryption-public-key] encryption-public-key)
(assoc-in [:hardwallet :keycard-instance-uid] (or instance-uid' instance-uid))
(assoc-in [:hardwallet :on-card-connected] nil) (assoc-in [:hardwallet :on-card-connected] nil)
(update :hardwallet dissoc :recovery-phrase) (update :hardwallet dissoc :recovery-phrase)
(update-in [:hardwallet :secrets] dissoc :pin :puk :password) (update-in [:hardwallet :secrets] dissoc :pin :puk :password)
@ -1345,28 +1378,21 @@
(fx/defn on-get-keys-success (fx/defn on-get-keys-success
[{:keys [db] :as cofx} data] [{:keys [db] :as cofx} data]
(let [{:keys [whisper-public-key (let [{:keys [wallet-address encryption-public-key] :as account-data} (js->clj data :keywordize-keys true)
whisper-private-key
wallet-address
encryption-public-key]} (js->clj data :keywordize-keys true)
whisper-public-key' (str "0x" whisper-public-key)
{:keys [photo-path name]} (get-in db [:accounts/accounts wallet-address]) {:keys [photo-path name]} (get-in db [:accounts/accounts wallet-address])
password encryption-public-key
instance-uid (get-in db [:hardwallet :application-info :instance-uid])] instance-uid (get-in db [:hardwallet :application-info :instance-uid])]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:hardwallet :pin :status] nil) (assoc-in [:hardwallet :pin :status] nil)
(assoc-in [:hardwallet :pin :login] []) (assoc-in [:hardwallet :pin :login] [])
(assoc-in [:hardwallet :whisper-public-key] whisper-public-key') (assoc-in [:hardwallet :account] (update account-data :whisper-public-key #(str "0x" %)))
(assoc-in [:hardwallet :whisper-private-key] whisper-private-key)
(assoc-in [:hardwallet :wallet-address] wallet-address)
(assoc-in [:hardwallet :encryption-public-key] encryption-public-key)
(update :accounts/login assoc (update :accounts/login assoc
:password password :password encryption-public-key
:address wallet-address :address wallet-address
:photo-path photo-path :photo-path photo-path
:name name)) :name name))
:hardwallet/get-application-info {:pairing (get-pairing db instance-uid)}} :hardwallet/get-application-info {:pairing (get-pairing db instance-uid)
:on-success :hardwallet/save-key-uid-to-account}}
(accounts.login/user-login true)))) (accounts.login/user-login true))))
(fx/defn on-get-keys-error (fx/defn on-get-keys-error

View File

@ -58,7 +58,7 @@
"encryption-public-key" "04f2a432677a1b7c4f1bb22078135821d1d10fce23422297b5c808a545f2b61cdba38ee7394762172fc6ff5e9e28db7535e555efe2812905ffd4e0c25e82a98ae8" "encryption-public-key" "04f2a432677a1b7c4f1bb22078135821d1d10fce23422297b5c808a545f2b61cdba38ee7394762172fc6ff5e9e28db7535e555efe2812905ffd4e0c25e82a98ae8"
"whisper-address" "87df2285f90b71221fab6267b7cb37532fedbb1f" "whisper-address" "87df2285f90b71221fab6267b7cb37532fedbb1f"
"wallet-address" "7e92236392a850980d00d0cd2a4b92886bd7fe7b"}) "wallet-address" "7e92236392a850980d00d0cd2a4b92886bd7fe7b"})
[:db :hardwallet]) [:db :hardwallet :account])
[:whisper-private-key [:whisper-private-key
:whisper-public-key :whisper-public-key
:encryption-public-key :encryption-public-key

View File

@ -236,11 +236,11 @@
(testing "login with keycard" (testing "login with keycard"
(let [wpk "c56c7ac797c27b3790ce02c2459e9957c5d20d7a2c55320535526ce9e4dcbbef" (let [wpk "c56c7ac797c27b3790ce02c2459e9957c5d20d7a2c55320535526ce9e4dcbbef"
epk "04f43da85ff1c333f3e7277b9ac4df92c9120fbb251f1dede7d41286e8c055acfeb845f6d2654821afca25da119daff9043530b296ee0e28e202ba92ec5842d617" epk "04f43da85ff1c333f3e7277b9ac4df92c9120fbb251f1dede7d41286e8c055acfeb845f6d2654821afca25da119daff9043530b296ee0e28e202ba92ec5842d617"
db {:hardwallet {:encryption-public-key epk db {:hardwallet {:account {:encryption-public-key epk
:whisper-private-key wpk :whisper-private-key wpk
:wallet-address "83278851e290d2488b6add2a257259f5741a3b7d" :wallet-address "83278851e290d2488b6add2a257259f5741a3b7d"
:whisper-public-key "0x04491c1272149d7fa668afa45968c9914c0661641ace7dbcbc585c15070257840a0b4b1f71ce66c2147e281e1a44d6231b4731a26f6cc0a49e9616bbc7fc2f1a93" :whisper-public-key "0x04491c1272149d7fa668afa45968c9914c0661641ace7dbcbc585c15070257840a0b4b1f71ce66c2147e281e1a44d6231b4731a26f6cc0a49e9616bbc7fc2f1a93"
:whisper-address "b8bec30855ff20c2ddab32282e2b2c8c8baca70d"}} :whisper-address "b8bec30855ff20c2ddab32282e2b2c8c8baca70d"}}}
result (login.core/login {:db db})] result (login.core/login {:db db})]
(is (= (-> result (get :hardwallet/login-with-keycard) keys count) (is (= (-> result (get :hardwallet/login-with-keycard) keys count)
3)) 3))