AeroVault
Military-grade encrypted vault format for single-file encrypted containers.
AeroVault combines AES-256-GCM-SIV (nonce misuse-resistant), Argon2id (128 MiB), AES-256-KW key wrapping, and optional ChaCha20-Poly1305 cascade encryption into a portable .aerovault file format.
The current container format is v3, which binds a per-file 16-byte file_id into the chunk AAD to prevent chunk splicing and reordering. Existing v2 containers stay fully supported (read, write, and in-place re-encrypt); the crypto stack below is shared by both.
Since 0.5.0 the crate also ships the unified .aerocorrect Reed-Solomon sidecar format: a detached, content-SHA-bound recovery file for any byte stream. It can protect .aerovault containers or ordinary files, repair is atomic and all-or-nothing, and the format v2 sidecar is self-healing so a lightly-corrupted recovery file still recovers. See Error Correction below.
Cryptographic Stack
| Layer | Algorithm | Standard |
|---|---|---|
| KDF | Argon2id (128 MiB, t=4, p=4) | RFC 9106 |
| Key Wrapping | AES-256-KW | RFC 3394 |
| Content Encryption | AES-256-GCM-SIV | RFC 8452 |
| Cascade Mode | ChaCha20-Poly1305 | RFC 8439 |
| Filename Encryption | AES-256-SIV | RFC 5297 |
| Header Integrity | HMAC-SHA512 | RFC 2104 |
| Key Separation | HKDF-SHA256 | RFC 5869 |
| Error Correction | Reed-Solomon parity sidecar | .aerocorrect v2 (self-healing) |
Installation
From source
From crates.io
CLI Usage
# Create a new vault
# Create with cascade encryption (AES-GCM-SIV + ChaCha20-Poly1305)
# Add files
# Add files to a directory
# List contents
# Extract a specific file
# Extract all
# Create directories
# Delete an entry
# Rename an entry in place
# Move or rename across directories
# Copy file or directory to another path
# Show security info
# Change password
# Check if file is an AeroVault
# Generate a detached recovery sidecar for any file
# Verify without modifying the file
# Repair in place from my-vault.aerovault.aerocorrect
Library Usage
use ;
// Create a new vault
let opts = new
.with_mode;
let vault = create?;
// Add files
vault.add_files?;
// Open and list
let vault = open?;
for entry in vault.list?
// Extract
vault.extract?;
// Rename in place (same parent directory)
vault.rename_entry?;
// Move (works for files and directories)
vault.move_entry?;
// Copy (works for files and directories)
vault.copy_entry?;
Error Correction API
use ;
Format Specification
See docs/AEROVAULT-V2-SPEC.md for the base binary layout. The current v3 container keeps that layout and adds a per-file 16-byte file_id to the chunk AAD (inner AEAD and the optional ChaCha20-Poly1305 cascade). The file_id is stored in the AES-SIV-authenticated manifest and the on-disk version is covered by the HMAC-SHA512 header MAC, so neither can be stripped to force the legacy path. See docs/AEROCORRECT-SPEC.md for the detached Error Correction sidecar. See the CHANGELOG (0.4.0, 0.5.0) for the v3 and .aerocorrect deltas.
Error Correction (.aerocorrect)
.aerocorrect is a detached, par2-style Reed-Solomon recovery sidecar for any byte stream. It protects the bytes of the target without embedding anything into it, so the same format repairs .aerovault containers, synced files, or ordinary standalone files. The sidecar binds to the SHA-256 of the protected content, not to a path, salt, account, or provider identity.
Error correction is the last wrapper in the AeroVault stack, so it protects the ciphertext bytes and never has to decode the format. For a .aerovault the parity lives in a sibling file by default, so the container stays byte-identical to a plain v3.
CLI
# Generate a detached recovery sidecar (writes report.bin.aerocorrect)
)) for
# Verify without modifying the file
# ...after a 4 KiB run in report.bin is overwritten with zeros...
# Repair in place from the sidecar
) )
Overhead levels
CLI levels map to storage-overhead targets; the exact Reed-Solomon grid is stored in each payload, so readers reconstruct from the payload metadata rather than from a CLI-level assumption.
| Level | Target overhead | Reed-Solomon grid |
|---|---|---|
low |
~7% | approx K=14, P=1 |
medium |
~15% | approx K=13, P=2 |
quartile |
~25% | K=8, P=2 |
high |
~30% | approx K=7, P=2 |
| numeric | 5-50% | clamped into the supported range |
Self-healing (format v2)
The small metadata that locates everything (the segment directory, content hash, and per-window geometry) is stored in triplicate with per-copy checksums, so a lightly-corrupted sidecar still recovers: a single rotted directory copy is detected and the read falls back to a good copy. The bulk parity carries no wholesale envelope checksum; every Reed-Solomon shard already carries its own checksum, so a rotted parity shard is treated as an erasure and routed around at repair time. (The pre-v2 framing used an all-or-nothing checksum that rejected any flip; v2 sidecars are written today, v1 sidecars are still read.)
Bounded memory
Generation and repair run in 64 MiB windows and read sidecar parity on demand, so memory is bounded to one window plus that window's parity payload regardless of file size (the EC file cap is 1 GiB).
Security model
Repair is fail-closed and all-or-nothing: the rebuilt stream is re-verified against the bound content hash (and, for a vault, its authenticated header MAC / manifest cipher_hash) before the original is replaced. A corrupt or foreign sidecar can therefore only make a repair fail, never overwrite good data. The atomic temp-and-rename write means a crash mid-repair never leaves a half-written original.
Feature / version matrix
| Surface | Reads | Writes |
|---|---|---|
| Vault container | v2, v3 | v3 |
.aerocorrect sidecar |
v1, v2 | v2 (self-healing) |
The .aerocorrect format is shared byte-for-byte with AeroFTP v4: a sidecar produced by either implementation verifies and repairs with the other for the same file and overhead level (a cross-implementation fixture pins this). See docs/AEROCORRECT-SPEC.md for the full binary layout.
vs Cryptomator
| AeroVault | Cryptomator v8 | |
|---|---|---|
| KDF | Argon2id (128 MiB) | scrypt (64 MiB) |
| Content cipher | AES-256-GCM-SIV | AES-256-GCM |
| Nonce misuse resistance | Yes | No |
| Cascade mode | Optional | No |
| Storage | Single file | Directory tree |
| Implementation | Rust | Java |
Security
- All key material is zeroized after use
- Constant-time MAC comparison prevents timing attacks
- File-id-bound chunk AAD (current format) prevents chunk splicing and reordering
- Extraction opens outputs with
O_NOFOLLOW+create_newto refuse symlink redirection - Per-chunk lengths are bounds-checked before allocation
.aerocorrectrepair verifies the final SHA-256 before replacing the original- Atomic writes prevent corruption on crash
- 128 MiB Argon2id makes GPU brute-force impractical
License
GPL-3.0 -- See LICENSE for details.
Origin
AeroVault was originally developed as the encryption engine for AeroFTP, a professional FTP/SFTP/cloud client. This standalone crate makes the format available for any Rust project.
Acknowledgements
From the v3 format work onward, the AeroVault wrapper-stack pipeline model (the packing / chunking / chunk-id / compression / crypt / cipher-hash taxonomy) is a design contribution by Ehud Kirsh (E. Kirsh), AeroFTP issue #162, 2026. Ehud has also provided sustained community testing of AeroVault across releases. The wrapper-stack format itself is implemented in the AeroFTP application; this crate provides the stable v2 / current-format library it builds on.