Unlock a LUKS container from its passphrase and read the plaintext — a
from-scratch, pure-Rust LUKS1/LUKS2 decryptor, validated sector-for-sector
against cryptsetup on real containers.
No cryptsetup C dependency, no dm-crypt, no mounting, no root: one library
that parses the on-disk header, derives the master key from a passphrase through
PBKDF2 or Argon2, and decrypts sectors with AES-XTS.
use std::fs::File;
use luks::LuksVolume;
// Auto-detects LUKS1 vs LUKS2 from the header.
let mut vol = LuksVolume::unlock_with_passphrase(File::open("container.luks")?, b"luks-TEST")?;
let mut first = [0u8; 512];
vol.read_at(0, &mut first)?; // decrypted payload sector 0
# Ok::<(), Box<dyn std::error::Error>>(())This build parses LUKS1 partition headers and LUKS2 binary-header + JSON
metadata, and unlocks both from a passphrase over the aes-xts-plain64 cipher
(AES-128/256-XTS) — the cryptsetup default. LUKS1 keyslots derive with
PBKDF2; LUKS2 keyslots derive with PBKDF2 or Argon2i/Argon2id. Both format
versions are validated against a cryptsetup 2.7.0 oracle:
| Version | Cipher | KDF | Oracle (tier) |
|---|---|---|---|
| LUKS1 | aes-xts-plain64 (AES-256-XTS) |
PBKDF2-sha256 | self-minted luks1.img vs cryptsetup (Tier-2) |
| LUKS2 | aes-xts-plain64, 4096-B sectors |
Argon2id | self-minted luks2.img vs cryptsetup (Tier-2) |
An unsupported cipher/mode/hash is recognized and refused with a named error
(the offending value verbatim) — never decrypted by construction. See
docs/RESEARCH.md.
Following the fleet reader/analyzer standard:
| Crate | Role | Emits |
|---|---|---|
luks-core |
reader / decryptor (pbkdf2 · argon2 · aes · xts-mode · hmac · sha2) |
plaintext Read + Seek view + typed header metadata |
luks-forensic |
anomaly analyzer over the header | severity-graded findings |
| Code | Severity | Meaning |
|---|---|---|
LUKS-WEAK-CIPHER-MODE |
Low | cipher mode is cbc/ecb (weaker than xts-plain64) |
LUKS-WEAK-KDF-HASH |
Low | the KDF/AF hash is sha1 |
LUKS-LOW-KDF-ITERATIONS |
Medium | an active keyslot has < 1000 PBKDF2 iterations (brute-force risk) |
LUKS-KEYSLOT-INVENTORY |
Info | count of active keyslots (of 8) |
Findings are observations, never verdicts — the examiner draws conclusions.
- Every cryptographic primitive is an audited RustCrypto crate (
pbkdf2,argon2,aes,xts-mode,hmac,sha1,sha2) — nothing hand-rolled. The only bespoke routine is the LUKS anti-forensic merge (the TKS1 splitter), validated only against the independentcryptsetuporacle on real containers, never a self-authored round-trip. - Panic-free, bounds-checked parsing of untrusted containers;
unwrap/expectdenied in production code (#![forbid(unsafe_code)]); the LUKS1/LUKS2 header parsers, the AF-merge, and the full unlock pipeline are fuzzed. - Tier-2 validated: decrypted sectors match
cryptsetupbyte-for-byte across LUKS1 and LUKS2 — seedocs/validation.md.
Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd