[#5180] Encrypt account's db with password
This commit is contained in:
parent
0dd008f7b9
commit
c61200f9ae
|
@ -48,6 +48,7 @@ def prep(type = 'nightly') {
|
|||
sh 'cp .env.jenkins .env'; break
|
||||
}
|
||||
common.installJSDeps('mobile')
|
||||
sh 'cp patches/js_realm.hpp node_modules/realm/src/js_realm.hpp'
|
||||
/* install ruby dependencies */
|
||||
sh 'bundle install --quiet'
|
||||
/* install Maven dependencies */
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
"react-native/Libraries/vendor/emitter/EventEmitter"
|
||||
"react-native-background-timer"
|
||||
"react-native-fetch-polyfill"
|
||||
"react-native-testfairy"]
|
||||
"react-native-testfairy"
|
||||
"text-encoding"
|
||||
"js-sha3"]
|
||||
|
||||
;; Resoures
|
||||
:resource-dirs ["resources/images"]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,6 +42,7 @@
|
|||
"homoglyph-finder": "1.1.1",
|
||||
"identicon.js": "github:status-im/identicon.js",
|
||||
"instabug-reactnative": "2.12.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"level-filesystem": "1.2.0",
|
||||
"metro": "^0.30.2",
|
||||
"nfc-react-native": "github:status-im/nfc-react-native",
|
||||
|
@ -80,6 +81,7 @@
|
|||
"realm": "git+https://github.com/status-im/realm-js.git",
|
||||
"rn-snoopy": "github:status-im/rn-snoopy",
|
||||
"string_decoder": "0.10.31",
|
||||
"text-encoding": "^0.6.4",
|
||||
"url": "0.10.3",
|
||||
"web3": "github:status-im/web3.js#feature/shhext"
|
||||
},
|
||||
|
|
|
@ -4683,6 +4683,11 @@
|
|||
"merge-stream": "1.0.1"
|
||||
}
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
|
@ -7988,6 +7993,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"text-encoding": {
|
||||
"version": "0.6.4",
|
||||
"resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
|
||||
"integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk="
|
||||
},
|
||||
"then-request": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz",
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
"homoglyph-finder": "1.1.1",
|
||||
"identicon.js": "https://github.com/status-im/identicon.js.git",
|
||||
"instabug-reactnative": "2.12.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"level-filesystem": "1.2.0",
|
||||
"process": "0.11.10",
|
||||
"prop-types": "15.6.0",
|
||||
|
@ -60,6 +61,7 @@
|
|||
"realm": "2.15.3",
|
||||
"rn-snoopy": "https://github.com/status-im/rn-snoopy.git",
|
||||
"string_decoder": "0.10.31",
|
||||
"text-encoding": "^0.6.4",
|
||||
"url": "0.10.3",
|
||||
"web3": "https://github.com/status-im/web3.js.git#feature/shhext"
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,12 +24,11 @@
|
|||
(defn clear-web-data! []
|
||||
(status/clear-web-data))
|
||||
|
||||
(defn change-account! [address]
|
||||
(defn change-account! [address password]
|
||||
;; No matter what is the keychain we use, as checks are done on decrypting base
|
||||
(.. (keychain/safe-get-encryption-key)
|
||||
(then (fn [encryption-key]
|
||||
(data-store/change-account address encryption-key)
|
||||
(re-frame/dispatch [:init.callback/account-change-success address])))
|
||||
(then #(data-store/change-account address password %))
|
||||
(then (fn [] (re-frame/dispatch [:init.callback/account-change-success address])))
|
||||
(catch (fn [error]
|
||||
(log/warn "Could not change account" error)
|
||||
;; If all else fails we fallback to showing initial error
|
||||
|
@ -52,7 +51,7 @@
|
|||
(if success
|
||||
(let [{:keys [address password save-password?]} (accounts.db/credentials cofx)]
|
||||
(merge {:accounts.login/clear-web-data nil
|
||||
:data-store/change-account address}
|
||||
:data-store/change-account [address password]}
|
||||
(when save-password?
|
||||
{:keychain/save-user-password [address password]})))
|
||||
{:db (update db :accounts/login assoc
|
||||
|
@ -92,5 +91,5 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
:data-store/change-account
|
||||
(fn [address]
|
||||
(change-account! address)))
|
||||
(fn [[address password]]
|
||||
(change-account! address password)))
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
(log/error "Could not move realms" error)))
|
||||
(then #(data-source/open-base-realm encryption-key)))))
|
||||
|
||||
(defn change-account [address encryption-key]
|
||||
(defn change-account [address password encryption-key]
|
||||
(log/debug "changing account to: " address)
|
||||
(data-source/change-account address encryption-key))
|
||||
(data-source/change-account address password encryption-key))
|
||||
|
||||
(defn- perform-transactions [raw-transactions realm]
|
||||
(let [success-events (keep :success-event raw-transactions)
|
||||
|
|
|
@ -11,28 +11,33 @@
|
|||
[status-im.utils.ethereum.core :as utils.ethereum]
|
||||
[cognitect.transit :as transit]
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[status-im.js-dependencies :as js-dependencies]))
|
||||
|
||||
(defn to-buffer [key]
|
||||
(when key
|
||||
(let [length (.-length key)
|
||||
arr (js/Uint8Array. length)]
|
||||
(dotimes [i length]
|
||||
(aset arr i (aget key i)))
|
||||
(.-buffer arr))))
|
||||
(when-not (nil? key)
|
||||
(when key
|
||||
(let [length (.-length key)
|
||||
arr (js/Int8Array. length)]
|
||||
(dotimes [i length]
|
||||
(aset arr i (aget key i)))
|
||||
arr))))
|
||||
|
||||
(defn encrypted-realm-version
|
||||
"Returns -1 if the file does not exists, the schema version if it successfully
|
||||
decrypts it, error otherwise."
|
||||
decrypts it, throws error otherwise."
|
||||
[file-name encryption-key]
|
||||
(.schemaVersion rn-dependencies/realm file-name (to-buffer encryption-key)))
|
||||
(log/info "encrypted-realm-version\nfile: " file-name " buf " (str encryption-key) (nil? encryption-key))
|
||||
(if encryption-key
|
||||
(.schemaVersion rn-dependencies/realm file-name (to-buffer encryption-key))
|
||||
(.schemaVersion rn-dependencies/realm file-name)))
|
||||
|
||||
(defn open-realm
|
||||
[options file-name encryption-key]
|
||||
(log/debug "Opening realm at " file-name "...")
|
||||
(let [options-js (clj->js (assoc options :path file-name))]
|
||||
(log/debug "Using encryption key...")
|
||||
(set! (.-encryptionKey options-js) (to-buffer encryption-key))
|
||||
(when encryption-key
|
||||
(set! (.-encryptionKey options-js) (to-buffer encryption-key)))
|
||||
(when (exists? js/window)
|
||||
(rn-dependencies/realm. options-js))))
|
||||
|
||||
|
@ -55,10 +60,10 @@
|
|||
utils.platform/android? (str
|
||||
(.-DocumentDirectoryPath rn-dependencies/fs)
|
||||
"/../no_backup/realm/")
|
||||
utils.platform/ios? (str
|
||||
(.-LibraryDirectoryPath rn-dependencies/fs)
|
||||
"/realm/")
|
||||
:else (.-defaultPath rn-dependencies/realm)))
|
||||
utils.platform/ios? (str
|
||||
(.-LibraryDirectoryPath rn-dependencies/fs)
|
||||
"/realm/")
|
||||
:else (.-defaultPath rn-dependencies/realm)))
|
||||
|
||||
(def old-realm-dir
|
||||
(string/replace old-base-realm-path #"default\.realm$" ""))
|
||||
|
@ -105,15 +110,34 @@
|
|||
(defn- migrate-schemas
|
||||
"Apply migrations in sequence and open database with the last schema"
|
||||
[file-name schemas encryption-key current-version]
|
||||
(log/info "migrate schemas")
|
||||
(doseq [schema schemas
|
||||
:when (> (:schemaVersion schema) current-version)
|
||||
:let [migrated-realm (open-realm schema file-name encryption-key)]]
|
||||
(close migrated-realm))
|
||||
(open-realm (last schemas) file-name encryption-key))
|
||||
|
||||
(defn keccak512-array [key]
|
||||
(.array (.-keccak512 js-dependencies/js-sha3) key))
|
||||
|
||||
(defn merge-Uint8Arrays [arr1 arr2]
|
||||
(let [arr1-length (.-length arr1)
|
||||
arr2-length (.-length arr2)
|
||||
arr (js/Uint8Array. (+ arr1-length arr2-length))]
|
||||
(.set arr arr1)
|
||||
(.set arr arr2 arr1-length)
|
||||
arr))
|
||||
|
||||
(defn db-encryption-key [password encryption-key]
|
||||
(let [password-array (.encode
|
||||
(new (.-TextEncoder js-dependencies/text-encoding))
|
||||
password)]
|
||||
(keccak512-array (merge-Uint8Arrays encryption-key password-array))))
|
||||
|
||||
(defn migrate-realm
|
||||
"Migrate realm if is a compatible version or reset the database"
|
||||
[file-name schemas encryption-key]
|
||||
(log/info "migrate-realm")
|
||||
(migrate-schemas file-name schemas encryption-key (encrypted-realm-version
|
||||
file-name
|
||||
encryption-key)))
|
||||
|
@ -125,8 +149,8 @@
|
|||
(defn- index-entity-schemas [all-schemas]
|
||||
(into {} (map (juxt :name identity)) (-> all-schemas last :schema)))
|
||||
|
||||
(def base-realm (atom nil))
|
||||
(def account-realm (atom nil))
|
||||
(defonce base-realm (atom nil))
|
||||
(defonce account-realm (atom nil))
|
||||
|
||||
(def entity->schemas (merge (index-entity-schemas base/schemas)
|
||||
(index-entity-schemas account/schemas)))
|
||||
|
@ -144,10 +168,66 @@
|
|||
(reset! base-realm (open-migrated-realm base-realm-path base/schemas encryption-key))
|
||||
(log/debug "Created @base-realm"))
|
||||
|
||||
(defn change-account [address encryption-key]
|
||||
(let [path (str accounts-realm-dir (utils.ethereum/sha3 address))]
|
||||
(defn re-encrypt-realm
|
||||
[file-name old-key new-key on-success on-error]
|
||||
(let [old-file-name (str file-name "old")]
|
||||
(.. (fs/move-file file-name old-file-name)
|
||||
(then #(fs/unlink (str file-name ".lock")))
|
||||
(then #(fs/unlink (str file-name ".management")))
|
||||
(then #(fs/unlink (str file-name ".note")))
|
||||
(catch (fn [e]
|
||||
(let [message (str "can't move old database " (str e) " " file-name)]
|
||||
(log/debug message)
|
||||
(on-error {:error message}))))
|
||||
(then (fn []
|
||||
(let [old-account-db (open-migrated-realm old-file-name
|
||||
account/schemas
|
||||
old-key)]
|
||||
(log/info "copy old database")
|
||||
(log/info "with key: " (str new-key))
|
||||
(.writeCopyTo old-account-db file-name (to-buffer new-key))
|
||||
(log/info "old database copied")
|
||||
(close old-account-db)
|
||||
(log/info "old database closed")
|
||||
(on-success)
|
||||
(fs/unlink old-file-name)
|
||||
(log/info "old database removed"))))
|
||||
(catch (fn [e]
|
||||
(try (fs/move-file old-file-name file-name)
|
||||
(catch :default _))
|
||||
(let [message (str "something went wrong " (str e) " " file-name)]
|
||||
(log/info message)
|
||||
(on-error {:error message})))))))
|
||||
|
||||
(defn check-db-encryption
|
||||
[file-name old-key new-key]
|
||||
(js/Promise.
|
||||
(fn [on-success on-error]
|
||||
(try
|
||||
(do
|
||||
(log/info "try to encrypt with password")
|
||||
(encrypted-realm-version file-name new-key)
|
||||
(log/info "try to encrypt with password success")
|
||||
(on-success))
|
||||
(catch :default _
|
||||
(do
|
||||
(log/info "try to encrypt with old key")
|
||||
(encrypted-realm-version file-name old-key)
|
||||
(log/info "try to encrypt with old key success")
|
||||
(re-encrypt-realm file-name old-key new-key on-success on-error)))))))
|
||||
|
||||
(defn change-account [address password encryption-key]
|
||||
(let [path (str accounts-realm-dir (utils.ethereum/sha3 address))
|
||||
account-db-key (db-encryption-key password encryption-key)]
|
||||
(close-account-realm)
|
||||
(reset! account-realm (open-migrated-realm path account/schemas encryption-key))))
|
||||
(..
|
||||
(check-db-encryption path encryption-key account-db-key)
|
||||
(then
|
||||
(fn []
|
||||
(log/info "change-account done" (nil? @account-realm))
|
||||
(reset! account-realm
|
||||
(open-migrated-realm path account/schemas account-db-key))
|
||||
(log/info "account-realm " (nil? @account-realm)))))))
|
||||
|
||||
(declare realm-obj->clj)
|
||||
|
||||
|
@ -235,10 +315,10 @@
|
|||
(defmulti to-query (fn [_ operator _ _] operator))
|
||||
|
||||
(defmethod to-query :eq [schema-name _ field value]
|
||||
(let [field-type (field-type schema-name field)
|
||||
query (str (name field) "=" (if (= "string" (name field-type))
|
||||
(str "\"" value "\"")
|
||||
value))]
|
||||
(let [field-type (field-type schema-name field)
|
||||
query (str (name field) "=" (if (= "string" (name field-type))
|
||||
(str "\"" value "\"")
|
||||
value))]
|
||||
query))
|
||||
|
||||
(defn get-by-field
|
||||
|
|
|
@ -5,3 +5,5 @@
|
|||
(def homoglyph-finder (js/require "homoglyph-finder"))
|
||||
(def identicon-js (js/require "identicon.js"))
|
||||
(def Web3 (js/require "web3"))
|
||||
(def text-encoding (js/require "text-encoding"))
|
||||
(def js-sha3 (js/require "js-sha3"))
|
||||
|
|
Loading…
Reference in New Issue