Encrypted vaults that survive the next decade.
Open-source, FIDO2 + TPM 2.0 native, post-quantum-ready.
Store sensitive files in the cloud or on shared media without trusting the host.
Website | Docs | Security | Fuzzing | Compare
You probably already store sensitive files where you don't fully control the storage: cloud sync (iCloud, Drive, Dropbox, OneDrive, S3, Backblaze), NAS units, USB sticks that travel, backup tapes that end up at a recycler. The provider promises encryption-at-rest "with their keys." LUKSbox encrypts the file before it ever leaves your machine, under your keys, in a single container that is opaque to the provider and tamper-evident on the way back.
A LUKSbox vault is one file (.lbx), optionally with a separate
header (.hdr) and post-quantum sidecar (.kyber) that you keep on
different storage. Drop it on any cloud or shared medium. The
provider sees one indistinguishable-from-random blob and cannot
decrypt it even under legal compulsion. Mount it locally as a real
drive when you need to use it.
| Concern | Plain cloud upload | Cloud + provider encryption | LUKSbox vault on cloud |
|---|---|---|---|
| Provider can read your files | Yes | Yes (they hold the key) | No |
| Government request to provider exposes data | Yes | Yes | No |
| Silent file tamper detected | No | Sometimes (TLS in transit only) | Yes (per-chunk AEAD) |
| Whole-vault rollback detected | No | No | Yes (anchor sidecar) |
| "Harvest now, decrypt later" (post-quantum) | Vulnerable | Vulnerable | ML-KEM-768/1024 hybrid slot |
| Hardware-key requirement to open | N/A | Provider-specific | FIDO2 / TPM / Windows Hello |
| Vault file looks like random data | No | No | Yes (with detached header) |
| Source you can audit | No | No | Yes (Apache-2.0) |
The full per-tool comparison (vs LUKS2 / VeraCrypt / age / gocryptfs / Cryptomator / BitLocker / FileVault) lives at https://luksbox.penthertz.com/compare/.
A LUKSbox vault is a travelling copy, not a master copy. Use it for the cloud, a USB stick, a vault you share with a colleague or client, anywhere you would not put plaintext. Like every encrypted container it is a single point of failure: if the
.lbxfile is corrupted or every keyslot becomes inaccessible, the data is gone. The forensic toolkit (header-backup,check,extract --tolerate-errors) helps in many damage scenarios but cannot recover bytes that are no longer on disk or no longer AEAD-tagged. Always keep an unencrypted copy somewhere you trust for any file you cannot afford to lose.
This is a pre-1.0 release. The on-disk format is locked, the cryptographic primitives are NIST/RFC standards built on RustCrypto, and 9 internal audit rounds have shipped. External paid audit and broader real-world deployment are the next milestones. The cloud-storage threat model, provider can't read your data even under subpoena, is what LUKSbox is built for and what it does today.
| Surface | State |
|---|---|
cargo test --workspace |
200+ passing, 0 failing, 0 ignored |
cargo audit (Linux/macOS) |
0 vulns / 0 unsound / 0 unmaintained |
cargo audit (Windows) |
1 unmaintained (registry, transitive via WinFsp) |
| Internal audit rounds | 9 documented at https://luksbox.penthertz.com/docs/security/audit/ (per-round details kept internal) |
| Third-party audit | not yet performed; engagement scope package available on request to security@penthertz.com |
| Fuzz iterations across 10 libFuzzer harnesses | 30M+ |
flowchart LR
User[User knowledge<br/>passphrase or PIN] --> Unlock[Unlock material]
FIDO[FIDO2 authenticator<br/>hmac-secret] --> Unlock
TPM[TPM 2.0<br/>sealed KEK] --> Unlock
PQ[ML-KEM seed file<br/>separate storage] --> Unlock
Unlock --> KEK[Key encryption key]
KEK --> MVK[Master volume key]
MVK --> HeaderMac[Header HMAC key]
MVK --> MetadataKey[Metadata AEAD key]
MVK --> FileKeys[Per-file HKDF keys]
MVK --> AnchorKey[Anchor HMAC key]
HeaderMac --> Header[Authenticated header]
MetadataKey --> Metadata[Encrypted metadata tree]
FileKeys --> Chunks[Encrypted file chunks]
AnchorKey --> Anchor[Rollback anchor]
The Master Volume Key (MVK) is the root secret. Keyslots do not
encrypt files directly; they wrap the MVK. Once a valid keyslot
unwraps the MVK, every other key in the vault is derived from it via
HKDF-SHA256 with a per-purpose info string. Lose the keyslot
material, lose the MVK; revoke a slot and that material is
permanently unable to recover the MVK from this vault.
For the full architecture map (on-disk graph, unlock sequence, concurrency / crash-safety pipeline, on-disk footprint), see https://luksbox.penthertz.com/docs/security/architecture/.
| Mechanism | What it does | Where it lives |
|---|---|---|
| AES-256-GCM-SIV (default) / AES-256-GCM / ChaCha20-Poly1305 | AEAD on every file chunk and on the metadata blob | crates/luksbox-core/src/aead.rs |
| HMAC-SHA256 over the entire 8 KiB header | Detects header tampering once a keyslot unwraps the MVK | crates/luksbox-core/src/header.rs |
HKDF-SHA256 with per-purpose info strings |
Derives every subkey from the MVK; uniqueness verified by regression test | crates/luksbox-core/src/key.rs |
| Argon2id (default 256 MiB / 3 / 4) | Stretches passphrases; cost params bounded by parser to reject DoS attempts | crates/luksbox-core/src/kdf.rs |
| FIDO2 hmac-secret (CTAP2 sec.6.5) | Hardware-backed unlock, wrap mode or direct mode | crates/luksbox-fido2/ |
| TPM 2.0 sealed KEK (Linux) | Bind a vault to the local chip; optional PIN; fused TPM+FIDO2 mode | crates/luksbox-tpm/ |
| ML-KEM-768 / ML-KEM-1024 (FIPS 203) | Post-quantum half of every hybrid keyslot; classical+PQ mixed via HKDF | crates/luksbox-pq/ |
| Per-chunk AAD (`file_id | chunk_index | |
Detached header sidecar (.hdr) |
Vault file alone is opaque random, no magic, no version, no keyslots | crates/luksbox-format/src/container.rs |
Anchor sidecar (.anchor) |
External rollback detection via MVK-keyed HMAC over a generation counter | crates/luksbox-format/src/anchor.rs |
| Lock-before-read open | Concurrent enrolls / revokes can't race on the keyslot table | crates/luksbox-format/src/container.rs::open |
| Post-lock path-inode re-stat | Catches narrow open-then-rename TOCTOU swaps with Error::PathSubstituted |
crates/luksbox-format/src/container.rs::verify_path_inode |
| Atomic temp + rename + parent-dir fsync | All sidecar writes survive power loss; works on POSIX (fsync on dir handle) and Windows (FILE_FLAG_BACKUP_SEMANTICS + FlushFileBuffers) |
crates/luksbox-core/src/file_util.rs |
O_NOFOLLOW on plaintext extraction |
luksbox get refuses pre-existing symlink destinations to defeat attacker-staged symlink-target overwrites |
crates/luksbox-core/src/file_util.rs::secure_create_or_truncate |
memfd_secret(2) for the unlocked MVK on Linux 5.14+ |
Excludes the MVK from coredumps and hibernate images; mlock + Zeroize fallback elsewhere |
crates/luksbox-core/src/secret_box.rs |
Workspace-wide Zeroizing audit on every secret-bearing intermediate |
AEAD plaintext, HKDF I/O, ML-KEM shared, CLI/GUI PIN copies all scrub on drop | covered across luksbox-core, luksbox-pq, luksbox-tpm, luksbox-cli |
The full attack matrix (defended vs not defended) is at https://luksbox.penthertz.com/docs/security/threat-model/.
# Create a vault (defaults: AES-256-GCM-SIV, Argon2id interactive)
luksbox create my-vault.lbx
# Mount it on a drive letter / mountpoint
luksbox mount my-vault.lbx /mnt/v # Linux/macOS
luksbox mount my-vault.lbx Z: # Windows
# Add a FIDO2 hardware factor
luksbox enroll my-vault.lbx --kind fido2
# Add a TPM 2.0 keyslot bound to this machine (Linux)
luksbox enroll my-vault.lbx --kind tpm2
# Hybrid post-quantum: needs a separate `.kyber` seed file
luksbox create my-vault.lbx --kind hybrid-pq \
--pq-hybrid /media/usb/my.kyber
# v3 format: no per-vault size ceiling (default v2 caps around 10 GiB).
# Old LUKSbox binaries refuse v3 vaults -- opt in only when you need
# bigger vaults than the v2 default can hold.
luksbox create my-vault.lbx --format v3
# Migrate an existing v2 vault to v3 (source untouched)
luksbox migrate-to-v3 old-v2.lbx --dst new-v3.lbx
# Interactive walkthrough, no flags to remember
luksbox wizardThree interfaces, one on-disk format: the luksbox CLI for scripts,
the luksbox wizard interactive TUI, and the luksbox-gui desktop
application. See https://luksbox.penthertz.com/docs/ for per-flow
walkthroughs.
| Platform | Method |
|---|---|
| Debian / Ubuntu / Mint | .deb from Releases, sudo apt install ./luksbox_*_amd64.deb |
| Fedora / RHEL / Rocky | .rpm from Releases, sudo dnf install ./luksbox-*.x86_64.rpm |
| macOS | .dmg from Releases, drag to /Applications, install macFUSE on first run |
| Windows | LUKSboxSetup.exe from Releases (bundles WinFsp); IT admins can use the bare .msi and install WinFsp separately |
| From source | cargo build --release -p luksbox-cli -p luksbox-gui after the deps in BUILDING.md |
The .deb and .rpm packages now Recommend tpm-udev + tpm2-tools
(Debian / Ubuntu) and tpm2-tss + tpm2-tools (Fedora / RHEL /
openSUSE), so installing them via apt / dnf brings the
/dev/tpm* udev rules and the tss system group along for the ride.
After install you still need to add yourself to the group once and
log back in, that is the Debian / Fedora convention for any package
that grants new device access:
sudo usermod -aG tss "$USER"
# log out + log back in, then verify:
id | tr , '\n' | grep tssThe Linux release tarball's dist/install.sh --tpm-setup does the
same thing for users who installed via tarball instead of apt /
dnf and don't have tpm-udev / tpm2-tss already.
LUKSbox is a young codebase. The cryptography rests on standardised primitives and well-audited Rust libraries (RustCrypto, libfido2, tss-esapi), but the integration layer and the on-disk format are ours. We want external eyes on this.
Every parser that touches attacker-controlled bytes has a libFuzzer
harness in fuzz/ and an AFL++ harness in
fuzz-afl/. PR CI runs each libFuzzer target for 5
minutes on the persistent corpus; a dedicated server runs the AFL++
campaigns for hours per release.
cargo install cargo-fuzz
cd fuzz
cargo +nightly fuzz run header_parse -- -max_total_time=300The current target list (header_parse, keyslot_parse,
metadata_parse, hybrid_sidecar_parse, seed_file_parse,
auth_then_process, header_roundtrip, winfsp_path_parse,
webauthn_device_path, vfs_ops) plus per-target invariants is in
FUZZING.md.
The fastest way to push fuzzing further is dropping a real-world input
file into fuzz/corpus/<target_name>/ and opening a
PR. Examples that would help today:
- Real headers from old vault layouts (V1 / V2) for
header_parse - Authenticator-specific cred IDs (Google Titan, SoloKey stateless,
Trezor) for
keyslot_parse - Edge-case Windows paths (UNC, network share, long path with
device-namespace prefix) for
winfsp_path_parse - Truncated / extended
.hybridsidecars forhybrid_sidecar_parse
If a parser doesn't have a harness yet and you can imagine an attacker
shaping its input, please add one. See the harness template in
FUZZING.md.
If you spot a code path where invariants aren't tested but feel like
they should be, file a regular GitHub issue (label
security-regression) with the invariant in plain English. We write
the test and credit the suggestion in the changelog.
scripts/fuzz_server.sh runs an AFL++
campaign indefinitely against any target. If you have spare cycles
and want to find something the libFuzzer 5-minute PR run misses, this
is the lever.
| Category | Channel | Priority |
|---|---|---|
| Suspected vulnerability (key recovery, plaintext disclosure, authentication bypass, FUSE/WinFsp escape, integer / memory unsafety reachable via a crafted vault file) | Email security@penthertz.com (PGP key in SECURITY.md). 72-hour acknowledgement SLA. Do not open a public issue. |
P0, fix + advisory + coordinated disclosure |
| Crash on a malformed input that you can reproduce | GitHub issue with the input file attached and the crashing target name. Use the fuzz-crash label. |
P1, reproducer + regression test in next release |
| Functional bug (CLI/GUI/wizard misbehaviour, mount problem, recovery-flow gap, on-disk format edge case) | GitHub issue with reproduction steps. Use the bug label. |
P2, triaged within a week |
| Documentation issue (wrong claim, missing instruction, broken link, unclear wording) | GitHub issue or PR. Use the docs label. |
P3, fixed in the next docs pass |
| Feature request | GitHub issue. Use the feature label. State your threat model so we can decide whether it fits the project's scope. |
P3, discussed; may end up on the roadmap or declined with reason |
| Audit assignment (you want a scoped mandate to review a specific surface) | Email security@penthertz.com. We hand you a focused scope (e.g. unsafe Rust in the FIDO2 FFI, CLI argument parser, FUSE adapter) plus a write-up template. |
scheduled |
Suspected vulnerabilities take priority over everything else. We respond within 72 hours and credit reporters in the public changelog
- in any advisory we publish.
flowchart LR
Root["luksbox/"]
Root --> Crates["crates/<br/>(Rust workspace)"]
Root --> Fuzz["fuzz/<br/>cargo-fuzz (libFuzzer)"]
Root --> FuzzAfl["fuzz-afl/<br/>cargo-afl (AFL++)"]
Root --> Assets["assets/<br/>repo branding"]
Root --> Dist["dist/<br/>packaging + install.sh"]
Root --> Scripts["scripts/<br/>release, fuzz, audit"]
Root --> Docs["docs/<br/>spec, architecture, side-channels"]
Root --> Top["top-level .md files"]
Crates --> Core["luksbox-core<br/>crypto primitives + on-disk header"]
Crates --> Format["luksbox-format<br/>container I/O, anchor, hybrid sidecar"]
Crates --> Vfs["luksbox-vfs<br/>directory tree atop a Container"]
Crates --> Fido2["luksbox-fido2<br/>libfido2 + webauthn FFI"]
Crates --> Tpm["luksbox-tpm<br/>Linux TPM 2.0 wrap/unwrap"]
Crates --> Pq["luksbox-pq<br/>ML-KEM-768/1024 + .kyber"]
Crates --> Mount["luksbox-mount<br/>FUSE3, FUSE-T, WinFsp"]
Crates --> Cli["luksbox-cli<br/>luksbox binary + wizard TUI"]
Crates --> Gui["luksbox-gui<br/>luksbox-gui egui desktop app"]
Top --> Building["BUILDING.md"]
Top --> Devel["DEVELOPMENT.md"]
Top --> Fuzzing["FUZZING.md"]
Top --> Testing["TESTING.md"]
Top --> Security["SECURITY.md"]
Top --> Trademark["TRADEMARK.md"]
Top --> License["LICENSE / NOTICE"]
The full documentation lives at https://luksbox.penthertz.com/:
| Section | Contents |
|---|---|
| Documentation hub | Install + per-flow walkthroughs (CLI / TUI / GUI) |
| Keyslots | Passphrase, FIDO2, TPM 2.0, hybrid post-quantum |
| Security | Architecture (with diagrams), threat model, cryptography, tests, audit, disclosure |
| Compare | LUKSbox vs LUKS2 / VeraCrypt / age / gocryptfs / Cryptomator / BitLocker / FileVault |
| FAQ | Cloud use, maturity, licensing, hardware support, recovery |
In-repo references for contributors:
SECURITY.md, disclosure policy + threat model summaryBUILDING.md, per-platform build instructionsTESTING.md, test taxonomy + how to run each tierFUZZING.md, fuzz harness setup + target listDEVELOPMENT.md, maintainer dev workflow + release processdocs/CRYPTO_SPEC.md, per-operation cryptographic walkthroughdocs/SECURITY_ARCHITECTURE.md, security architecture map (mirrors the website page)docs/HARDWARE_SIDE_CHANNEL_NOTES.md, published side-channel attacks against FIDO2 silicondocs/TPM_LINUX_PERMISSIONS.md, end-user playbook for/dev/tpmrm0accessdocs/PROJECT_OVERVIEW.md, project overview + comparison vs LUKS2 / VeraCryptdocs/TPM_FUTURE_IMPROVEMENTS.md, TPM roadmap (Windows TBS, PCR sealing)
Source code is licensed under the Apache License, Version 2.0. LUKSbox is OSI-approved open source: read the source, audit the cryptography, build it yourself, modify it, redistribute it, and use it in any product including commercial offerings that compete with LUKSbox. The Apache 2.0 grant includes an explicit patent license from every contributor, which matters for a cryptography project.
What's explicitly NOT granted by the copyright license is the right to use the LUKSbox or Penthertz trademarks in your derived work; see TRADEMARK.md. You can fork the code and ship it; you cannot call your fork "LUKSbox" or imply endorsement by Penthertz.
The NOTICE file contains the attribution that downstream redistributors must propagate (per the license's Notices section).
The DISCLAIMER restates the no-warranty / no-liability clauses (LICENSE sections 7 and 8), the data-loss reality of any encrypted container, and the export-control responsibility, in plain English. Read it once before relying on LUKSbox to protect material information.
Maintained by Sébastien Dudek, Penthertz
(penthertz.com,
@PentHertz,
security@penthertz.com).
See SECURITY.md sec.1 for the responsible-disclosure flow.