AI Integration Quick Reference
AI Integration Quick Reference
encryption: true. The minimum SDK version is 5.1.0. It works on all Flutter targets — Android, iOS, macOS, Windows, Linux and web.
Encryption covers the message database only. Downloaded 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.
Add the cipher engine
Unlike the otherOfflineConfig flags, encryption: true is not sufficient on its own. The cipher engine is chosen by a build hook whose user-defines are read from the root package’s pubspec.yaml only, so the SDK cannot select it on your behalf. Add this stanza to your own app’s pubspec.yaml:
hooks: is a top-level key in your app’s pubspec.yaml — a sibling of dependencies:, not nested under it. You do not need to add any sqlite3 dependency yourself; the SDK already depends on it, and this stanza only selects the cipher-enabled build.
Web
Flutter web needs one extra step: copy the cipher-enabled WebAssembly build the SDK ships into your app’s web root.<version> with your installed cometchat_sdk version, and copy the file again after every SDK upgrade — the asset must match the SDK version. Use the copy the SDK ships, not one from the sqlite3 package — only the bundled build can key a database in the browser. If the asset is missing, the encrypted open fails and encryptionFailureBehavior decides what happens. On web the cipher is ChaCha20-Poly1305 (native targets report AES-256-CBC/HMAC-SHA512) and the key is a non-extractable WebCrypto key, so keyStorage reads OfflineKeyStorage.software; both are real whole-database encryption.
Turn on encryption
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 — for example the cipher engine is not linked, or secure key storage is unavailable. It governs only that case: a transient failure still retries, and a lost or wrong key self-heals by wiping and rebuilding the cache encrypted.
Key storage
You do not supply or manage the encryption key. The SDK generates a random 32-byte key, one per app ID and logged-in user (UID), stores it in the platform’s secure key store, and never returns it from any API. The key never leaves the device. If the key is lost or the stored database no longer matches it, the cache resets and rebuilds — see Cache resets.On all five native targets
keyStorage reports OfflineKeyStorage.keystore, which names the kind of vault, not that hardware is involved: iOS and Android are hardware-backed, while Windows DPAPI, Linux libsecret and the macOS login keychain are OS software stores tied to the login. Web reports OfflineKeyStorage.software.Check encryption status
CometChat.getOfflineEncryptionStatus() returns an OfflineEncryptionStatus 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 normative, cross-SDK wire strings behind these enums (
SQLCIPHER, NONE, KEYSTORE, SOFTWARE, ONLINE_ONLY, PLAINTEXT_FALLBACK) are available through each value’s wireValue, so an auditor gets the same answer from every CometChat SDK.What gets 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.
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. How they are reported depends on the reason. When the reset isencryptionChanged (you turned encryption on or off between launches), each queued message fails with reason discarded and pendingMessagesLost is the exact count. For a key or corruption reset, the queued rows lived inside the unreadable database, so they cannot be counted one by one: they are lost silently and pendingMessagesLost is null. null is not zero — it means an unknown number were lost.
Register an OfflineCacheResetListener to be told when this happens:
keyLost, wrongKey, corrupted, escalated, and encryptionChanged (turning encryption on or off between launches, which also discards any queued messages and the cached media). See Stay in Sync for the full cache-reset flow, and the API Reference for every field and enum.