diff --git a/ios/App/App/FileSync/FileSync.m b/ios/App/App/FileSync/FileSync.m index bec982aeb..2804f17b3 100644 --- a/ios/App/App/FileSync/FileSync.m +++ b/ios/App/App/FileSync/FileSync.m @@ -19,5 +19,7 @@ CAP_PLUGIN(FileSync, "FileSync", CAP_PLUGIN_METHOD(updateRemoteFiles, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(encryptFnames, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(decryptFnames, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(decryptWithPassphrase, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(encryptWithPassphrase, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(updateLocalVersionFiles, CAPPluginReturnPromise); ) diff --git a/ios/App/App/FileSync/FileSync.swift b/ios/App/App/FileSync/FileSync.swift index 8a9c28de4..0d16f90ad 100644 --- a/ios/App/App/FileSync/FileSync.swift +++ b/ios/App/App/FileSync/FileSync.swift @@ -218,6 +218,47 @@ public class FileSync: CAPPlugin, SyncDebugDelegate { } call.resolve(["value": fnames]) } + + @objc func encryptWithPassphrase(_ call: CAPPluginCall) { + guard let passphrase = call.getString("passphrase"), + let content = call.getString("content") else { + call.reject("required parameters: passphrase, content") + return + } + guard let ciphertext = content.data(using: .utf8) else { + call.reject("cannot decode ciphertext with utf8") + return + } + call.keepAlive = true + DispatchQueue.global(qos: .background).async { + if let encrypted = AgeEncryption.encryptWithPassphrase(ciphertext, passphrase, armor: true) { + call.resolve(["data": String(data: encrypted, encoding: .utf8) as Any]) + } else { + call.reject("cannot encrypt with passphrase") + } + } + } + + + @objc func decryptWithPassphrase(_ call: CAPPluginCall) { + guard let passphrase = call.getString("passphrase"), + let content = call.getString("content") else { + call.reject("required parameters: passphrase, content") + return + } + guard let ciphertext = content.data(using: .utf8) else { + call.reject("cannot decode ciphertext with utf8") + return + } + call.keepAlive = true + DispatchQueue.global(qos: .background).async { + if let decrypted = AgeEncryption.decryptWithPassphrase(ciphertext, passphrase) { + call.resolve(["data": String(data: decrypted, encoding: .utf8) as Any]) + } else { + call.reject("cannot decrypt with passphrase") + } + } + } @objc func getLocalFilesMeta(_ call: CAPPluginCall) { // filePaths are url encoded diff --git a/src/main/frontend/encrypt.cljs b/src/main/frontend/encrypt.cljs index cb00ee4c9..1ad1da8cc 100644 --- a/src/main/frontend/encrypt.cljs +++ b/src/main/frontend/encrypt.cljs @@ -9,7 +9,8 @@ [promesa.core :as p] [electron.ipc :as ipc] [shadow.loader :as loader] - [lambdaisland.glogi :as log])) + [lambdaisland.glogi :as log] + [frontend.mobile.util :as mobile-util])) (defonce age-pem-header-line "-----BEGIN AGE ENCRYPTED FILE-----") (defonce age-version-line "age-encryption.org/v1") @@ -96,6 +97,12 @@ encrypted (ipc/ipc "encrypt-with-passphrase" passphrase raw-content)] (utf8/decode encrypted)) + (mobile-util/native-ios?) + (p/chain (.encryptWithPassphrase mobile-util/file-sync + (clj->js {:passphrase passphrase :content content})) + #(js->clj % :keywordize-keys true) + :data) + :else (p/let [lazy-encrypt-with-user-passphrase (resolve 'frontend.extensions.age-encryption/encrypt-with-user-passphrase) content (utf8/encode content) @@ -110,6 +117,12 @@ decrypted (ipc/ipc "decrypt-with-passphrase" passphrase raw-content)] (utf8/decode decrypted)) + (mobile-util/native-ios?) + (p/chain (.decryptWithPassphrase mobile-util/file-sync + (clj->js {:passphrase passphrase :content content})) + #(js->clj % :keywordize-keys true) + :data) + :else (p/let [_ (loader/load :age-encryption) lazy-decrypt-with-user-passphrase (resolve 'frontend.extensions.age-encryption/decrypt-with-user-passphrase)