SecureStore

interface SecureStore

Platform secure storage that holds the wrapping key for sealed state (decision 0078, anchor B). Implemented on the foreign side — iOS/macOS Keychain, Android Keystore — so the key lives where an attacker who can rewrite the state file cannot reach it. That separation is the whole of what sealing is worth: without it, an attacker who rewrites the blob rewrites the key too and the authenticator proves nothing.

The implementation must return the same 32-byte key across restarts for a given install (a changed key makes every restore look like tampering) and must keep it unreadable to a file-rewriter. It is called on the SDK's own threads, from inside a send, a receive or a restore, so it must not touch the UI, wait on the app's threads, or call back into any Tenant or Client method; do the storage work and return. See bindings/swift and bindings/android for a Keychain and a Keystore implementation.

Inheritors

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
abstract fun bumpRollbackCounter(): ULong

Atomically increment and persist the rollback counter, returning the new value. Never decreases. Called on every send and every ratchet-advancing receive (one advance each), not on export; exportStateSealed binds the current value. Because it tracks ratchet advances, a restore of any state older than the latest send presents a lower counter and is caught. Committing here is a per-message secure-storage write, so keep it fast.

Link copied to clipboard
abstract fun rollbackCounter(): ULong

Read the highest rollback counter this store has committed (0 if never). Read-only; used on restore to detect a same-generation rollback. Must be rollback-resistant to a file-rewriter (kept in secure storage) and must survive restarts.

Link copied to clipboard
abstract fun wrapKey(): ByteArray

Return the 32-byte wrapping key, creating and persisting it on first use. Raise an error if secure storage is unavailable — the caller must then use the unsealed path, which makes no rollback claim, rather than fall back to an unprotected key. A store that exists but cannot be reached yet (a Keychain before first unlock, a Keystore that needs the user) throws StoreUnavailable, which the client passes through as that kind, so the app retries after the unlock; anything else is State.