Skip to main content

Crate day_part_keychain

Crate day_part_keychain 

Source
Expand description

day-part-keychain: small secrets in the platform’s own secure store, by key. No UI; any Rust code can depend on this crate and keep a session token, a password or a key where the OS keeps its own.

use day_part_keychain::{Protection, Secret};

day_part_keychain::set("session", &Secret::from("eyJhbGciOi…"), Protection::WhenUnlocked)?;
let token = day_part_keychain::get("session")?;
println!("{} bytes", token.len());

Platform selection is #[cfg(target_os)]: the data protection keychain on iOS and macOS, the Android Keystore over files in the app’s no-backup directory, DPAPI over files under %LOCALAPPDATA% on Windows, the Secret Service (GNOME Keyring, KDE’s ksecretd, KeePassXC) through libsecret on desktop Linux, and the Universal Keystore over files in the app sandbox on HarmonyOS. The web has no store a page may rely on for a secret, so support reports Unsupported there and every call fails with KeychainError::Unsupported.

§What an item is

An item is a key (a short string the app chooses) and a Secret (up to MAX_SECRET_LEN bytes), stored for this app on this device under a Protection level. Items belong to the app that wrote them: each platform scopes them by the app’s identity (the bundle, the package, the user’s profile and the app id). They survive a reinstall where the platform keeps keychain data across one (Apple) and are removed with the app elsewhere; none of them is backed up or synchronized, because the keys that encrypt them never leave the device.

§Reading an item that needs the person

A Protection::UserPresence item is readable only after the device verifies the person: a biometric or the device credential, in the OS’s own dialog. get is synchronous and never shows that dialog; on such an item it returns KeychainError::NeedsPresence, and the app calls get_async or get_future, which show the dialog and resolve with the secret. The other protection levels resolve without a dialog in either form.

§Threads

The synchronous calls run on the caller’s thread and finish in milliseconds on every platform but Linux, where a locked keyring makes the Secret Service show its unlock dialog during the call; UI code there prefers get_async, which works on a thread of its own. Completions run where the platform delivers them (a worker thread, an Android executor, the HarmonyOS JS thread), which is why the callback is Send; get_future awaited under day::task resumes on the UI thread. Nothing here posts to a main loop, so the crate works in a plain main and under cargo test (docs/async.md rule 3).

Structs§

Entry
One stored item, without its secret.
Secret
Bytes that are wiped when dropped.

Enums§

KeychainError
Why a call did not do what it was asked.
Protection
When an item may be read.
Support

Constants§

MAX_KEY_LEN
The longest key, in UTF-8 bytes. Long enough for a reverse-DNS name with an account after it, short enough for every platform’s identifier and file-name limits.
MAX_SECRET_LEN
The largest secret, in bytes. A keychain holds credentials, not documents: tokens, passwords, keys and the occasional certificate all fit, and every platform store below stays fast at this size.

Functions§

backend
The store selected for this process, as a short name for diagnostics and support notes: data-protection-keychain, login-keychain, android-keystore, dpapi, secret-service, huks, or none.
contains
Whether an item exists under key, without reading it and without a dialog.
entries
Every item this app stored, with its level, without the secrets and without a dialog.
get
The item under key, without a dialog. A Protection::UserPresence item answers KeychainError::NeedsPresence; use get_async or get_future for it.
get_async
The item under key, showing the OS’s verification dialog with reason when the item needs the person present, and answering exactly once, on the platform’s thread. An item at another level resolves without a dialog.
get_future
get_async as a future.
protection_support
Whether one Protection level is realized here: Native where the OS binds the item to it, Emulated where the crate gates the read without a binding (Windows user presence), Unsupported where nothing can honor it (Linux user presence, every level on the web).
remove
Remove the item under key. KeychainError::NotFound when there is none.
set
Store secret under key at protection, replacing any item with that key (whatever its level). Never shows a dialog.
support
What this target’s store promises: Native where the platform keeps the secret in its own store, Emulated where the store is a stand-in with weaker guarantees (an unsigned macOS development build’s login keychain), Unsupported where there is none (the web, a Linux session with no Secret Service).
Day API ↩ Guides· daybrite.dev