Skip to content

Secure Storage

Sudhi S edited this page Jul 28, 2026 · 1 revision

Secure Storage

SecureDatastore encrypts values at rest using platform key management — Keychain on iOS, an AndroidKeyStore-backed AES-256-GCM key on Android. Use it for auth tokens, refresh tokens, and encryption keys.

final secure = SecureDatastore();

await secure.setString('refresh_token', tokenJwt);
final token = await secure.getString('refresh_token');

await secure.setBytes('symmetric_key', keyBytes);
final key = await secure.getBytes('symmetric_key');

await secure.remove('refresh_token');
await secure.clear(); // wipes every secret

API surface

Intentionally minimal — String and Uint8List only:

Method Purpose
setString / getString store / read a string secret
setBytes / getBytes store / read raw bytes
remove(key) delete both buckets for a key
clear() wipe all secrets
getKeys() list stored keys (values stay encrypted)
containsKey(key) membership check
configure({multiProcess, appGroupId}) cross-process access — see Multi-Process Access

Values are capped at 1 MiB. Errors surface as NativeDatastoreException.

How it protects your data

Platform Backing
iOS Keychain (kSecClassGenericPassword, …AfterFirstUnlockThisDeviceOnly) — readable after first unlock, never backed up or device-migrated.
Android AES-256-GCM with a key in the AndroidKeyStore (hardware-backed where available), fresh IV per write, stored in a dedicated DataStore file. Requires API 23+.

In scope: confidentiality of secrets at rest (offline storage/backup dumps). Out of scope: a rooted/jailbroken or otherwise compromised runtime where the app is already under attacker control. See the threat model and SECURITY.md.

Notes & gotchas

  • String vs bytes are independent buckets. setString('t', …) and setBytes('t', …) coexist under the same key; remove('t') clears both.
  • Android < 23 throws UnsupportedOperationException from the secure API only — the regular NativeDatastore still works.
  • clear() does not delete the platform key, only the stored values.

Clone this wiki locally