Skip to main content

Crate lacodda_seal

Crate lacodda_seal 

Source
Expand description

Sealing for the lacodda line: bytes sealed under a key, and a key locked under a passphrase.

Two formats, each a few bytes of header in front of an XChaCha20-Poly1305 ciphertext. The header says which format and which version it is, and everything a reader needs to open it except the secret - so a blob written today opens with a later release of this crate, and a blob from a newer format is refused by name instead of misread.

  • A Key is 32 random bytes. Key::seal turns bytes into a sealed blob, Key::open turns it back - or fails, if the blob was sealed under another key, for another context, or changed on the way.
  • A LockedKey is a key wrapped under a passphrase: Argon2id stretches the passphrase into a key-encryption key, which seals the key. The Argon2id parameters and the salt travel in the header, so the lock can be stored anywhere - next to the data it protects, on a server that must not read it - and opened on any device that knows the passphrase.

Every blob is bound to a context chosen by the caller - a few bytes that say what the blob is for. Opening it under any other context fails, so a blob cannot be moved from one use to another and accepted there.

use lacodda_seal::{Key, LockedKey};

let key = Key::generate()?;
let sealed = key.seal(b"notes/v1", b"the plan for Tuesday")?;
assert_eq!(key.open(b"notes/v1", &sealed)?.as_slice(), b"the plan for Tuesday");
assert!(key.open(b"photos/v1", &sealed).is_err());

// The key itself, locked under a passphrase, can be stored in the open.
let lock = LockedKey::lock(&key, b"correct horse battery staple", b"notes/key")?;
let again = LockedKey::from_bytes(&lock.to_bytes())?.unlock(b"correct horse battery staple", b"notes/key")?;
assert_eq!(again.id(), key.id());

The byte layouts are on the efema documentation site: https://lacodda.github.io/efema/concepts/sealing/.

Structs§

KdfParams
How hard Argon2id works to turn a passphrase into a key.
Key
A symmetric key: 32 bytes, wiped from memory when dropped.
KeyId
The identity of a key: eight bytes of a hash over it.
LockedKey
A key locked under a passphrase.

Enums§

Error
What can go wrong sealing, opening, locking or unlocking.

Constants§

KEY_ID_LEN
Length of a key’s identity, in bytes.
KEY_LEN
Length of a key, in bytes.
LOCKED_LEN
Length of a locked key, in bytes: the header, the wrapped key and its tag.
NONCE_LEN
Length of an XChaCha20-Poly1305 nonce, in bytes.
SALT_LEN
Length of an Argon2id salt, in bytes.
SEALED_OVERHEAD
How many bytes sealing adds to the plaintext: the header and the tag.
TAG_LEN
Length of a Poly1305 tag, in bytes.

Functions§

is_locked_key
Whether bytes start as a locked key does, whatever its version.
is_sealed
Whether bytes start as a sealed blob does - the first byte of the format, whatever its version. For telling the two kinds apart when they travel side by side; Key::open still decides whether one opens.
sealed_key_id
The identity of the key a sealed blob was sealed under, read from its header without opening it.