Browse Source

feat(rtc): encrypt data for apply-ops

rcmerci 1 month ago
parent
commit
b742e4b3e7

+ 26 - 0
src/main/frontend/worker/rtc/client.cljs

@@ -6,6 +6,8 @@
             [frontend.worker.flows :as worker-flows]
             [frontend.worker.rtc.branch-graph :as r.branch-graph]
             [frontend.worker.rtc.client-op :as client-op]
+            [frontend.worker.rtc.const :as rtc-const]
+            [frontend.worker.rtc.encrypt :as rtc-encrypt]
             [frontend.worker.rtc.exception :as r.ex]
             [frontend.worker.rtc.log-and-state :as rtc-log-and-state]
             [frontend.worker.rtc.malli-schema :as rtc-schema]
@@ -437,6 +439,28 @@
     (client-op/add-ops! repo rename-db-ident-ops)
     nil))
 
+(defn- task--encrypt-remote-ops
+  [encrypt-key remote-ops]
+  (let [encrypt-attr-set (conj rtc-const/encrypt-attr-set :page-name)]
+    (m/sp
+      (loop [[remote-op & rest-remote-ops] remote-ops
+             result []]
+        (if-not remote-op
+          result
+          (let [[op-type op-value] remote-op]
+            (case op-type
+              :update-page
+              (recur rest-remote-ops
+                     (conj result (c.m/<? (rtc-encrypt/<encrypt-map encrypt-key encrypt-attr-set op-value))))
+              :update
+              (recur rest-remote-ops
+                     (conj result
+                           (c.m/<?
+                            (rtc-encrypt/<encrypt-av-coll
+                             encrypt-key rtc-const/encrypt-attr-set (:av-coll op-value)))))
+              ;; else
+              (recur rest-remote-ops (conj result remote-op)))))))))
+
 (defn new-task--push-local-ops
   "Return a task: push local updates"
   [repo conn graph-uuid major-schema-version date-formatter get-ws-create-task *remote-profile? add-log-fn]
@@ -453,6 +477,8 @@
                       other-remote-ops)]
       (when-let [ops-for-remote (rtc-schema/to-ws-ops-decoder remote-ops)]
         (let [local-tx (client-op/get-local-tx repo)
+              encrypt-key-for-test (c.m/<? (rtc-encrypt/<salt+password->key (ldb/get-key-value @conn :logseq.kv/graph-rtc-encrypt-salt) "test-password"))
+              encrypted-remote-ops (m/? (task--encrypt-remote-ops encrypt-key-for-test ops-for-remote))
               r (try
                   (let [message (cond-> {:action "apply-ops"
                                          :graph-uuid graph-uuid :schema-version (str major-schema-version)

+ 48 - 7
src/main/frontend/worker/rtc/encrypt.cljs

@@ -81,7 +81,7 @@
      false
      #js ["encrypt" "decrypt"])))
 
-(defn <encrypt-text
+(defn- <encrypt-text
   [key' plaintext]
   (p/let [iv (js/crypto.getRandomValues (js/Uint8Array. 12))
           data (.encode encoder plaintext)
@@ -92,7 +92,7 @@
                           data)]
     [iv (js/Uint8Array. encrypted-data)]))
 
-(defn <decrypt-text
+(defn- <decrypt-text
   [key' encrypted-package]
   (let [[iv ciphertext] encrypted-package]
     (assert (and (some? iv) (some? ciphertext)))
@@ -104,11 +104,52 @@
       (.decode decoder decrypted-data))))
 
 (defn <decrypt-text-if-encrypted
-  [key' s]
-  (let [maybe-encrypted-package (ldb/read-transit-str s)]
-    (if (string? maybe-encrypted-package)
-      maybe-encrypted-package
-      (<decrypt-text key' maybe-encrypted-package))))
+  "return nil if not a encrypted-package"
+  [key' maybe-encrypted-package]
+  (when (and (vector? maybe-encrypted-package)
+             (<= 2 (count maybe-encrypted-package)))
+    (<decrypt-text key' maybe-encrypted-package)))
+
+(defn <encrypt-map
+  [key' encrypt-attr-set m]
+  (assert (map? m))
+  (reduce
+   (fn [map-p encrypt-attr]
+     (p/let [m map-p]
+       (if-let [v (get m encrypt-attr)]
+         (p/let [v' (p/chain (<encrypt-text key' v) ldb/write-transit-str)]
+           (assoc m encrypt-attr v'))
+         m)))
+   (p/promise m) encrypt-attr-set))
+
+(defn <encrypt-av-coll
+  "see also `rtc-schema/av-schema`"
+  [key' encrypt-attr-set av-coll]
+  (p/all
+   (mapv
+    (fn [[a v & others]]
+      (p/let [v' (if (and (contains? encrypt-attr-set a)
+                          (string? v))
+                   (p/chain (<encrypt-text key' v) ldb/write-transit-str)
+                   v)]
+        (apply conj [a v'] others)))
+    av-coll)))
+
+(defn <decrypt-map
+  [key' encrypt-attr-set m]
+  (assert (map? m))
+  (reduce
+   (fn [map-p encrypt-attr]
+     (p/let [m map-p]
+       (if-let [v (get m encrypt-attr)]
+         (if (string? v)
+           (p/let [v' (<decrypt-text-if-encrypted key' (ldb/read-transit-str v))]
+             (if v'
+               (assoc m encrypt-attr v')
+               m))
+           m)
+         m)))
+   (p/promise m) encrypt-attr-set))
 
 (comment
   (->

+ 1 - 11
src/main/frontend/worker/rtc/full_upload_download_graph.cljs

@@ -130,16 +130,7 @@
            result []]
       (if-not block
         result
-        (let [block' (->> block
-                          (map
-                           (fn [[a v]]
-                             (m/sp
-                               (if (and (contains? encrypt-attr-set a) (string? v))
-                                 [a (ldb/write-transit-str (c.m/<? (rtc-encrypt/<encrypt-text encrypt-key v)))]
-                                 [a v]))))
-                          (apply m/join vector)
-                          (m/?)
-                          (into {}))]
+        (let [block' (c.m/<? (rtc-encrypt/<encrypt-map encrypt-key encrypt-attr-set block))]
           (recur rest-blocks (conj result block')))))))
 
 (comment
@@ -150,7 +141,6 @@
                    (let [k (c.m/<? (rtc-encrypt/<salt+password->key salt "password"))]
                      (m/? (task--encrypt-blocks k #{:block/title :block/name} blocks))))
                  #(def encrypted-blocks %) prn))
-
   )
 
 (defn new-task--upload-graph