diff --git a/README.md b/README.md index 788e1054..80c8e682 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,40 @@ You must manage the `close` of the database before opening a new database. The Web code use `localforage` package to store the datastore in the Browser. The Electron code use `sqlite3`package + +## Database encryption passphrases + +On **iOS** and **Android**, encrypted stores use SQLCipher passphrases from the plugin `Global` defaults (`test secret` / `test new secret`) unless you configure your own. + +**Recommended (Capacitor CLI apps):** set passphrases in `capacitor.config.ts` so they are not patched inside `node_modules`: + +```ts +import type { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + plugins: { + CapgoCapacitorDataStorageSqlite: { + encryptionSecret: 'my-production-passphrase', + encryptionNewSecret: 'my-next-passphrase', + }, + }, +}; + +export default config; +``` + +Then use `openStore` with `encrypted: true` and `mode` set to `secret`, `encryption`, or `newsecret` as described in the API docs. + +**Advanced:** the built-in defaults live in the plugin package (not in your `android/` app tree): + +- Android: `node_modules/@capgo/capacitor-data-storage-sqlite/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java` +- iOS: `node_modules/@capgo/capacitor-data-storage-sqlite/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift` + +Avoid editing those files directly; they are overwritten on install. Prefer `capacitor.config` or a fork of the plugin. + +To open an encrypted `.db` in a desktop SQLCipher tool, use the same passphrase you configured as `encryptionSecret` (or the current secret after a `newsecret` rekey). + + ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): @@ -651,13 +685,13 @@ Get the native Capacitor plugin version #### capOpenStorageOptions -| Prop | Type | Description | -| ---------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`database`** | string | The storage database name | -| **`table`** | string | The storage table name | -| **`encrypted`** | boolean | Set to true for database encryption | -| **`mode`** | string | * Set the mode for database encryption ["encryption", "secret","newsecret"] | -| **`autoVacuum`** | capSQLiteAutoVacuum | Set the SQLite auto_vacuum mode for the store. Use `none`/`0`, `full`/`1`, or `incremental`/`2`. iOS, Android, and Electron only. Web ignores this option. | +| Prop | Type | Description | +| ---------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`database`** | string | The storage database name | +| **`table`** | string | The storage table name | +| **`encrypted`** | boolean | Set to true for database encryption | +| **`mode`** | string | Set the mode for database encryption on iOS and Android. - `encryption` — encrypt an existing plaintext database with the configured passphrase - `secret` — open or create an encrypted database with the configured passphrase - `newsecret` — rekey an encrypted database from `encryptionSecret` to `encryptionNewSecret` Passphrases are set in `capacitor.config` under `plugins.CapgoCapacitorDataStorageSqlite` (see {@link CapgoCapacitorDataStorageSqliteConfig}). Defaults are defined in the plugin's `Global` sources if you do not configure them. | +| **`autoVacuum`** | capSQLiteAutoVacuum | Set the SQLite auto_vacuum mode for the store. Use `none`/`0`, `full`/`1`, or `incremental`/`2`. iOS, Android, and Electron only. Web ignores this option. | #### capStorageOptions diff --git a/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/CapgoCapacitorDataStorageSqlitePlugin.java b/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/CapgoCapacitorDataStorageSqlitePlugin.java index f83e702a..4ad185c4 100644 --- a/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/CapgoCapacitorDataStorageSqlitePlugin.java +++ b/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/CapgoCapacitorDataStorageSqlitePlugin.java @@ -5,8 +5,10 @@ import com.getcapacitor.JSObject; import com.getcapacitor.Plugin; import com.getcapacitor.PluginCall; +import com.getcapacitor.PluginConfig; import com.getcapacitor.PluginMethod; import com.getcapacitor.annotation.CapacitorPlugin; +import com.jeep.plugin.capacitor.capgocapacitordatastoragesqlite.cdssUtils.Global; @CapacitorPlugin(name = "CapgoCapacitorDataStorageSqlite") public class CapgoCapacitorDataStorageSqlitePlugin extends Plugin { @@ -21,8 +23,11 @@ public class CapgoCapacitorDataStorageSqlitePlugin extends Plugin { * Load Method * Load the context */ + @Override public void load() { context = getContext(); + PluginConfig config = getConfig(); + Global.configure(config.getString("encryptionSecret"), config.getString("encryptionNewSecret")); implementation = new CapgoCapacitorDataStorageSqlite(context); } diff --git a/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java b/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java index 82ab1872..d264f629 100644 --- a/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java +++ b/android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java @@ -2,6 +2,26 @@ public class Global { - public String secret = "test secret"; - public String newsecret = "test new secret"; + private static final String DEFAULT_SECRET = "test secret"; + private static final String DEFAULT_NEW_SECRET = "test new secret"; + + private static String secretDefault = DEFAULT_SECRET; + private static String newSecretDefault = DEFAULT_NEW_SECRET; + + public String secret; + public String newsecret; + + public Global() { + secret = secretDefault; + newsecret = newSecretDefault; + } + + public static void configure(String secret, String newSecret) { + if (secret != null && !secret.isEmpty()) { + secretDefault = secret; + } + if (newSecret != null && !newSecret.isEmpty()) { + newSecretDefault = newSecret; + } + } } diff --git a/docs/API.md b/docs/API.md index d776785a..b5045996 100644 --- a/docs/API.md +++ b/docs/API.md @@ -576,12 +576,25 @@ use the `openStore` method with the following options: The existing datastore will be encrypted with a secret key and opens with given database and table names. -To define your own "secret" and "newsecret" keys: +To define your own `secret` and `newsecret` passphrases (Capacitor CLI apps): -- in IOS, go to the Pod/Development Pods/jeepqCapacitor/DataStorageSQLite/Global.swift file -- in Android, go to jeepq-capacitor/java/com.jeep.plugins.capacitor/cdssUtils/Global.java +**Recommended:** set them in `capacitor.config.ts` under `plugins.CapgoCapacitorDataStorageSqlite`: -and then update the default values before building your app. +```ts +plugins: { + CapgoCapacitorDataStorageSqlite: { + encryptionSecret: 'my-production-passphrase', + encryptionNewSecret: 'my-next-passphrase', + }, +}, +``` + +Run `npx cap sync` after changing config. Use `mode: "secret"` or `mode: "encryption"` with `encryptionSecret`, and `mode: "newsecret"` to rekey to `encryptionNewSecret`. + +**Defaults in the plugin package** (do not edit in `node_modules`; values reset on install): + +- iOS: `@capgo/capacitor-data-storage-sqlite` → `ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift` +- Android: `@capgo/capacitor-data-storage-sqlite` → `android/src/main/java/com/jeep/plugin/capacitor/capgocapacitordatastoragesqlite/cdssUtils/Global.java` ### Create a New Encrypted Datastore diff --git a/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/CapgoCapacitorDataStorageSqlitePlugin.swift b/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/CapgoCapacitorDataStorageSqlitePlugin.swift index ffaa62a2..b044717e 100644 --- a/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/CapgoCapacitorDataStorageSqlitePlugin.swift +++ b/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/CapgoCapacitorDataStorageSqlitePlugin.swift @@ -36,6 +36,15 @@ public class CapgoCapacitorDataStorageSqlitePlugin: CAPPlugin, CAPBridgedPlugin private let implementation = CapgoCapacitorDataStorageSqlite() private let retHandler: ReturnHandler = ReturnHandler() + public override func load() { + super.load() + let config = getConfig() + Global.configure( + secret: config.getString("encryptionSecret"), + newSecret: config.getString("encryptionNewSecret") + ) + } + // MARK: - OpenStore @objc func openStore(_ call: CAPPluginCall) { diff --git a/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift b/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift index 9c0db7ce..d947c287 100644 --- a/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift +++ b/ios/Sources/CapgoCapacitorDataStorageSqlitePlugin/Global.swift @@ -8,6 +8,23 @@ import Foundation struct Global { - var secret: String = "test secret" - var newsecret: String = "test new secret" + static var secretDefault: String = "test secret" + static var newsecretDefault: String = "test new secret" + + var secret: String + var newsecret: String + + init() { + secret = Global.secretDefault + newsecret = Global.newsecretDefault + } + + static func configure(secret: String?, newSecret: String?) { + if let secret = secret, !secret.isEmpty { + secretDefault = secret + } + if let newSecret = newSecret, !newSecret.isEmpty { + newsecretDefault = newSecret + } + } } diff --git a/src/definitions.ts b/src/definitions.ts index f7b1e892..f2e79c7f 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -174,9 +174,16 @@ export interface capOpenStorageOptions { * Set to true for database encryption */ encrypted?: boolean; // only for ios and android - /*** - * Set the mode for database encryption - * ["encryption", "secret","newsecret"] + /** + * Set the mode for database encryption on iOS and Android. + * + * - `encryption` — encrypt an existing plaintext database with the configured passphrase + * - `secret` — open or create an encrypted database with the configured passphrase + * - `newsecret` — rekey an encrypted database from `encryptionSecret` to `encryptionNewSecret` + * + * Passphrases are set in `capacitor.config` under `plugins.CapgoCapacitorDataStorageSqlite` + * (see {@link CapgoCapacitorDataStorageSqliteConfig}). Defaults are defined in the plugin's + * `Global` sources if you do not configure them. */ mode?: string; // only for ios and android /** @@ -306,3 +313,30 @@ export interface capStoreJson { */ export?: JsonStore; } + +/** + * Capacitor plugin configuration for `@capgo/capacitor-data-storage-sqlite`. + * + * Add under `plugins.CapgoCapacitorDataStorageSqlite` in `capacitor.config.ts`. + * iOS and Android only (SQLCipher). + * + * @example + * ```ts + * plugins: { + * CapgoCapacitorDataStorageSqlite: { + * encryptionSecret: 'my-production-passphrase', + * encryptionNewSecret: 'my-next-passphrase', + * }, + * }, + * ``` + */ +export interface CapgoCapacitorDataStorageSqliteConfig { + /** + * SQLCipher passphrase used when `openStore` `mode` is `secret` or `encryption`. + */ + encryptionSecret?: string; + /** + * Target passphrase when `openStore` `mode` is `newsecret` (rekey from `encryptionSecret`). + */ + encryptionNewSecret?: string; +}