HKDF-TREE(1) FreeBSD General Commands Manual HKDF-TREE(1)

hkdf-treedeterministic hierarchical passphrase derivation from a master seed

hkdf-tree derive [--salt salt] --info info [--output-len n] [--raw]

hkdf-tree list --config file [-v, --verbose] [--status status] [--derivation kind]

hkdf-tree show --config file --entry info-string [--newline]

hkdf-tree report --config file --output file [--title title] [--subtitle subtitle] [--fingerprint fp] [--entry info-string] [--status status] [--derivation kind]

hkdf-tree derives passphrases deterministically from a single high-entropy master seed using HKDF-SHA256 (RFC 5869). Each credential is identified by a hierarchical info-string of the form <domain>/<realm>/<purpose>-v<N>, declared in a YAML inventory together with its encoding (Diceware, alphanumeric, numeric, or base64). The same seed, salt, and info-string always reproduce the same passphrase; nothing derived is ever stored.

Subcommands that derive (derive, show, report) read the master seed as from standard input. Hex-encoded seeds must be decoded first, for example with ‘xxd -r -p’.

Apply HKDF-SHA256 to the seed on stdin with --salt and --info, and write --output-len bytes (default 32) to stdout, hex-encoded unless --raw is given. This is the low-level primitive; it does not consult an inventory.
Load and validate the inventory given by --config and print one info-string per entry, deterministically sorted. -v adds derivation kind, status, and encoding per line. --status (active, retired, reserved) and --derivation (hkdf, manual, service-generated) filter the listing and may be repeated.
Derive and encode a single entry, looked up by --entry, and print the resulting passphrase to stdout without a trailing newline (add one with --newline). Entries with manual or service-generated derivation are refused.
Generate a printable A4 PDF (--output), one card per inventory entry: a human-readable title (the purpose's usage text) next to a QR code, followed by info-string, encoding, passphrase, paper-backup destinations, and notes. The output file is created with mode 0600. --fingerprint prints a short seed fingerprint on the cover page for cross-verification against the paper backup.

By default every entry is included. --entry restricts the report to the given info-string and may be repeated; --status and --derivation filter as they do for list, but apply only when --entry is absent, so an explicitly named entry can never be dropped silently. Selection happens derivation: passphrases of unselected entries are never computed and therefore never reach the output file. Reprinting one card thus exposes exactly that one secret. An info-string that matches nothing is an error, and no file is written — otherwise a typo would be indistinguishable from a successful run until the passphrase is needed and cannot be reproduced.

The hkdf-tree utility exits 0 on success, and >0 if an error occurs. A usage error (unknown flag, missing argument) exits with status 2.

Derive the low-level bytes for one entry:

xxd -r -p seed.hex | hkdf-tree derive \
    --salt acme-hkdf-v1 --info alice/laptop/fde-daily-v1

List all active HKDF-derived entries:

hkdf-tree list --config ~/.config/hkdf-tree/inventory.yaml \
    --status active --derivation hkdf -v

Reproduce one passphrase:

hkdf-tree show --config inventory.yaml \
    --entry alice/laptop/fde-daily-v1 --newline < seed.bin

Generate the paper-backup report:

hkdf-tree report --config inventory.yaml \
    --output /tmp/report.pdf --subtitle "$(date +%F)" < seed.bin

Reprint a single card, deriving nothing else:

hkdf-tree report --config inventory.yaml \
    --entry alice/laptop/fde-recovery-v1 \
    --output /tmp/one.pdf < seed.bin

gpg(1), RFC 5869

Project documentation: README.md, docs/ in the source repository.

Dr. Johannes Brügmann <dr.johannes.bruegmann@gmail.com>

The PDF report contains every derived passphrase in plaintext. Write it to volatile storage (tmpfs), print on an offline printer, and destroy the file afterwards; the tool never encrypts anything itself. The master seed should only be entered on trusted, preferably air-gapped systems. The inventory file contains no secrets, only structure and public parameters (including the salt), and may be backed up freely.

FreeBSD 15.1-RELEASE-p2 August 2, 2026 HKDF-TREE(1)