Skip to main content
Encryption at rest means Ditto’s documents and attachments on disk are unreadable without a key. Copying the app’s files or pulling the storage from a device doesn’t expose your data. It matters most for apps that handle sensitive data on devices that can be lost or stolen, such as handhelds, tablets, and kiosks.
App-level encryption at rest is available in the Swift and Kotlin SDKs in version 5.2 and later. Support for other SDKs is planned.

How it works

App-level encryption at rest lets your app encrypt all locally persisted Ditto data, including attachments, with key material that your app supplies. The feature is opt-in. When no encryption key is configured, Ditto creates or opens an unencrypted local store. Ditto uses a 32-byte encryption key directly, so generate high-entropy key material with a cryptographically secure random number generator. Ditto does not store, generate, or manage your encryption key. Your app must provide the same key whenever it opens an encrypted local store, including after each cold start. Store the key outside the Ditto persistence directory, such as in Apple Keychain Services on iOS or the Android Keystore system on Android. Encryption at rest protects locally persisted data only. It does not change Ditto sync behavior, peer discovery, queries, subscriptions, or data transmitted between peers.

Encrypt the local store

Pass the key through DittoConfig.encryptionKey before you open Ditto. Use the same key every time you reopen the store.

Handle encryption errors

Opening a store can fail with a typed encryption error. Your app can tell a missing key from a corrupted store and respond to each one instead of treating every failure the same way. In Swift these are cases on the error thrown by Ditto.open: keyRequired, keyUnexpected, keyInvalid, unsupportedScheme, and metadataCorrupt. In Kotlin they are reasons on DittoException.EncryptionException: KeyRequired, KeyUnexpected, KeyInvalid, UnsupportedScheme, and MetadataCorrupt. The older passphrase error cases are deprecated. Opening an existing encrypted store without a key, or with the wrong key, fails without modifying the store. Opening an existing unencrypted store with a key also fails.

Switch between encrypted and unencrypted storage

Ditto doesn’t convert a store in place. To change between encrypted and unencrypted local storage, close Ditto, delete the existing local store, and reopen it with the desired configuration.
Deleting the local store permanently removes unsynced local changes and resets the local peer identity. Only delete the store when you intend to remove local data, such as when recovering from a lost key, switching between encrypted and unencrypted storage, or wiping a device on logout.

Recover from a lost key

If the encryption key is lost, the local encrypted store cannot be recovered. Delete the local store and let Ditto resync data from other peers. Any changes that hadn’t synced before the key was lost are gone.