fido2-storage 0.1.0

FIDO2 largeBlob storage with Argon2id + XChaCha20-Poly1305 encryption
docs.rs failed to build fido2-storage-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

fido2-storage

Crates.io License: MIT OR Apache-2.0

FIDO2 largeBlob storage with Argon2id + XChaCha20-Poly1305 encryption.

A pure storage + crypto crate for reading and writing encrypted blobs on FIDO2 hardware (e.g. YubiKey largeBlob). The crate has no knowledge of what is stored — framing, serialization, and application-specific types are the caller's responsibility.

Install

[dependencies]
fido2-storage = "0.1"

To use the interactive device-prompt helpers (stdin/stderr I/O), enable the cli feature:

[dependencies]
fido2-storage = { version = "0.1", features = ["cli"] }

Native dependencies

This crate wraps libfido2 via fido2-rs. The build requires:

  • A C compiler and CMake (for building libfido2 from source)
  • pkg-config (Linux), or FIDO2_LIB_DIR / FIDO2_USE_PKG_CONFIG env vars
  • On macOS with Homebrew: OpenSSL headers are keg-only; export BINDGEN_EXTRA_CLANG_ARGS="-I$(brew --prefix openssl@3)/include" so bindgen can find them

Quick start

use fido2_storage::{Fido2DeviceStore, RelyingParty, CredentialUser};

let rp = RelyingParty {
    id: "my-app.local".to_string(),
    name: "My App".to_string(),
};
let mut store = Fido2DeviceStore::open("hid:///dev/hidraw0", rp)?;

let user = CredentialUser {
    id: &[0x01, 0x02, 0x03, 0x04],
    name: "user1",
    display_name: Some("User One"),
};
let cred_id = store.write_blob(&user, b"raw blob bytes", "1234")?;
let raw = store.read_blob(&cred_id, Some("1234"))?;
# Ok::<(), anyhow::Error>(())

See examples/crypto_roundtrip.rs for a runnable example of the crypto layer (no hardware required):

cargo run --example crypto_roundtrip

Architecture

  • crypto — Argon2id key derivation and XChaCha20-Poly1305 AEAD. KdfParams bundles salt, nonce, and cost parameters in a 68-byte wire format: salt(32) + nonce(24) + memory_cost(4 BE) + iterations(4 BE) + parallelism(4 BE).
  • storeFido2DeviceStore for raw byte I/O on FIDO2 devices. Talks to a connected authenticator (e.g. YubiKey) with the largeBlobKey extension to write, read, list, and delete blobs.

derive_key and encrypt/decrypt are separate functions so the caller controls how many times Argon2id runs. Derive the key once from the user's password, then pass the 32-byte key to encrypt or decrypt. This avoids the double-derivation anti-pattern.

Security notes

  • Argon2id parameters follow OWASP recommendations: 19 MiB memory cost, 2 iterations, 1 lane. Parameter bounds are enforced by KdfParams::validate().
  • Key zeroization — derived keys and decrypted plaintexts are wrapped in Zeroizing, which wipes memory on drop.
  • AAD bindingencrypt/decrypt accept additional authenticated data. Use the blob header as AAD to bind ciphertext to metadata and prevent tampering.
  • PIN policy — write and delete operations require a PIN per the CTAP2 spec. PIN/UV errors are never retried (to avoid device lockout).

License

Dual-licensed under either of

at your option.