Skip to main content

Module keystore

Module keystore 

Source
Expand description

Overridable, per-platform secure storage for a persisted identity seed.

KeyPair::save/load write a raw file — explicitly documented there as “a testing/parity convenience,” not what a real mobile binding should use. This module is the real answer: a small KeyStore trait plus KeyringStore, a default implementation backed by the keyring crate, which selects the actual native secure store per target automatically — Keychain (Security.framework) on macOS and iOS, Secret Service (D-Bus) on Linux, Credential Manager on Windows, and the Android Keystore (via JNI) on Android. Nothing in this crate branches on target platform itself; keyring’s own Cargo.toml does that selection via per-target optional dependencies (see keyring = 4.2.0’s manifest), and the backend that ends up linked is what actually runs.

KeyStore itself is deliberately not tied to keyring at all — a caller with a different secure-storage requirement (a hardware security module, a different vault) can implement the trait directly and hand it to KeyPair::save_to_keystore/ load_from_keystore — “overridable per target platform” is a property of the trait boundary, not something wired into this crate’s own logic.

§Android setup, required once per app, not something this crate can do for you

android-native-keyring-store (the backend keyring links in for Android, confirmed via its own Cargo.toml: jni + ndk-context) needs the embedding app to hand it a JNI Context once at startup, because Android’s Keystore is a Java API with no NDK surface — there is no way for Rust code alone to reach it. That crate ships its own JNI export for exactly this (confirmed in its README, not assumed): once this crate is linked into an Android .so, that export is present automatically, and the Kotlin side calls it once, e.g. from MainActivity.onCreate:

package io.crates.keyring
class Keyring {
    companion object {
        init { System.loadLibrary("your_actual_library_name") }
        external fun initializeNdkContext(context: Context)
    }
}
// in onCreate:
Keyring.initializeNdkContext(this.applicationContext)

No custom UniFFI foreign-trait bridge is needed for Android or iOS — both have first-party keyring backends, confirmed by reading keyring 4.2.0’s own Cargo.toml target-cfg dependency blocks directly, not assumed from the crate’s name.

§A second Linux backend, LinuxKeyutilsStore

KeyringStore’s Linux path (keyring’s v1 API) unconditionally uses the D-Bus Secret Service, which requires a running provider (gnome-keyring, KWallet) — absent on headless boxes, containers, and this crate’s own dev sandbox (confirmed directly: a D-Bus session socket exists here, but no org.freedesktop.secrets provider is listening on it, so KeyringStore::new returns KeyStoreError::Backend with NoDefaultStore). LinuxKeyutilsStore uses the kernel’s own keyutils facility instead, always available on Linux — this is exactly what lets this module’s own tests verify a real save/load/delete round trip in this environment.

Structs§

KeyringStore
The default KeyStore: the platform-native secure store keyring selects for the current target (see this module’s own doc). service and account are the same two strings every keyring consumer already uses to address one credential — pick values scoped to this application, e.g. ("com.example.myapp", "macula-identity"), since the underlying stores are shared OS-wide facilities, not sandboxed to this crate.
LinuxKeyutilsStore
A second, independently-selectable KeyStore backend — proof that the trait boundary is genuinely overridable, not merely declared to be: the kernel’s own keyutils facility, no D-Bus/secret-service daemon required. This is what KeyringStore’s underlying keyring dependency itself recommends for headless Linux (containers, CI, a sandboxed dev box with no gnome-keyring/kwalletd running) — see linux-keyutils-keyring-store’s own module doc, which states this outright.

Enums§

KeyStoreError

Traits§

KeyStore
Secure storage for a 32-byte identity seed. Implement this directly for a backend other than KeyringStore (a hardware security module, a different vault) — this is the override point “per target platform” hangs off, not a platform enum this crate switches on internally.