module

Secrets::Vault

Vault encryption / decryption via shell-out to the age(1) binary (https://age-encryption.org).

v0.1 supports single-recipient only. Both encrypt and decrypt are streaming via stdin/stdout — the plaintext is never written to a disk file. The identity (private key) is briefly written to a mode-0600 temp file because age -i requires a path; the file is deleted as soon as age returns.

Instance methods

binary

Override at runtime (tests).

Source
decrypt(ciphertext : String, identity : String) : String

Decrypt ciphertext (ASCII-armored age PEM) using identity (an "AGE-SECRET-KEY-1..." private key string). Returns the plaintext as a String.

Source
decrypt_with_passphrase(ciphertext : String, passphrase : String) : String

Decrypt a passphrase-encrypted recovery paper blob.

Source
encrypt(plaintext : String, recipient : String) : String

Encrypt plaintext to ASCII-armored age PEM for recipient (a public key string starting with "age1...").

Single-recipient overload retained for backward compatibility with the v0.1–v0.3 API. New code should prefer the array form.

Source
encrypt(plaintext : String, recipients : Array(String)) : String

Encrypt plaintext to ASCII-armored age PEM for the given list of recipient public keys. Each key must start with "age1...". age(1) natively supports multi-recipient encryption: any of the corresponding identities can later decrypt the file.

Empty list raises VaultError — encrypting to nobody is never what the caller intended.

Source
encrypt_with_passphrase(plaintext : String, passphrase : String) : String

Encrypt with a passphrase (used for the recovery paper export). age -p prompts via /dev/tty; we feed the passphrase on a second pipe via the AGE_PASSPHRASE env var when available, or via a tty wrapper. Simplest robust path: shell-out to age -p with the passphrase fed twice on stdin (age prompts then asks for confirmation when encrypting). Encrypt with a passphrase (used for the recovery paper export).

Why not age -p? Because age -p insists on reading the passphrase from /dev/tty, which can't be fed without spawning a pseudo-terminal. For the paper recovery use case we use openssl enc with PBKDF2 (600 000 iterations, SHA-256, AES-256-CBC), which accepts the passphrase via -pass pass:STRING directly. openssl is available on every Unix-like system (LibreSSL on macOS, OpenSSL on Linux/FreeBSD).

The output is base64-armored and wrapped in PEM-like markers so the paper format is clearly identifiable.

Source
tmpdir

Where to put the brief identity tempfile. macOS doesn't expose a tmpfs by default; /tmp is fine for a sub-100ms exposure.

Source