mirror of
https://github.com/logseq/logseq.git
synced 2026-05-29 23:19:38 +00:00
feat(rtc,e2ee): reset e2ee password
This commit is contained in:
@@ -1199,7 +1199,10 @@
|
||||
token (state/get-auth-id-token)
|
||||
[rsa-key-pair set-rsa-key-pair!] (hooks/use-state :not-inited)
|
||||
[init-key-err set-init-key-err!] (hooks/use-state nil)
|
||||
[get-key-err set-get-key-err!] (hooks/use-state nil)]
|
||||
[get-key-err set-get-key-err!] (hooks/use-state nil)
|
||||
[old-password set-old-password!] (hooks/use-state nil)
|
||||
[new-password set-new-password!] (hooks/use-state nil)
|
||||
[reset-password-status set-reset-password-status!] (hooks/use-state nil)]
|
||||
(hooks/use-effect!
|
||||
(fn []
|
||||
(when (and user-uuid token)
|
||||
@@ -1220,14 +1223,34 @@
|
||||
(when init-key-err [:p (str "Init key-pair err:" init-key-err)])
|
||||
(shui/button
|
||||
{:on-click (fn []
|
||||
(-> (p/let [key-pair (state/<invoke-db-worker :thread-api/init-user-rsa-key-pair
|
||||
;; :thread-api/force-reset-user-rsa-key-pair
|
||||
token user-uuid)]
|
||||
(set-rsa-key-pair! key-pair))
|
||||
(-> (p/do!
|
||||
(state/<invoke-db-worker :thread-api/init-user-rsa-key-pair
|
||||
token user-uuid)
|
||||
(p/let [r (state/<invoke-db-worker :thread-api/get-user-rsa-key-pair token user-uuid)]
|
||||
(set-rsa-key-pair! r)))
|
||||
(p/catch set-init-key-err!)))}
|
||||
"Init E2EE encrypt-key-pair")]
|
||||
rsa-key-pair
|
||||
[:p "E2EE key-pair already generated!"]))]))
|
||||
[:div
|
||||
[:p "E2EE key-pair already generated!"]
|
||||
[:h2 "Old Password:"]
|
||||
(shui/input
|
||||
{:type "password"
|
||||
:on-change #(set-old-password! (util/evalue %))})
|
||||
[:h2 "New Password:"]
|
||||
(shui/input
|
||||
{:type "password"
|
||||
:on-change #(set-new-password! (util/evalue %))})
|
||||
(when reset-password-status [:p reset-password-status])
|
||||
(shui/button
|
||||
{:on-click (fn []
|
||||
(-> (p/do!
|
||||
(set-reset-password-status! "Updating E2EE password ...")
|
||||
(state/<invoke-db-worker :thread-api/reset-e2ee-password
|
||||
token user-uuid old-password new-password)
|
||||
(set-reset-password-status! "E2EE password updated!"))
|
||||
(p/catch (fn [_] (set-reset-password-status! "Wrong old-password")))))}
|
||||
"Reset Password")]))]))
|
||||
|
||||
(rum/defc settings-collaboration
|
||||
[]
|
||||
|
||||
@@ -268,8 +268,8 @@
|
||||
:on-click (fn [_]
|
||||
(when-let [user-uuid (user/user-uuid)]
|
||||
(p/let [user-rsa-key-pair (state/<invoke-db-worker
|
||||
:thread-api/get-user-rsa-key-pair-from-indexeddb
|
||||
user-uuid)]
|
||||
:thread-api/get-user-rsa-key-pair
|
||||
(state/get-auth-id-token) user-uuid)]
|
||||
(reset! *keys-state user-rsa-key-pair))))}
|
||||
(shui/tabler-icon "refresh") "keys-state")
|
||||
(shui/button
|
||||
@@ -279,15 +279,7 @@
|
||||
(p/let [r (state/<invoke-db-worker :thread-api/init-user-rsa-key-pair token (user/user-uuid))]
|
||||
(when (instance? ExceptionInfo r)
|
||||
(log/error :init-user-rsa-key-pair r)))))}
|
||||
(shui/tabler-icon "upload") "init upload user rsa-key-pair")
|
||||
(shui/button
|
||||
{:size :sm
|
||||
:on-click (fn [_]
|
||||
(when-let [token (state/get-auth-id-token)]
|
||||
(p/let [r (state/<invoke-db-worker :thread-api/force-reset-user-rsa-key-pair token (user/user-uuid))]
|
||||
(when (instance? ExceptionInfo r)
|
||||
(log/error :force-reset-user-rsa-key-pair r)))))}
|
||||
(shui/tabler-icon "upload") "force-reset upload user rsa-key-pair")]
|
||||
(shui/tabler-icon "upload") "init upload user rsa-key-pair")]
|
||||
[:div.pb-4
|
||||
[:pre.select-text
|
||||
(-> keys-state
|
||||
|
||||
@@ -27,24 +27,26 @@
|
||||
(assert (and k @store))
|
||||
(idb-keyval/set k value @store))
|
||||
|
||||
(defn- <remove-item!
|
||||
[k]
|
||||
(idb-keyval/del k @store))
|
||||
(comment
|
||||
(defn- <remove-item!
|
||||
[k]
|
||||
(idb-keyval/del k @store)))
|
||||
|
||||
(defn- graph-encrypted-aes-key-idb-key
|
||||
[repo]
|
||||
(assert (some? repo))
|
||||
(str "rtc-encrypted-aes-key###" repo))
|
||||
|
||||
(defn- user-rsa-key-pair-idb-key
|
||||
[user-uuid]
|
||||
(assert (some? user-uuid))
|
||||
(str "user-rsa-key-pair###" user-uuid))
|
||||
(comment
|
||||
(defn- user-rsa-key-pair-idb-key
|
||||
[user-uuid]
|
||||
(assert (some? user-uuid))
|
||||
(str "user-rsa-key-pair###" user-uuid)))
|
||||
|
||||
(defn task--upload-user-rsa-key-pair
|
||||
"Uploads the user's RSA key pair to the server."
|
||||
[get-ws-create-task user-uuid public-key encrypted-private-key & {:keys [force-reset]
|
||||
:or {force-reset false}}]
|
||||
[get-ws-create-task user-uuid public-key encrypted-private-key & {:keys [reset-private-key]
|
||||
:or {reset-private-key false}}]
|
||||
(m/sp
|
||||
(let [exported-public-key-str (ldb/write-transit-str (c.m/<? (crypt/<export-public-key public-key)))
|
||||
encrypted-private-key-str (ldb/write-transit-str encrypted-private-key)
|
||||
@@ -53,13 +55,13 @@
|
||||
:user-uuid user-uuid
|
||||
:public-key exported-public-key-str
|
||||
:encrypted-private-key encrypted-private-key-str
|
||||
:force-reset force-reset}))]
|
||||
:reset-private-key reset-private-key}))]
|
||||
(when (:ex-data response)
|
||||
(throw (ex-info (:ex-message response)
|
||||
(assoc (:ex-data response) :type :rtc.exception/upload-user-rsa-key-pair-error)))))))
|
||||
|
||||
(defn task--fetch-user-rsa-key-pair
|
||||
"Fetches the user's RSA key pair, from indexeddb or server.
|
||||
"Fetches the user's RSA key pair from server.
|
||||
Return {:public-key CryptoKey, :encrypted-private-key [array,array,array]}
|
||||
Return nil if not exists"
|
||||
[get-ws-create-task user-uuid]
|
||||
@@ -68,26 +70,17 @@
|
||||
(when-let [exported-public-key (ldb/read-transit-str public-key-transit-str)]
|
||||
(c.m/<? (crypt/<import-public-key exported-public-key)))))]
|
||||
(m/sp
|
||||
(let [key-pair (c.m/<? (<get-item (user-rsa-key-pair-idb-key user-uuid)))]
|
||||
(if key-pair
|
||||
(let [public-key (m/? (task--import-public-key (:public-key key-pair)))]
|
||||
{:public-key public-key
|
||||
:encrypted-private-key (ldb/read-transit-str (:encrypted-private-key key-pair))})
|
||||
(let [response (m/? (ws-util/send&recv get-ws-create-task
|
||||
{:action "fetch-user-rsa-key-pair"
|
||||
:user-uuid user-uuid}))]
|
||||
(if (:ex-data response)
|
||||
(throw (ex-info (:ex-message response)
|
||||
(assoc (:ex-data response)
|
||||
:type :rtc.exception/fetch-user-rsa-key-pair-error)))
|
||||
(let [{:keys [public-key encrypted-private-key]} response]
|
||||
(when (and public-key encrypted-private-key)
|
||||
(c.m/<? (<set-item! (user-rsa-key-pair-idb-key user-uuid)
|
||||
(clj->js
|
||||
{:public-key public-key
|
||||
:encrypted-private-key encrypted-private-key})))
|
||||
{:public-key (m/? (task--import-public-key public-key))
|
||||
:encrypted-private-key (ldb/read-transit-str encrypted-private-key)})))))))))
|
||||
(let [response (m/? (ws-util/send&recv get-ws-create-task
|
||||
{:action "fetch-user-rsa-key-pair"
|
||||
:user-uuid user-uuid}))]
|
||||
(if (:ex-data response)
|
||||
(throw (ex-info (:ex-message response)
|
||||
(assoc (:ex-data response)
|
||||
:type :rtc.exception/fetch-user-rsa-key-pair-error)))
|
||||
(let [{:keys [public-key encrypted-private-key]} response]
|
||||
(when (and public-key encrypted-private-key)
|
||||
{:public-key (m/? (task--import-public-key public-key))
|
||||
:encrypted-private-key (ldb/read-transit-str encrypted-private-key)})))))))
|
||||
|
||||
(defn task--fetch-graph-aes-key
|
||||
"Fetches the AES key for a graph, from indexeddb or server.
|
||||
@@ -135,9 +128,16 @@
|
||||
(let [{:keys [_public-key private-key]} (m/? (task--get-decrypted-rsa-key-pair get-ws-create-task user-uuid))]
|
||||
(m/? (task--fetch-graph-aes-key get-ws-create-task graph-uuid private-key)))))
|
||||
|
||||
(def-thread-api :thread-api/get-user-rsa-key-pair-from-indexeddb
|
||||
[user-uuid]
|
||||
(<get-item (user-rsa-key-pair-idb-key user-uuid)))
|
||||
(defn task--reset-user-rsa-private-key
|
||||
"Throw if decrypt encrypted-private-key failed."
|
||||
[get-ws-create-task user-uuid old-password new-password]
|
||||
(m/sp
|
||||
(let [{:keys [public-key encrypted-private-key]}
|
||||
(m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid))
|
||||
private-key (c.m/<? (crypt/<decrypt-private-key old-password encrypted-private-key))
|
||||
new-encrypted-private-key (c.m/<? (crypt/<encrypt-private-key new-password private-key))]
|
||||
(m/? (task--upload-user-rsa-key-pair get-ws-create-task user-uuid public-key new-encrypted-private-key
|
||||
:reset-private-key true)))))
|
||||
|
||||
(def-thread-api :thread-api/get-user-rsa-key-pair
|
||||
[token user-uuid]
|
||||
@@ -149,11 +149,6 @@
|
||||
{:public-key (c.m/<? (crypt/<export-public-key public-key))
|
||||
:encrypted-private-key encrypted-private-key}))))
|
||||
|
||||
(def-thread-api :thread-api/throw-ex-test
|
||||
[]
|
||||
(m/sp
|
||||
(throw (ex-info "throw test" {}))))
|
||||
|
||||
(def-thread-api :thread-api/init-user-rsa-key-pair
|
||||
[token user-uuid]
|
||||
(m/sp
|
||||
@@ -164,92 +159,12 @@
|
||||
{:keys [password]} (c.m/<? (worker-state/<invoke-main-thread :thread-api/request-e2ee-password))
|
||||
encrypted-private-key (c.m/<? (crypt/<encrypt-private-key password privateKey))]
|
||||
(m/? (task--upload-user-rsa-key-pair get-ws-create-task user-uuid publicKey encrypted-private-key))
|
||||
;; fetch again
|
||||
(c.m/<? (<remove-item! (user-rsa-key-pair-idb-key user-uuid)))
|
||||
(m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid))
|
||||
(c.m/<? (<get-item (user-rsa-key-pair-idb-key user-uuid))))))
|
||||
nil)))
|
||||
(catch Cancelled _)
|
||||
(catch :default e e))))
|
||||
|
||||
(def-thread-api :thread-api/force-reset-user-rsa-key-pair
|
||||
[token user-uuid]
|
||||
(def-thread-api :thread-api/reset-e2ee-password
|
||||
[token user-uuid old-password new-password]
|
||||
(m/sp
|
||||
(try
|
||||
(let [{:keys [get-ws-create-task]} (ws-util/gen-get-ws-create-map--memoized (ws-util/get-ws-url token))
|
||||
{:keys [publicKey privateKey]} (c.m/<? (crypt/<generate-rsa-key-pair))
|
||||
{:keys [password]} (c.m/<? (worker-state/<invoke-main-thread :thread-api/request-e2ee-password))
|
||||
encrypted-private-key (c.m/<? (crypt/<encrypt-private-key password privateKey))]
|
||||
(m/? (task--upload-user-rsa-key-pair get-ws-create-task user-uuid publicKey encrypted-private-key
|
||||
:force-reset true))
|
||||
;; fetch again
|
||||
(c.m/<? (<remove-item! (user-rsa-key-pair-idb-key user-uuid)))
|
||||
(m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid))
|
||||
(c.m/<? (<get-item (user-rsa-key-pair-idb-key user-uuid))))
|
||||
(catch Cancelled _)
|
||||
(catch :default e e))))
|
||||
|
||||
(comment
|
||||
(do
|
||||
(defn- array-buffers-equal?
|
||||
[buf1 buf2]
|
||||
(if (not= (.-byteLength buf1) (.-byteLength buf2))
|
||||
false
|
||||
(let [arr1 (js/Uint8Array. buf1)
|
||||
arr2 (js/Uint8Array. buf2)]
|
||||
(= (vec arr1) (vec arr2)))))
|
||||
|
||||
(def user-uuid "test-user-uuid")
|
||||
(def graph-uuid "test-graph-uuid")
|
||||
(def password "test-password")
|
||||
(def token "test-token")
|
||||
|
||||
;; Prepare keys
|
||||
(def prepare-keys-task
|
||||
(m/sp
|
||||
(let [rsa-key-pair (c.m/<? (crypt/<generate-rsa-key-pair))
|
||||
public-key (:publicKey rsa-key-pair)
|
||||
private-key (:privateKey rsa-key-pair)
|
||||
encrypted-private-key (c.m/<? (crypt/<encrypt-private-key password private-key))
|
||||
aes-key (c.m/<? (crypt/<generate-aes-key))
|
||||
encrypted-aes-key (c.m/<? (crypt/<encrypt-aes-key public-key aes-key))]
|
||||
{:public-key public-key
|
||||
:private-key private-key
|
||||
:encrypted-private-key encrypted-private-key
|
||||
:aes-key aes-key
|
||||
:encrypted-aes-key encrypted-aes-key})))
|
||||
|
||||
;; Run test
|
||||
(def cancel
|
||||
(c.m/run-task*
|
||||
(m/sp
|
||||
(prn "--- Start testing crypt.cljs ---")
|
||||
(let [{:keys [public-key private-key encrypted-private-key aes-key encrypted-aes-key] :as xxx}
|
||||
(m/? prepare-keys-task)]
|
||||
(def xxx xxx)
|
||||
(prn "1. Test fetch from local storage")
|
||||
(prn " Clean local storage first")
|
||||
(c.m/<? (<remove-item! (user-rsa-key-pair-idb-key user-uuid)))
|
||||
(c.m/<? (<remove-item! (graph-encrypted-aes-key-idb-key graph-uuid)))
|
||||
|
||||
(prn " Set items to local storage")
|
||||
(c.m/<? (<set-item! (user-rsa-key-pair-idb-key user-uuid)
|
||||
(clj->js
|
||||
{:public-key public-key
|
||||
:encrypted-private-key encrypted-private-key})))
|
||||
(c.m/<? (<set-item! (graph-encrypted-aes-key-idb-key graph-uuid) encrypted-aes-key))
|
||||
|
||||
(prn " Fetch user rsa key pair from local storage")
|
||||
(let [fetched-key-pair (m/? (task--fetch-user-rsa-key-pair token user-uuid password))
|
||||
exported-public-key (c.m/<? (.exportKey crypt/subtle "spki" public-key))
|
||||
exported-fetched-public-key (c.m/<? (.exportKey crypt/subtle "spki" (:public-key fetched-key-pair)))]
|
||||
(assert (array-buffers-equal? exported-public-key exported-fetched-public-key))
|
||||
(prn " Fetched user rsa key pair successfully"))
|
||||
|
||||
(prn " Fetch graph aes key from local storage")
|
||||
(let [fetched-aes-key (m/? (task--fetch-graph-aes-key token graph-uuid private-key))
|
||||
exported-aes-key (c.m/<? (.exportKey crypt/subtle "raw" aes-key))
|
||||
exported-fetched-aes-key (c.m/<? (.exportKey crypt/subtle "raw" fetched-aes-key))]
|
||||
(assert (array-buffers-equal? exported-aes-key exported-fetched-aes-key))
|
||||
(prn " Fetched graph aes key successfully"))
|
||||
|
||||
(prn "--- Test finished ---")))))))
|
||||
(let [{:keys [get-ws-create-task]} (ws-util/gen-get-ws-create-map--memoized (ws-util/get-ws-url token))]
|
||||
(m/? (task--reset-user-rsa-private-key get-ws-create-task user-uuid old-password new-password)))))
|
||||
|
||||
@@ -395,9 +395,9 @@
|
||||
["upload-user-rsa-key-pair"
|
||||
[:map
|
||||
[:user-uuid :uuid]
|
||||
[:public-key :string]
|
||||
[:public-key {:optional true} :string]
|
||||
[:encrypted-private-key :string]
|
||||
[:force-reset {:optional true} :boolean]]]
|
||||
[:reset-private-key {:optional true} :boolean]]]
|
||||
["fetch-user-rsa-key-pair"
|
||||
[:map
|
||||
[:user-uuid :uuid]]]
|
||||
|
||||
Reference in New Issue
Block a user