key-storage cleanup (#16427)

This commit is contained in:
flexsurfer 2023-06-29 14:29:39 +02:00 committed by GitHub
parent b953ddb5af
commit d9f7510d13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 30 additions and 320 deletions

View File

@ -48,7 +48,7 @@
{:events [::start-keycard-backup]}
[{:keys [db] :as cofx}]
{::multiaccounts.recover/import-multiaccount {:passphrase (-> db
:multiaccounts/key-storage
:profile/key-storage
:seed-phrase
mnemonic/sanitize-passphrase)
:password nil
@ -66,7 +66,7 @@
:recovering? true
:selected-storage-type :advanced)
(assoc-in [:keycard :flow] :recovery)
(update :multiaccounts/key-storage dissoc :seed-phrase))
(update :profile/key-storage dissoc :seed-phrase))
:dismiss-keyboard nil}
(common/listen-to-hardware-back-button)
(navigation/navigate-to :keycard-onboarding-intro nil)))

View File

@ -2,7 +2,6 @@
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.keycard.common :as common]
[status-im.multiaccounts.key-storage.core :as key-storage]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]
@ -124,31 +123,32 @@
pairings (get-in db [:keycard :pairings])]
(rf/merge
cofx
{:db (-> db
(update :profile/profiles-overview dissoc key-uid)
(assoc-in [:keycard :secrets] nil)
(update-in [:keycard :pairings]
dissoc
(keyword instance-uid))
(update-in [:keycard :pairings] dissoc instance-uid)
(assoc-in [:keycard :whisper-public-key] nil)
(assoc-in [:keycard :wallet-address] nil)
(assoc-in [:keycard :application-info] nil)
(assoc-in [:keycard :pin]
{:status nil
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
:t/profile-deleted-title
:t/database-reset-title))
:content (i18n/label (if keys-removed-from-card?
:t/profile-deleted-keycard
:t/database-reset-content))
:on-dismiss #(re-frame/dispatch [:logout])}
::key-storage/delete-multiaccount {:key-uid key-uid
:on-success #(log/debug "[keycard] remove account ok")
:on-error #(log/warn "[keycard] remove account: " %)}}
{:db (-> db
(update :profile/profiles-overview dissoc key-uid)
(assoc-in [:keycard :secrets] nil)
(update-in [:keycard :pairings]
dissoc
(keyword instance-uid))
(update-in [:keycard :pairings] dissoc instance-uid)
(assoc-in [:keycard :whisper-public-key] nil)
(assoc-in [:keycard :wallet-address] nil)
(assoc-in [:keycard :application-info] nil)
(assoc-in [:keycard :pin]
{:status nil
:error-label nil
:on-verified nil}))
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
:t/profile-deleted-title
:t/database-reset-title))
:content (i18n/label (if keys-removed-from-card?
:t/profile-deleted-keycard
:t/database-reset-content))
:on-dismiss #(re-frame/dispatch [:logout])}}
;;should be reimplemented
;;:key-storage/delete-profile {:key-uid key-uid
;;:on-success #(log/debug "[keycard] remove account ok")
;; :on-error #(log/warn "[keycard] remove account: " %)}
(common/clear-on-card-connected)
(common/hide-connection-sheet))))

View File

@ -1,119 +1,13 @@
(ns status-im.multiaccounts.key-storage.core
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.mnemonic :as mnemonic]
[utils.i18n :as i18n]
[status-im.keycard.backup-key :as keycard.backup]
[status-im.keycard.common :as common]
[status-im.multiaccounts.logout.core :as multiaccounts.logout]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[status-im2.navigation.events :as navigation]
[utils.security.core :as security]))
(rf/defn key-and-storage-management-pressed
"This event can be dispatched before login and from profile and needs to redirect accordingly"
{:events [::key-and-storage-management-pressed]}
[{:keys [db] :as cofx}]
(navigation/navigate-to
cofx
(if (multiaccounts.model/logged-in? db)
:actions-logged-in
:actions-not-logged-in)
nil))
(rf/defn navigate-back
{:events [::navigate-back]}
[{:keys [db] :as cofx}]
(rf/merge
cofx
{:db (-> db
(dissoc :recovered-account?)
(update :keycard
dissoc
:from-key-storage-and-migration?
:creating-backup?
:factory-reset-card?))}
(navigation/navigate-back)))
(rf/defn enter-seed-pressed
"User is logged out and probably wants to move multiaccount to Keycard. Navigate to enter seed phrase screen"
{:events [::enter-seed-pressed]}
[{:keys [db] :as cofx}]
(rf/merge
cofx
{:db (assoc db :recovered-account? true)}
(navigation/navigate-to :seed-phrase nil)))
(rf/defn key-uid-seed-mismatch
{:events [::show-seed-key-uid-mismatch-error-popup]}
[cofx _]
(popover/show-popover cofx {:view :seed-key-uid-mismatch}))
(rf/defn key-uid-matches
{:events [::key-uid-matches]}
[{:keys [db] :as cofx} _]
(let [backup? (get-in db [:keycard :creating-backup?])]
(if backup?
(keycard.backup/start-keycard-backup cofx)
(navigation/navigate-to cofx :storage nil))))
(defn validate-seed-against-key-uid
"Check if the key-uid was generated with the given seed-phrase"
[{:keys [import-mnemonic-fn on-success on-error]} {:keys [seed-phrase key-uid]}]
(import-mnemonic-fn
(mnemonic/sanitize-passphrase seed-phrase)
nil
(fn [result]
(let [{:keys [keyUid]} (types/json->clj result)]
;; if the key-uid from app-db is same as the one returned by multiaccount import,
;; it means that this seed was used to generate this multiaccount
(if (= key-uid keyUid)
(on-success)
(on-error))))))
(re-frame/reg-fx
::validate-seed-against-key-uid
(partial validate-seed-against-key-uid
{:import-mnemonic-fn native-module/multiaccount-import-mnemonic
:on-success #(re-frame/dispatch [::key-uid-matches])
:on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])}))
(rf/defn seed-phrase-validated
{:events [::seed-phrase-validated]}
[{:keys [db] :as cofx} validation-error]
(let [error? (-> validation-error
types/json->clj
:error
string/blank?
not)
onboarding? (not (or (:profile/login db) (:profile/profile db)))]
(if error?
(popover/show-popover cofx {:view :custom-seed-phrase})
{::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase)
;; Unique key-uid of the account for which we are going to move
;; keys
:key-uid (or (-> db :profile/login :key-uid)
(-> db :profile/profile :key-uid)
(and onboarding?
(-> db
:keycard
:application-info
:key-uid)))}})))
(rf/defn keycard-storage-pressed
{:events [::keycard-storage-pressed]}
[{:keys [db]} selected?]
{:db (assoc-in db [:multiaccounts/key-storage :keycard-storage-selected?] selected?)})
(re-frame/reg-fx
::delete-imported-key
:key-storage/delete-imported-key
(fn [{:keys [key-uid address password on-success on-error]}]
(let [hashed-pass (ethereum/sha3 (security/safe-unmask-data password))]
(native-module/delete-imported-key
@ -125,132 +19,3 @@
(if-not (string/blank? error)
(on-error error)
(on-success))))))))
#_"Multiaccount has been deleted from device. We now need to emulate the restore seed phrase process, and make the user land on Keycard setup screen.
To ensure that keycard setup works, we need to:
1. Import multiaccount, derive required keys and save them at the correct location in app-db
2. Take the user to :keycard-onboarding-intro screen in :intro-login-stack
The exact events dispatched for this flow if consumed from the UI are:
:m.r/enter-phrase-input-changed
:m.r/enter-phrase-next-pressed
:m.r/re-encrypt-pressed
:i/on-key-storage-selected ([:intro-wizard :selected-storage-type] is set to :advanced)
:m.r/select-storage-next-pressed
We don't need to take the exact steps, just set the required state and redirect to correct screen
"
(rf/defn import-multiaccount
[{:keys [db] :as cofx}]
{:dispatch [:bottom-sheet/hide-old]
::multiaccounts.recover/import-multiaccount
{:passphrase (get-in db [:multiaccounts/key-storage :seed-phrase])
:password nil
:success-event ::import-multiaccount-success}})
(rf/defn delete-multiaccount-and-init-keycard-onboarding
{:events [::delete-multiaccount-and-init-keycard-onboarding]}
[{:keys [db] :as cofx}]
(rf/merge
{:dispatch [:bottom-sheet/hide-old]
:db (assoc-in db [:multiaccounts/key-storage :reset-db-checked?] true)}
(import-multiaccount)))
(rf/defn storage-selected
{:events [::storage-selected]}
[{:keys [db] :as cofx}]
(if (get-in db [:multiaccounts/key-storage :reset-db-checked?])
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning})
(bottom-sheet/hide-bottom-sheet-old cofx)))
(rf/defn skip-password-pressed
{:events [::skip-password-pressed]}
[cofx]
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning}))
(rf/defn password-changed
{:events [::password-changed]}
[{db :db} password]
(let [unmasked-pass (security/safe-unmask-data password)]
{:db (update db
:keycard assoc
:migration-password password
:migration-password-error nil
:migration-password-valid? (and unmasked-pass (> (count unmasked-pass) 5)))}))
(rf/defn verify-password-result
{:events [::verify-password-result]}
[{:keys [db] :as cofx} result]
(let [{:keys [error]} (types/json->clj result)]
(if (string/blank? error)
(rf/merge
cofx
{:db (update db :keycard dissoc :migration-password-error :migration-password-valid?)}
(import-multiaccount))
{:db (assoc-in db [:keycard :migration-password-error] (i18n/label :t/wrong-password))})))
(rf/defn verify-password
{:events [::verify-password]}
[{:keys [db] :as cofx}]
(native-module/verify-database-password
(get-in db [:profile/login :key-uid])
(ethereum/sha3 (security/safe-unmask-data (get-in db [:keycard :migration-password])))
#(re-frame/dispatch [::verify-password-result %])))
(rf/defn handle-multiaccount-import
{:events [::import-multiaccount-success]}
[{:keys [db] :as cofx} root-data derived-data]
(rf/merge cofx
{:db (-> db
(update :intro-wizard
assoc
:root-key root-data
:derived derived-data
:recovering? true
:selected-storage-type :advanced)
(assoc-in [:keycard :flow] :recovery)
(assoc-in [:keycard :from-key-storage-and-migration?] true)
(assoc-in [:keycard :converting-account?]
(not (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
(assoc-in [:keycard :delete-account?]
(true? (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
(dissoc :multiaccounts/key-storage))}
(popover/hide-popover)
(common/listen-to-hardware-back-button)
(navigation/navigate-to :keycard-onboarding-intro nil)))
(rf/defn goto-multiaccounts-screen
{:events [::hide-popover-and-goto-multiaccounts-screen]}
[cofx _]
(rf/merge cofx
(popover/hide-popover)
(navigation/navigate-to :multiaccounts nil)))
(rf/defn confirm-logout-and-goto-key-storage
{:events [::confirm-logout-and-goto-key-storage]}
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db (assoc db :goto-key-storage? true)}
(multiaccounts.logout/logout)))
(rf/defn logout-and-goto-key-storage
{:events [::logout-and-goto-key-storage]}
[_]
{:ui/show-confirmation
{:title (i18n/label :t/logout-title)
:content (i18n/label :t/logout-key-management)
:confirm-button-text (i18n/label :t/logout)
:on-accept #(re-frame/dispatch [::confirm-logout-and-goto-key-storage])
:on-cancel nil}})
(comment
;; check import mnemonic output
(native-module/multiaccount-import-mnemonic
"rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
nil
(fn [result]
(prn (types/json->clj result))))
;; check delete account output
(native-module/delete-multiaccount "0x3831d0f22996a65970a214f0a94bfa9a63a21dac235d8dadb91be8e32e7d3ab7"
(fn [result]
(prn ::--delete-account-res-> result))))

View File

@ -1,44 +0,0 @@
(ns status-im.multiaccounts.key-storage.core-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.multiaccounts.key-storage.core :as models]
[utils.security.core :as security]))
(def seed-key-uid-pair
{:seed-phrase "rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
:key-uid "0x3831d0f22996a65970a214f0a94bfa9a63a21dac235d8dadb91be8e32e7d3ab7"})
(defn mock-import-mnemonic-fn
[_ _ _]
;; return json with keyUid, the real world will have more info in the response
(str "{\"keyUid\": \"" (:key-uid seed-key-uid-pair) "\"}"))
(deftest validate-seed-against-key-uid
(testing "Success event is triggered if correct seed is entered for selected multiaccount (key-uid)"
(models/validate-seed-against-key-uid
{:import-mnemonic-fn mock-import-mnemonic-fn
:on-success #(is true) ; this callback should be called
:on-error #(is false)}
{:seed-phrase (:seed-phrase seed-key-uid-pair)
:key-uid (:key-uid seed-key-uid-pair)}))
(testing "Error event is triggered if incorrect seed is entered for selected multiaccount"
(models/validate-seed-against-key-uid
{:import-mnemonic-fn mock-import-mnemonic-fn
:on-success #(is false)
:on-error #(is true)}
{:seed-phrase (:seed-phrase seed-key-uid-pair)
:key-uid "0xInvalid-Will-make-the-function-fail"})))
(deftest handle-multiaccount-import
(testing "Sets correct state for Keycard onboarding after multiaccounts seeds are derived"
(let [res (models/handle-multiaccount-import {:db {}} :passed-root-data :passed-derived-data)]
(is (= :passed-root-data (get-in res [:db :intro-wizard :root-key])))
(is (= :passed-derived-data (get-in res [:db :intro-wizard :derived])))
(is (= :advanced (get-in res [:db :intro-wizard :selected-storage-type]))) ; :advanced storage type
; means Keycard
(is (= :recovery (get-in res [:db :keycard :flow])))
(is (get-in res [:db :keycard :from-key-storage-and-migration?])))))
(comment
(security/safe-unmask-data (security/mask-data nil)))

View File

@ -4,7 +4,6 @@
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[status-im.multiaccounts.biometric.core :as biometric]
[status-im.multiaccounts.key-storage.core :as key-storage]
[status-im.multiaccounts.reset-password.core :as reset-password]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.common.common :as components.common]
@ -127,14 +126,6 @@
:on-press #(re-frame/dispatch
[:multiaccounts.ui/webview-permission-requests-switched
((complement boolean) webview-allow-permission-requests?)])}])
(when (not keycard?)
[quo/list-item
{:size :small
:title (i18n/label :t/manage-keys-and-storage)
:chevron true
:on-press #(re-frame/dispatch [::key-storage/logout-and-goto-key-storage])
:accessibility-label :key-managment}])
[separator]
[quo/list-header (i18n/label :t/privacy-photos)]
[quo/list-item

View File

@ -12,7 +12,6 @@
[status-im.ethereum.stateofus :as stateofus]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.key-storage.core :as key-storage]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[native-module.core :as native-module]
[status-im.ui.components.list-selection :as list-selection]
@ -342,7 +341,7 @@
(if (= (string/lower-case dapps-address) (string/lower-case deleted-address))
{:utils/show-popup {:title (i18n/label :t/warning)
:content (i18n/label :t/account-is-used)}}
{::key-storage/delete-imported-key
{:key-storage/delete-imported-key
{:key-uid (get-in db [:profile/profile :key-uid])
:address (:address account)
:password password

View File

@ -93,7 +93,6 @@
(reg-root-key-sub :profile/profile-settings :profile/profile)
(reg-root-key-sub :profile/wallet-accounts :profile/wallet-accounts)
(reg-root-key-sub :multiaccounts/key-storage :multiaccounts/key-storage)
(reg-root-key-sub :multiaccount/reset-password-form-vals :multiaccount/reset-password-form-vals)
(reg-root-key-sub :multiaccount/reset-password-errors :multiaccount/reset-password-errors)
(reg-root-key-sub :multiaccount/resetting-password? :multiaccount/resetting-password?)