From fd061833f52131cf714757e666da8221773d1836 Mon Sep 17 00:00:00 2001 From: Dmitry Novotochinov Date: Thu, 23 May 2019 14:45:50 +0300 Subject: [PATCH] save keycard key-uid to account and use it to login Signed-off-by: Dmitry Novotochinov --- mobile_files/package.json.orig | 2 +- mobile_files/yarn.lock | 6 +- src/status_im/accounts/create/core.cljs | 3 +- src/status_im/accounts/db.cljs | 2 + src/status_im/accounts/login/core.cljs | 7 +- .../realm/schemas/base/account.cljs | 4 + .../data_store/realm/schemas/base/core.cljs | 8 ++ src/status_im/hardwallet/core.cljs | 110 +++++++++++------- test/cljs/status_im/test/hardwallet/core.cljs | 2 +- test/cljs/status_im/test/sign_in/flow.cljs | 10 +- 10 files changed, 97 insertions(+), 57 deletions(-) diff --git a/mobile_files/package.json.orig b/mobile_files/package.json.orig index 64c0057717..a5b6582f43 100644 --- a/mobile_files/package.json.orig +++ b/mobile_files/package.json.orig @@ -56,7 +56,7 @@ "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-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-transformer": "^0.12.1", "react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status", diff --git a/mobile_files/yarn.lock b/mobile_files/yarn.lock index 121b6767c1..876bc1f811 100644 --- a/mobile_files/yarn.lock +++ b/mobile_files/yarn.lock @@ -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" 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": - version "2.5.4" - resolved "git+https://github.com/status-im/react-native-status-keycard.git#5a4e9206bbe7e1a30aad0bc254b5e370a63643cc" +"react-native-status-keycard@git+https://github.com/status-im/react-native-status-keycard.git#v2.5.5": + version "2.5.5" + resolved "git+https://github.com/status-im/react-native-status-keycard.git#fdf2f0e50a9b1d7eb0c46ddc6a33ab562f4c5c53" react-native-svg-transformer@^0.12.1: version "0.12.1" diff --git a/src/status_im/accounts/create/core.cljs b/src/status_im/accounts/create/core.cljs index 3acaefbc17..c95645a761 100644 --- a/src/status_im/accounts/create/core.cljs +++ b/src/status_im/accounts/create/core.cljs @@ -64,7 +64,7 @@ status db] :as cofx} {: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 {:keys [seed-backed-up? login? new-account?] :or {login? true}}] (let [normalized-address (utils.hex/normalize-hex address) @@ -80,6 +80,7 @@ :seed-backed-up? seed-backed-up? :mnemonic mnemonic :keycard-instance-uid keycard-instance-uid + :keycard-key-uid keycard-key-uid :keycard-pairing keycard-pairing :keycard-paired-on keycard-paired-on :settings (constants/default-account-settings) diff --git a/src/status_im/accounts/db.cljs b/src/status_im/accounts/db.cljs index 00c35f9f3f..95b4dd75d8 100644 --- a/src/status_im/accounts/db.cljs +++ b/src/status_im/accounts/db.cljs @@ -58,6 +58,7 @@ (spec/def :account/mainnet-warning-shown-version (spec/nilable string?)) (spec/def :account/desktop-alpha-release-warning-shown? (spec/nilable boolean?)) (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-paired-on (spec/nilable int?)) @@ -74,6 +75,7 @@ :account/mainnet-warning-shown-version :account/desktop-alpha-release-warning-shown? :account/keycard-instance-uid + :account/keycard-key-uid :account/keycard-pairing :account/keycard-paired-on])) diff --git a/src/status_im/accounts/login/core.cljs b/src/status_im/accounts/login/core.cljs index 3c290cc9d1..5d61bcefc9 100644 --- a/src/status_im/accounts/login/core.cljs +++ b/src/status_im/accounts/login/core.cljs @@ -74,9 +74,9 @@ ;;;; Handlers (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 - (get-in [:db :hardwallet]) + (get-in [:db :hardwallet :account]) (select-keys [:whisper-private-key :encryption-public-key]) (assoc :on-result #(re-frame/dispatch [:accounts.login.callback/login-success %])))} (let [{:keys [address password]} (accounts.db/credentials cofx)] @@ -159,8 +159,7 @@ :on-card-read :card-read-in-progress? :pin - :whisper-private-key - :encryption-public-key)) + :account)) :web3/set-default-account [web3 address] :web3/fetch-node-version [web3 #(re-frame/dispatch diff --git a/src/status_im/data_store/realm/schemas/base/account.cljs b/src/status_im/data_store/realm/schemas/base/account.cljs index c0b2eb1b7a..2f56534355 100644 --- a/src/status_im/data_store/realm/schemas/base/account.cljs +++ b/src/status_im/data_store/realm/schemas/base/account.cljs @@ -242,3 +242,7 @@ (def v22 (update (update v21 :properties dissoc :mainnet-warning-shown?) :properties merge {:mainnet-warning-shown-version {:type :string :optional true}})) + +(def v23 (assoc-in v22 + [:properties :keycard-key-uid] + {:type :string :optional true})) diff --git a/src/status_im/data_store/realm/schemas/base/core.cljs b/src/status_im/data_store/realm/schemas/base/core.cljs index 386212eac3..a653401a5a 100644 --- a/src/status_im/data_store/realm/schemas/base/core.cljs +++ b/src/status_im/data_store/realm/schemas/base/core.cljs @@ -108,6 +108,11 @@ extension/v12 account/v22]) +(def v28 [network/v1 + bootnode/v4 + extension/v12 + account/v23]) + ;; put schemas ordered by version (def schemas [{:schema v1 :schemaVersion 1 @@ -189,4 +194,7 @@ :migration (constantly nil)} {:schema v27 :schemaVersion 27 + :migration (constantly nil)} + {:schema v28 + :schemaVersion 28 :migration (constantly nil)}]) diff --git a/src/status_im/hardwallet/core.cljs b/src/status_im/hardwallet/core.cljs index 3b0e10b525..10840732e5 100644 --- a/src/status_im/hardwallet/core.cljs +++ b/src/status_im/hardwallet/core.cljs @@ -30,6 +30,14 @@ (filter #(= keycard-instance-uid (:keycard-instance-uid %))) 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 ([db] (get-pairing db (get-in db [:hardwallet :application-info :instance-uid]))) @@ -257,20 +265,35 @@ :hardwallet/get-keys {:pairing pairing :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 [{:keys [db] :as cofx} auto-login?] - (let [account-login-address (get-in db [:accounts/login :address]) - account-was-manually-selected? account-login-address - account-instance-uid (get-in db [:accounts/accounts account-login-address :keycard-instance-uid]) + (let [keycard-key-uid (get-in db [:hardwallet :application-info :key-uid]) keycard-instance-uid (get-in db [:hardwallet :application-info :instance-uid]) - account (find-account-by-keycard-instance-uid db keycard-instance-uid) - account-mismatch? (if account-was-manually-selected? - (not= account-instance-uid keycard-instance-uid) - (nil? account)) + account (get-account-for-login db keycard-key-uid keycard-instance-uid auto-login?) + account-key-uid (get account :keycard-key-uid) + account-instance-uid (get account :keycard-instance-uid) + 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)] - (cond - (empty? keycard-instance-uid) + (empty? keycard-key-uid) (fx/merge cofx {:utils/show-popup {:title (i18n/label :t/no-account-on-card) :content (i18n/label :t/no-account-on-card-text)}} @@ -693,6 +716,23 @@ {:hardwallet/get-application-info {:pairing pairing' :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] (or (= code "android.nfc.TagLostException") @@ -939,7 +979,7 @@ pin (vector->string (get-in db [:hardwallet :pin :import-account]))] (fx/merge cofx {:db (-> db - (assoc-in [:hardwallet :keycard-instance-uid] instance-uid) + (assoc-in [:hardwallet :account :instance-uid] instance-uid) (assoc-in [:hardwallet :secrets] {:pairing pairing' :paired-on (utils.datetime/timestamp)})) :hardwallet/get-keys {:pairing pairing' @@ -1287,11 +1327,12 @@ (fx/defn create-keycard-account [{:keys [db] :as cofx}] - (let [{{:keys [whisper-public-key - wallet-address - encryption-public-key - keycard-instance-uid - secrets]} :hardwallet} db + (let [{{:keys [account secrets]} :hardwallet} db + {:keys [whisper-public-key + wallet-address + encryption-public-key + instance-uid + key-uid]} account {:keys [pairing paired-on]} secrets] (fx/merge (-> cofx (accounts.create/get-signing-phrase) @@ -1300,7 +1341,8 @@ (accounts.create/on-account-created {:pubkey whisper-public-key :address wallet-address :mnemonic "" - :keycard-instance-uid keycard-instance-uid + :keycard-instance-uid instance-uid + :keycard-key-uid key-uid :keycard-pairing pairing :keycard-paired-on paired-on} encryption-public-key @@ -1310,22 +1352,13 @@ (fx/defn on-generate-and-load-key-success [{:keys [db random-guid-generator] :as cofx} data] - (let [{:keys [whisper-public-key - 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])] + (let [account-data (js->clj data :keywordize-keys true)] (fx/merge cofx {:db (-> db - (assoc-in [:hardwallet :whisper-public-key] whisper-public-key') - (assoc-in [:hardwallet :whisper-private-key] whisper-private-key) - (assoc-in [:hardwallet :whisper-address] whisper-address) - (assoc-in [:hardwallet :wallet-address] wallet-address) - (assoc-in [:hardwallet :encryption-public-key] encryption-public-key) - (assoc-in [:hardwallet :keycard-instance-uid] (or instance-uid' instance-uid)) + (assoc-in [:hardwallet :account] (-> account-data + (update :whisper-public-key #(str "0x" %)) + (update :instance-uid #(get-in db [:hardwallet :account :instance-uid] %)))) + (assoc-in [:hardwallet :application-info :key-uid] (:key-uid account-data)) (assoc-in [:hardwallet :on-card-connected] nil) (update :hardwallet dissoc :recovery-phrase) (update-in [:hardwallet :secrets] dissoc :pin :puk :password) @@ -1345,28 +1378,21 @@ (fx/defn on-get-keys-success [{:keys [db] :as cofx} data] - (let [{:keys [whisper-public-key - whisper-private-key - wallet-address - encryption-public-key]} (js->clj data :keywordize-keys true) - whisper-public-key' (str "0x" whisper-public-key) + (let [{:keys [wallet-address encryption-public-key] :as account-data} (js->clj data :keywordize-keys true) {: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])] (fx/merge cofx {:db (-> db (assoc-in [:hardwallet :pin :status] nil) (assoc-in [:hardwallet :pin :login] []) - (assoc-in [:hardwallet :whisper-public-key] whisper-public-key') - (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) + (assoc-in [:hardwallet :account] (update account-data :whisper-public-key #(str "0x" %))) (update :accounts/login assoc - :password password + :password encryption-public-key :address wallet-address :photo-path photo-path :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)))) (fx/defn on-get-keys-error diff --git a/test/cljs/status_im/test/hardwallet/core.cljs b/test/cljs/status_im/test/hardwallet/core.cljs index 7c3d2ba1de..55c4cd2775 100644 --- a/test/cljs/status_im/test/hardwallet/core.cljs +++ b/test/cljs/status_im/test/hardwallet/core.cljs @@ -58,7 +58,7 @@ "encryption-public-key" "04f2a432677a1b7c4f1bb22078135821d1d10fce23422297b5c808a545f2b61cdba38ee7394762172fc6ff5e9e28db7535e555efe2812905ffd4e0c25e82a98ae8" "whisper-address" "87df2285f90b71221fab6267b7cb37532fedbb1f" "wallet-address" "7e92236392a850980d00d0cd2a4b92886bd7fe7b"}) - [:db :hardwallet]) + [:db :hardwallet :account]) [:whisper-private-key :whisper-public-key :encryption-public-key diff --git a/test/cljs/status_im/test/sign_in/flow.cljs b/test/cljs/status_im/test/sign_in/flow.cljs index 44a3f5dac0..60ad5eff1d 100644 --- a/test/cljs/status_im/test/sign_in/flow.cljs +++ b/test/cljs/status_im/test/sign_in/flow.cljs @@ -236,11 +236,11 @@ (testing "login with keycard" (let [wpk "c56c7ac797c27b3790ce02c2459e9957c5d20d7a2c55320535526ce9e4dcbbef" epk "04f43da85ff1c333f3e7277b9ac4df92c9120fbb251f1dede7d41286e8c055acfeb845f6d2654821afca25da119daff9043530b296ee0e28e202ba92ec5842d617" - db {:hardwallet {:encryption-public-key epk - :whisper-private-key wpk - :wallet-address "83278851e290d2488b6add2a257259f5741a3b7d" - :whisper-public-key "0x04491c1272149d7fa668afa45968c9914c0661641ace7dbcbc585c15070257840a0b4b1f71ce66c2147e281e1a44d6231b4731a26f6cc0a49e9616bbc7fc2f1a93" - :whisper-address "b8bec30855ff20c2ddab32282e2b2c8c8baca70d"}} + db {:hardwallet {:account {:encryption-public-key epk + :whisper-private-key wpk + :wallet-address "83278851e290d2488b6add2a257259f5741a3b7d" + :whisper-public-key "0x04491c1272149d7fa668afa45968c9914c0661641ace7dbcbc585c15070257840a0b4b1f71ce66c2147e281e1a44d6231b4731a26f6cc0a49e9616bbc7fc2f1a93" + :whisper-address "b8bec30855ff20c2ddab32282e2b2c8c8baca70d"}}} result (login.core/login {:db db})] (is (= (-> result (get :hardwallet/login-with-keycard) keys count) 3))