enhance(rtc,e2ee): init user rsa-pair in debug-ui

This commit is contained in:
rcmerci
2025-10-25 17:01:45 +08:00
committed by Tienson Qin
parent 8b6127b562
commit cdafca7748
4 changed files with 69 additions and 67 deletions

View File

@@ -4,6 +4,28 @@
(defonce subtle (.. js/crypto -subtle))
(defn <export-public-key
[public-key]
(p/let [exported (.exportKey subtle "spki" public-key)]
(js/Uint8Array. exported)))
(defn <import-public-key
[exported-public-key]
(.importKey subtle "spki" exported-public-key
#js {:name "RSA-OAEP" :hash "SHA-256"}
true
#js ["encrypt"]))
(comment
(->
(p/let [kp (<generate-rsa-key-pair)
public-key (:publicKey kp)
exported-public-key (<export-public-key public-key)
public-key* (<import-public-key exported-public-key)
exported-public-key2 (<export-public-key public-key*)]
(prn (= (vec exported-public-key) (vec exported-public-key2))))
(p/catch (fn [e] (prn :e e)))))
(defn <generate-rsa-key-pair
"Generates a new RSA public/private key pair.
Return

View File

@@ -8,6 +8,7 @@
[frontend.state :as state]
[frontend.ui :as ui]
[frontend.util :as util]
[lambdaisland.glogi :as log]
[logseq.db.frontend.schema :as db-schema]
[logseq.shui.ui :as shui]
[missionary.core :as m]
@@ -214,7 +215,7 @@
:placeholder "repo name here"}]]]
[:div.flex.my-2.items-center.gap-2
(ui/button (str "upload current repo")
(ui/button "upload current repo"
{:icon "upload"
:on-click (fn []
(let [repo (state/get-current-repo)
@@ -265,61 +266,22 @@
(shui/button
{:size :sm
:on-click (fn [_]
(p/let [graph-keys (state/<invoke-db-worker :thread-api/rtc-get-graph-keys (state/get-current-repo))
devices (some->> (state/get-auth-id-token)
(state/<invoke-db-worker :thread-api/list-devices))]
(swap! (get state ::keys-state) #(merge % graph-keys {:devices devices}))))}
(shui/tabler-icon "refresh") "keys-state")]
(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)]
(reset! *keys-state user-rsa-key-pair))))}
(shui/tabler-icon "refresh") "keys-state")
(shui/button
{:size :sm
:on-click (fn [_]
(when-let [token (state/get-auth-id-token)]
(p/let [r (state/<invoke-db-worker :thread-api/init-user-rsa-key-pair token (user/user-uuid))]
(when (instance? ExceptionInfo r)
(log/error :thread-api/init-user-rsa-key-pair r)))))}
(shui/tabler-icon "upload") "init upload user rsa-key-pair")]
[:div.pb-4
[:pre.select-text
(-> {:devices (:devices keys-state)
:graph-aes-key-jwk (:aes-key-jwk keys-state)}
(-> keys-state
(fipp/pprint {:width 20})
with-out-str)]]
(shui/button
{:size :sm
:on-click (fn [_]
(when-let [device-uuid (not-empty (:remove-device-device-uuid keys-state))]
(when-let [token (state/get-auth-id-token)]
(state/<invoke-db-worker :thread-api/remove-device token device-uuid))))}
"Remove device:")
[:input.form-input.my-2.py-1.w-32
{:on-change (fn [e] (swap! *keys-state assoc :remove-device-device-uuid (util/evalue e)))
:on-focus (fn [e] (let [v (.-value (.-target e))]
(when (= v "device-uuid here")
(set! (.-value (.-target e)) ""))))
:placeholder "device-uuid here"}]
(shui/button
{:size :sm
:on-click (fn [_]
(when-let [device-uuid (not-empty (:remove-public-key-device-uuid keys-state))]
(when-let [key-name (not-empty (:remove-public-key-key-name keys-state))]
(when-let [token (state/get-auth-id-token)]
(state/<invoke-db-worker :thread-api/remove-device-public-key token device-uuid key-name)))))}
"Remove public-key:")
[:input.form-input.my-2.py-1.w-32
{:on-change (fn [e] (swap! *keys-state assoc :remove-public-key-device-uuid (util/evalue e)))
:on-focus (fn [e] (let [v (.-value (.-target e))]
(when (= v "device-uuid here")
(set! (.-value (.-target e)) ""))))
:placeholder "device-uuid here"}]
[:input.form-input.my-2.py-1.w-32
{:on-change (fn [e] (swap! *keys-state assoc :remove-public-key-key-name (util/evalue e)))
:on-focus (fn [e] (let [v (.-value (.-target e))]
(when (= v "key-name here")
(set! (.-value (.-target e)) ""))))
:placeholder "key-name here"}]
(shui/button
{:size :sm
:on-click (fn [_]
(when-let [token (state/get-auth-id-token)]
(when-let [device-uuid (not-empty (:sync-private-key-device-uuid keys-state))]
(state/<invoke-db-worker :thread-api/rtc-sync-current-graph-encrypted-aes-key
token [(parse-uuid device-uuid)]))))}
"Sync CurrentGraph EncryptedAesKey")
[:input.form-input.my-2.py-1.w-32
{:on-change (fn [e] (swap! *keys-state assoc :sync-private-key-device-uuid (util/evalue e)))
:on-focus (fn [e] (let [v (.-value (.-target e))]
(when (= v "device-uuid here")
(set! (.-value (.-target e)) ""))))
:placeholder "device-uuid here"}]])]))
with-out-str)]]])]))

View File

@@ -6,10 +6,13 @@
(:require ["/frontend/idbkv" :as idb-keyval]
[frontend.common.crypt :as crypt]
[frontend.common.missionary :as c.m]
[frontend.common.thread-api :refer [def-thread-api]]
[frontend.worker.rtc.ws-util :as ws-util]
[frontend.worker.state :as worker-state]
[logseq.db :as ldb]
[missionary.core :as m]
[promesa.core :as p]))
[promesa.core :as p])
(:import [missionary Cancelled]))
(defonce ^:private store (delay (idb-keyval/newStore "localforage" "keyvaluepairs" 2)))
@@ -40,14 +43,15 @@
(defn task--upload-user-rsa-key-pair
"Uploads the user's RSA key pair to the server."
[token user-uuid public-key encrypted-private-key]
[get-ws-create-task user-uuid public-key encrypted-private-key]
(m/sp
(let [{:keys [get-ws-create-task]} (ws-util/gen-get-ws-create-map--memoized (ws-util/get-ws-url token))
(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)
response (m/? (ws-util/send&recv get-ws-create-task
{:action "upload-user-rsa-key-pair"
:user-uuid user-uuid
:public-key public-key
:encrypted-private-key encrypted-private-key}))]
:public-key exported-public-key-str
:encrypted-private-key encrypted-private-key-str}))]
(when (:ex-data response)
(throw (ex-info (:ex-message response)
(assoc (:ex-data response) :type :rtc.exception/upload-user-rsa-key-pair-error)))))))
@@ -103,11 +107,6 @@
[]
(m/sp (c.m/<? (crypt/<generate-aes-key))))
(defn task--get-user-public-key
[get-ws-create-task user-uuid]
(m/sp
(:public-key (m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid)))))
(defn task--get-rsa-key-pair
[get-ws-create-task user-uuid]
(m/sp
@@ -124,6 +123,25 @@
(let [{:keys [_public-key private-key]} (m/? (task--get-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)))
(def-thread-api :thread-api/init-user-rsa-key-pair
[token user-uuid]
(m/sp
(try
(let [{:keys [get-ws-create-task]} (ws-util/gen-get-ws-create-map--memoized (ws-util/get-ws-url token))]
(when-not (m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid))
(let [{:keys [publicKey privateKey]} (c.m/<? (crypt/<generate-rsa-key-pair))
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
(m/? (task--fetch-user-rsa-key-pair get-ws-create-task user-uuid)))))
(catch Cancelled _)
(catch :default e e))))
(comment
(do
(defn- array-buffers-equal?

View File

@@ -152,7 +152,7 @@
worker-util/parse-jwt
:sub)
public-key (when user-uuid
(m/? (rtc-crypt/task--get-user-public-key get-ws-create-task user-uuid)))]
(:public-key (m/? (rtc-crypt/task--fetch-user-rsa-key-pair get-ws-create-task user-uuid))))]
(when-not public-key
(throw (ex-info "user public-key not found" {:type :rtc.exception/not-found-user-rsa-key-pair
:user-uuid user-uuid})))