Manifest Format¶
1 Overview¶
The manifest maps opaque blob IDs to target file paths. It is stored encrypted
and GPG-signed at .vault/manifest.gpg and decrypted on every operation.
2 Format¶
2.1 v2 (current, since 0.2.0)¶
# vault-manifest-v2
a1b2c3d4e5f67890 ~/.secret/api_key.txt e3b0c44298fc1c14...
fedcba9876543210 ~/.config/app/credentials.json a7ffc6f8bf1ed766...
First line: version header (
# vault-manifest-v2)Subsequent lines:
<id>\t<path>\t<sha256>Blank lines and lines starting with
#are ignored
The sha256 field contains the SHA-256 hex digest of the corresponding
.vault/<id>.gpg blob. On unseal, each blob hash is verified before
decryption.
2.2 v1 (legacy, pre-0.2.0)¶
# vault-manifest-v1
a1b2c3d4e5f67890 ~/.secret/api_key.txt
fedcba9876543210 ~/.config/app/credentials.json
v1 manifests lack blob hashes and are unsigned. unseal rejects v1 manifests by
default. Pass --allow-unsigned to accept them, then run seal to upgrade to
v2.
2.3 Fields¶
id16-character lowercase hex string, generated from 8 bytes of cryptographic randomness (
std/sysrand).pathTarget file path. Paths under
$HOMEare stored with~/prefix for portability across machines. In root-relative mode, paths are stored relative to the configured root. Absolute paths outside$HOMEare stored as-is.hash(v2 only) SHA-256 hex digest of the encrypted
.gpgblob. Used for integrity verification onunseal.
3 Blob files¶
Each manifest entry has a corresponding .vault/<id>.gpg file containing the
GPG-encrypted and signed file contents. The --set-filename "" flag is used
during encryption to avoid leaking the original filename in GPG metadata.
All blobs are signed with the user’s default GPG key during seal and add.
4 Integrity model¶
The signed manifest is the integrity anchor. On unseal:
The manifest is decrypted and its GPG signature is verified
Each blob’s SHA-256 hash is compared against the manifest
Blobs are decrypted to temporary files
Each blob’s GPG signature is verified
Only after all checks pass are files moved to their final paths
This prevents forgery (attacker encrypts a malicious blob to your public key), ciphertext swapping (attacker renames blobs), and manifest replacement (attacker substitutes a v1 unsigned manifest).
5 Directory layout¶
.vault/
config # recipient configuration (plaintext)
manifest.gpg # signed + encrypted manifest
a1b2c3d4e5f67890.gpg # signed + encrypted blob
fedcba9876543210.gpg # signed + encrypted blob
Only .vault/ is committed to git. The plaintext files live at their target
paths outside the repository.