[fix 8702] hash passwords before sending them to status-go

fix #8702

- use ethereum.utils sha3 function to hash passwords before sending them
to status-go
- some native calls take password as one of their params: they now take
hashed-password (still a string, only relevant for status-react caller)
- some native calls take password within a map of rpc params: it now
needs to be hashed with `ethereum.core/sha3`

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2019-09-04 22:59:44 +02:00
parent d312192209
commit 6be85f46a5
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
9 changed files with 105 additions and 100 deletions

View File

@ -2,6 +2,7 @@
(:require [cljs.core.async :as async]
[re-frame.core :as re-frame]
[status-im.data-store.realm.core :as realm]
[status-im.ethereum.core :as ethereum]
[status-im.i18n :as i18n]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.native-module.core :as status]
@ -192,7 +193,7 @@
::verify
(fn [[address password realm-error]]
(status/verify address
(security/safe-unmask-data password)
(ethereum/sha3 (security/safe-unmask-data password))
#(re-frame/dispatch [::verify-success % realm-error]))))
(fx/defn handle-change-multiaccount-success

View File

@ -1,9 +1,7 @@
(ns status-im.hardwallet.fx
(:require [re-frame.core :as re-frame]
[status-im.hardwallet.card :as card]
[status-im.utils.datetime :as utils.datetime]
[status-im.native-module.core :as statusgo]
[status-im.react-native.js-dependencies :as js-dependencies]))
[status-im.native-module.core :as status]))
(re-frame/reg-fx
:hardwallet/get-application-info
@ -91,9 +89,9 @@
(re-frame/reg-fx
:hardwallet/login-with-keycard
statusgo/login-with-keycard)
status/login-with-keycard)
(re-frame/reg-fx
:send-transaction-with-signature
(fn [{:keys [transaction signature on-completed]}]
(statusgo/send-transaction-with-signature transaction signature on-completed)))
(status/send-transaction-with-signature transaction signature on-completed)))

View File

@ -1,25 +1,19 @@
(ns status-im.multiaccounts.create.core
(:require [clojure.set :refer [map-invert]]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ethereum.core :as ethereum]
[status-im.native-module.core :as status]
[status-im.node.core :as node]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.mobile-network-settings.events :as mobile-network]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.config :as config]
[status-im.utils.fx :as fx]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
[status-im.utils.platform :as platform]
[status-im.utils.random :as random]
[status-im.utils.security :as security]
[status-im.utils.signing-phrase.core :as signing-phrase]
[status-im.utils.types :as types]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
[status-im.utils.utils :as utils]))
(defn get-signing-phrase [cofx]
(assoc cofx :signing-phrase (signing-phrase/generate)))
@ -50,8 +44,9 @@
[{:keys [db] :as cofx}]
(let [{:keys [selected-id address key-code]} (:intro-wizard db)
{:keys [address]} (get-selected-multiaccount cofx)
hashed-password (ethereum/sha3 (security/safe-unmask-data key-code))
callback #(re-frame/dispatch [::store-multiaccount-success key-code])]
{::store-multiaccount [selected-id address key-code callback]}))
{::store-multiaccount [selected-id address hashed-password callback]}))
(fx/defn intro-wizard
{:events [:multiaccounts.create.ui/intro-wizard]}
@ -195,7 +190,7 @@
seed-backed-up?
(assoc-in [:multiaccount :seed-backed-up?] true))
::save-account-and-login [(types/clj->json multiaccount-data)
password
(ethereum/sha3 (security/safe-unmask-data password))
(node/get-new-config db)
(types/clj->json accounts-data)]}
(when (:intro-wizard db)
@ -275,26 +270,26 @@
(re-frame/reg-fx
::store-multiaccount
(fn [[id address password callback]]
(fn [[id address hashed-password callback]]
(status/multiaccount-store-account
id
(security/safe-unmask-data password)
hashed-password
(fn []
(status/multiaccount-load-account
address
password
hashed-password
(fn [value]
(let [{:keys [id]} (types/json->clj value)]
(status/multiaccount-store-derived
id
[constants/path-whisper constants/path-default-wallet]
password
hashed-password
callback))))))))
(re-frame/reg-fx
::save-account-and-login
(fn [[multiaccount-data password config accounts-data]]
(fn [[multiaccount-data hashed-password config accounts-data]]
(status/save-account-and-login multiaccount-data
(security/safe-unmask-data password)
hashed-password
config
accounts-data)))

View File

@ -7,6 +7,7 @@
[status-im.constants :as constants]
[status-im.contact.core :as contact]
[status-im.data-store.core :as data-store]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.transactions.core :as transactions]
[status-im.fleet.core :as fleet]
@ -63,7 +64,7 @@
(let [{:keys [address password name photo-path]} (:multiaccounts/login db)]
{:db (assoc-in db [:multiaccounts/login :processing] true)
::login [(types/clj->json {:name name :address address :photo-path photo-path})
password]}))
(ethereum/sha3 (security/safe-unmask-data password))]}))
(fx/defn finish-keycard-setup
[{:keys [db] :as cofx}]
@ -309,6 +310,6 @@
(re-frame/reg-fx
::login
(fn [[account-data password]]
(fn [[account-data hashed-password]]
(status/login account-data
(security/safe-unmask-data password))))
hashed-password)))

View File

@ -2,6 +2,7 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.mnemonic :as mnemonic]
[status-im.i18n :as i18n]
[status-im.multiaccounts.create.core :as multiaccounts.create]
@ -96,9 +97,10 @@
[{:keys [db] :as cofx}]
(let [{:keys [password passphrase root-key]} (:multiaccounts/recover db)
{:keys [id address]} root-key
callback #(re-frame/dispatch [::store-multiaccount-success password])]
callback #(re-frame/dispatch [::store-multiaccount-success password])
hashed-password (ethereum/sha3 (security/safe-unmask-data password))]
{:db (assoc-in db [:multiaccounts/recover :processing?] true)
::multiaccounts.create/store-multiaccount [id address password callback]}))
::multiaccounts.create/store-multiaccount [id address hashed-password callback]}))
(fx/defn recover-multiaccount-with-checks
{:events [::sign-in-button-pressed]}
@ -113,24 +115,6 @@
:confirm-button-text (i18n/label :recovery-confirm-phrase)
:on-accept #(re-frame/dispatch [::recover-multiaccount-confirmed])}}))))
(re-frame/reg-fx
::store-multiaccount
(fn [[id address password]]
(status/multiaccount-store-account
id
(security/safe-unmask-data password)
(fn []
(status/multiaccount-load-account
address
password
(fn [value]
(let [{:keys [id]} (types/json->clj value)]
(status/multiaccount-store-derived
id
[constants/path-whisper constants/path-default-wallet]
password
#(re-frame/dispatch [::store-multiaccount-success password])))))))))
(re-frame/reg-fx
::import-multiaccount
(fn [{:keys [passphrase password]}]

View File

@ -1,8 +1,8 @@
(ns status-im.native-module.core
(:require [status-im.ui.components.react :as r]
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.react-native.js-dependencies :as rn-dependencies]
[clojure.string :as string]
[status-im.ui.components.react :as react]
[status-im.utils.platform :as platform]
[status-im.utils.types :as types]))
@ -30,31 +30,35 @@
#(callback (types/json->clj %))))
(defn save-account-and-login
[multiaccount-data password config accounts-data]
"NOTE: beware, the password has to be sha3 hashed"
[multiaccount-data hashed-password config accounts-data]
(clear-web-data)
(.saveAccountAndLogin (status) multiaccount-data password config accounts-data))
(.saveAccountAndLogin (status) multiaccount-data hashed-password config accounts-data))
(defn login
[account-data password]
"NOTE: beware, the password has to be sha3 hashed"
[account-data hashed-password]
(clear-web-data)
(.login (status) account-data password))
(.login (status) account-data hashed-password))
(defn logout []
(clear-web-data)
(.logout (status)))
(defonce listener
(.addListener r/device-event-emitter "gethEvent"
(.addListener react/device-event-emitter "gethEvent"
#(re-frame/dispatch [:signals/signal-received (.-jsonEvent %)])))
(defn multiaccount-load-account
"this function is used after storing an account when you still want to
"NOTE: beware, the password has to be sha3 hashed
this function is used after storing an account when you still want to
derive accounts from it, because saving an account flushes the loaded keys
from memory"
[address password callback]
[address hashed-password callback]
(.multiAccountLoadAccount (status)
(types/clj->json {:address address
:password password})
:password hashed-password})
callback))
(defn multiaccount-reset
@ -77,24 +81,27 @@
callback)))
(defn multiaccount-store-account
"this stores the account and flush keys in memory so
"NOTE: beware, the password has to be sha3 hashed
this stores the account and flush keys in memory so
in order to also store derived accounts like initial wallet
and chat accounts, you need to load the account again with
`multiaccount-load-account` before using `multiaccount-store-derived`
and the id of the account stored will have changed"
[account-id password callback]
[account-id hashed-password callback]
(when (status)
(.multiAccountStoreAccount (status)
(types/clj->json {:accountID account-id
:password password})
:password hashed-password})
callback)))
(defn multiaccount-store-derived
[account-id paths password callback]
"NOTE: beware, the password has to be sha3 hashed"
[account-id paths hashed-password callback]
(.multiAccountStoreDerived (status)
(types/clj->json {:accountID account-id
:paths paths
:password password})
:password hashed-password})
callback))
@ -115,12 +122,15 @@
[mnemonic password callback]
(.multiAccountImportMnemonic (status)
(types/clj->json {:mnemonicPhrase mnemonic
;;NOTE this is not the multiaccount password
:Bip39Passphrase password})
callback))
(defn verify [address password callback]
(.verify (status) address password callback))
(defn verify
"NOTE: beware, the password has to be sha3 hashed"
[address hashed-password callback]
(.verify (status) address hashed-password callback))
(defn login-with-keycard
[{:keys [whisper-private-key encryption-public-key on-result]}]
@ -136,26 +146,40 @@
(defn call-private-rpc [payload callback]
(.callPrivateRPC (status) payload callback))
(defn hash-transaction [rpcParams callback]
(defn hash-transaction
"used for keycard"
[rpcParams callback]
(.hashTransaction (status) rpcParams callback))
(defn hash-message [message callback]
(defn hash-message
"used for keycard"
[message callback]
(.hashMessage (status) message callback))
(defn hash-typed-data [data callback]
(defn hash-typed-data
"used for keycard"
[data callback]
(.hashTypedData (status) data callback))
(defn sign-message [rpcParams callback]
(defn send-transaction-with-signature
"used for keycard"
[rpcParams sig callback]
(.sendTransactionWithSignature (status) rpcParams sig callback))
(defn sign-message
"NOTE: beware, the password in rpcParams has to be sha3 hashed"
[rpcParams callback]
(.signMessage (status) rpcParams callback))
(defn sign-typed-data [data account password callback]
(.signTypedData (status) data account password callback))
(defn send-transaction
"NOTE: beware, the password has to be sha3 hashed"
[rpcParams hashed-password callback]
(.sendTransaction (status) rpcParams hashed-password callback))
(defn send-transaction [rpcParams password callback]
(.sendTransaction (status) rpcParams password callback))
(defn send-transaction-with-signature [rpcParams sig callback]
(.sendTransactionWithSignature (status) rpcParams sig callback))
(defn sign-typed-data
"NOTE: beware, the password has to be sha3 hashed"
[data account hashed-password callback]
(.signTypedData (status) data account hashed-password callback))
(defn send-data-notification
[{:keys [data-payload tokens] :as m} on-result]

View File

@ -1,26 +1,25 @@
(ns status-im.signing.core
(:require [status-im.utils.fx :as fx]
[status-im.i18n :as i18n]
[status-im.utils.money :as money]
[status-im.utils.hex :as utils.hex]
[status-im.ethereum.tokens :as tokens]
[status-im.ethereum.core :as ethereum]
[clojure.string :as string]
[status-im.ethereum.abi-spec :as abi-spec]
[status-im.utils.security :as security]
[status-im.utils.types :as types]
[status-im.native-module.core :as status]
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.utils.utils :as utils]
status-im.utils.handlers
[status-im.ethereum.eip55 :as eip55]))
[status-im.ethereum.abi-spec :as abi-spec]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.tokens :as tokens]
[status-im.i18n :as i18n]
[status-im.native-module.core :as status]
[status-im.utils.fx :as fx]
[status-im.utils.hex :as utils.hex]
[status-im.utils.money :as money]
[status-im.utils.security :as security]
[status-im.utils.types :as types]
[status-im.utils.utils :as utils]))
(re-frame/reg-fx
:signing/send-transaction-fx
(fn [{:keys [tx-obj password cb]}]
(fn [{:keys [tx-obj hashed-password cb]}]
(status/send-transaction (types/clj->json tx-obj)
(security/safe-unmask-data password)
hashed-password
cb)))
(re-frame/reg-fx
@ -41,8 +40,8 @@
(re-frame/reg-fx
:signing.fx/sign-typed-data
(fn [{:keys [data account on-completed password]}]
(status/sign-typed-data data account (security/safe-unmask-data password) on-completed)))
(fn [{:keys [data account on-completed hashed-password]}]
(status/sign-typed-data data account hashed-password on-completed)))
(defn get-contact [db to]
(let [to (utils.hex/normalize-hex to)]
@ -63,17 +62,18 @@
[{{:signing/keys [sign tx] :as db} :db}]
(let [{{:keys [data typed?]} :message} tx
{:keys [in-progress? password]} sign
from (ethereum/default-address db)]
from (ethereum/default-address db)
hashed-password (ethereum/sha3 (security/safe-unmask-data password))]
(when-not in-progress?
(merge
{:db (update db :signing/sign assoc :error nil :in-progress? true)}
(if typed?
{:signing.fx/sign-typed-data {:data data
:account from
:password password
:hashed-password hashed-password
:on-completed #(re-frame/dispatch [:signing/sign-message-completed %])}}
{:signing.fx/sign-message {:params {:data data
:password (security/safe-unmask-data password)
:password hashed-password
:account from}
:on-completed #(re-frame/dispatch [:signing/sign-message-completed %])}})))))
@ -92,7 +92,7 @@
(when-not in-progress?
{:db (update db :signing/sign assoc :error nil :in-progress? true)
:signing/send-transaction-fx {:tx-obj tx-obj-to-send
:password password
:hashed-password (ethereum/sha3 (security/safe-unmask-data password))
:cb #(re-frame/dispatch [:signing/transaction-completed % tx-obj-to-send])}})))))
(fx/defn prepare-unconfirmed-transaction

View File

@ -1,6 +1,7 @@
(ns status-im.wallet.accounts.core
(:require [re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.i18n :as i18n]
@ -20,10 +21,10 @@
(re-frame/reg-fx
::generate-account
(fn [{:keys [address password path-num]}]
(fn [{:keys [address hashed-password path-num]}]
(status/multiaccount-load-account
address
password
hashed-password
(fn [value]
(let [{:keys [id error]} (types/json->clj value)]
(if error
@ -36,7 +37,7 @@
(status/multiaccount-store-derived
id
[path]
password
hashed-password
(fn [result]
(let [{:keys [public-key address]}
(get (types/json->clj result) (keyword path))]
@ -59,7 +60,7 @@
{:db (assoc-in db [:generate-account :step] :generating)
::generate-account {:address (get-in db [:multiaccount :address])
:path-num (inc (get-in db [:multiaccount :latest-derived-path]))
:password password}}))
:hashed-password (ethereum/sha3 password)}}))
(fx/defn generate-new-account-error
{:events [::generate-new-account-error]}

View File

@ -4,6 +4,7 @@
and documents which describe the whole \"sign in\" flow."
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.data-store.core :as data-store]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.multiaccounts.login.core :as login.core]
[status-im.test.sign-in.data :as data]))
@ -18,7 +19,7 @@
efx (login.core/login cofx)]
(testing "Change multiaccount."
(is (= (::login.core/login efx)
["{\"name\":\"user\",\"address\":\"address\",\"photo-path\":\"photo\"}" "password"])))
["{\"name\":\"user\",\"address\":\"address\",\"photo-path\":\"photo\"}" (ethereum/sha3 "password")])))
(testing "start activity indicator"
(is (= (get-in efx [:db :multiaccounts/login :processing]) true))))))