luksbox header-dump
Decrypt the metadata blob and emit a JSON tree of every inode and chunk reference.
luksbox header-dump <PATH> [--pretty] [--unlock-args]
Decrypts the metadata blob and emits a JSON tree of every inode, chunk reference, generation counter, and keyslot summary. Read-only (never writes). Strictly forensic: this exposes the metadata that the format normally only handles internally.
Requires unlock material (passphrase, FIDO2, TPM, or hybrid). The
output goes to stdout; pipe it into jq for queries.
Examples
Pretty-printed full dump
luksbox header-dump my.lbx --pretty
Quick query: every chunk's slot offset for one file
luksbox header-dump my.lbx \
| jq '.inodes[] | select(.path == "/payload") | .chunks[] | {chunk_idx, slot_offset, generation}'
Quick query: which keyslot kinds are populated
luksbox header-dump my.lbx | jq '.keyslots | map(select(.is_empty == false))'
Output shape
{
"vault": "my.lbx",
"header_storage": "my.lbx",
"header": {
"cipher": "Aes256GcmSiv",
"kdf": "Argon2id",
"chunk_size": 4096,
"flags": 0,
"metadata_offset": 8192,
"metadata_size": 1048576,
"data_offset": 1056768,
"header_salt_prefix": "09ec28b5"
},
"keyslots": [
{ "index": 0, "kind": "Passphrase", "is_empty": false },
{ "index": 1, "kind": "Empty", "is_empty": true }
],
"tree_counters": {
"next_chunk_id": 3,
"next_chunk_gen": 7,
"next_file_id": 3,
"free_chunk_count": 0
},
"inodes": [
{
"id": 1,
"path": "/",
"kind": "dir",
"size_raw": 0,
"children": [
{ "id": 2, "name": "payload" }
]
},
{
"id": 2,
"path": "/payload",
"kind": "file",
"size_raw": 12000,
"chunks": [
{ "chunk_idx": 0, "chunk_id": 0, "generation": 4, "slot_offset": 1056768 },
{ "chunk_idx": 1, "chunk_id": 1, "generation": 5, "slot_offset": 1060892 },
{ "chunk_idx": 2, "chunk_id": 2, "generation": 6, "slot_offset": 1065016 }
]
}
]
}
Field reference
header
| Field | Meaning |
|---|---|
cipher |
AEAD primitive: Aes256GcmSiv, Aes256Gcm, or ChaCha20Poly1305 |
kdf |
KDF identifier (currently always Argon2id) |
chunk_size |
Chunk plaintext size in bytes (always 4096 today) |
flags |
Bitfield: bit 0 = FLAG_PAD_FILES_POW2, bit 1 = FLAG_HIDE_SIZE_HEADER |
metadata_offset / metadata_size |
Offset and capacity of the AEAD-encrypted metadata region |
data_offset |
Offset where the data region (4 KiB chunks) begins |
header_salt_prefix |
First 4 bytes of the per-vault HKDF salt, hex. The full 32 bytes are not exposed: a public dump that included the salt would let an attacker reproduce subkey derivations if they ever recovered the MVK |
keyslots
One row per slot (always 8 rows; empty ones too). kind is the
SlotKind enum: Passphrase, Fido2HmacSecret, Fido2DerivedMvk,
Tpm2Sealed, Tpm2Pin, Tpm2Fido2, HybridPq*, or Empty.
tree_counters
| Field | Meaning |
|---|---|
next_chunk_id |
Next chunk_id to be allocated for a fresh write |
next_chunk_gen |
Next chunk-generation counter (monotonic, used in chunk AAD for replay protection) |
next_file_id |
Next file_id to be allocated |
free_chunk_count |
Number of chunk_ids on the LIFO free-list (freed and reusable) |
inodes
Every inode in the vault, sorted by id for stable diffs. path
is the full vault-internal path. size_raw is the raw stored size:
in FLAG_HIDE_SIZE_HEADER mode, this is the padded chunk capacity,
not the real file length (the real length lives in chunk 0's first
8 bytes). For directories, children lists (name, id). For
files, chunks lists every chunk reference with its computed
slot_offset (so you can dd if=vault.lbx bs=1 skip=<offset> count=4124 to inspect the raw nonce + ciphertext + tag).
Security notes
- The dump exposes file paths, file sizes, and chunk metadata that are normally encrypted on disk. Treat the output as confidential. Do not paste it into a public bug report without redacting paths.
header_salt_prefixis intentionally truncated to 4 bytes. Full salt exposure is not needed for forensics and would marginally weaken the vault if the dump ever leaked while the MVK was also exposed.- The chunk plaintext is not included in the dump. To extract
plaintext, use
get(strict) orextract(lossy).
See the forensics page for the full recovery flow this subcommand fits into.