Skip to main content
Offline support keeps the logged-in user’s messages in a local database on the device. Turn encryption on to store that database encrypted at rest using SQLCipher. Encryption is opt-in and off by default; nothing changes until you call setEncryption(true). The minimum SDK version is 4.2.0.
Encryption covers the message database only. Downloaded and outgoing media files (photos, voice notes, documents) stay as ordinary unencrypted files on disk, because their local paths are handed to native image and video loaders. See What is and isn’t encrypted.

No extra dependency

iOS needs no separate cipher dependency. The SDK ships its own SQLCipher build and keeps it isolated from your app, so it does not clash with an app’s own SQLite, SQLCipher, GRDB or FMDB. There is nothing to add to your Podfile or Swift package.

Turn on encryption

Set setEncryption(true) on the OfflineConfig you pass to the SDK during initialization (see Enable Offline Support).

Choose what happens when encryption cannot run

encryptionFailureBehavior decides what the cache does when encryption cannot be applied at all on this build or device — the cipher engine is not linked into the build, for example. Because the engine ships inside the SDK this should not happen in a normal app, but the setting is there so you decide the outcome rather than the SDK. It governs only that case: a transient failure (such as a locked Keychain) still retries, and a lost or wrong key self-heals by wiping and rebuilding the cache encrypted.
.plaintextFallback means cached message content may be stored unencrypted on disk whenever encryption cannot run. This availability-over-guarantee trade is wrong for compliance use — keep the default .onlineOnly if cached content must never be written in the clear.
While the cache is dormant for this reason, CometChat.isOfflineEnabled() returns false.

Key storage

You do not supply or manage the encryption key. The SDK generates a random 256-bit key per user (scoped to the app ID and the logged-in user’s UID) and keeps it in the iOS Keychain, with the AfterFirstUnlockThisDeviceOnly accessibility class — available after the first unlock, and never synced or restored to another device. The key is never returned by any API. If the key is lost or the stored database no longer matches it, the cache resets and rebuilds — see Cache resets.

Check encryption status

CometChat.getOfflineEncryptionStatus() returns a [String: Any] dictionary describing what encryption is actually doing — never what was merely requested. It is safe to call at any time and never returns the key or any part of it.
The string values are also available as constants on CometChat.OfflineEncryptionTier (for example OfflineEncryptionTier.atRestSqlcipher).
The single most useful support signal is enabled == true with atRest == "NONE": encryption was switched on but is not in effect — the cache is dormant, still opening, or was opened unencrypted under .plaintextFallback.

What is and isn’t encrypted

Media bytes live outside the database because Attachment.localPath is public API and those paths are passed straight to native media loaders. “Encrypted at rest” here always means the message database, never the media cache. Encryption is not end-to-end: the server still sees message content.

Cache resets on key loss

If the key can no longer decrypt the stored database, the SDK wipes the local cache and rebuilds it encrypted — it never silently falls back to plaintext for a cache that could be encrypted. Any unsent messages still queued in the outbox at that point are lost. They lived inside the unreadable database, so they cannot be counted or reported one by one: pendingMessagesLost is CometChat.offlinePendingCountUnknown (-1). When the reset is .encryptionChanged instead, each queued message fails with reason .discarded and pendingMessagesLost is the exact count, unless the old database could not be read. Register an OfflineCacheResetListener to be told when this happens:
The encryption-related reasons are .keyLost, .wrongKey, .corrupted, .escalated, and .encryptionChanged (you turned encryption on or off between launches, which also discards any queued messages). pendingMessagesLost is CometChat.offlinePendingCountUnknown (-1) when the unsent messages could not be counted. See Stay in Sync for the full cache-reset flow and the complete list of reasons, and the API Reference for every field and enum.
Switching encryption on or off between launches rebuilds the cache in the new format. If the old cache file cannot be deleted at that moment, offline support is unavailable for the rest of that app session.