filevault-core 0.1.0

Reader/decryptor for Apple CoreStorage / FileVault 2 (FVDE) encrypted volumes — AES-XTS, PBKDF2, RFC 3394 key unwrap
Documentation

filevault-forensic

Crates.io (core) Crates.io (forensic) Docs.rs Rust 1.81+ License: Apache-2.0 Sponsor

CI Coverage unsafe forbidden Security audit

Decrypt Apple CoreStorage / FileVault 2 volumes in pure Rust — password to plaintext HFS+, no libfvde, no C, one static dependency-light crate.

Point it at an encrypted CoreStorage physical volume and a password; get a Read + Seek view of the decrypted logical volume plus a severity-graded forensic audit of its protectors and encryption state.

use std::fs::File;
use filevault::FileVaultVolume;

let img = File::open("corestorage.raw")?;
let mut vol = FileVaultVolume::unlock_with_password(img, "s3cret")?;

let mut boot = [0u8; 512];
vol.read_at(1024, &mut boot)?;      // decrypted HFS+ volume header ("H+")
# Ok::<(), filevault::FileVaultError>(())

Validated end-to-end against pyfvde (libyal libfvde) on a real encrypted volume: the decrypted sectors are byte-identical (see validation).

Two crates

crate role
filevault-core (use filevault) the reader/decryptor — parse the CoreStorage volume header + metadata, derive the volume key (PBKDF2-SHA256 → RFC 3394 key-unwrap), AES-XTS-decrypt logical-volume sectors
filevault-forensic the analyzer — graded [forensicnomicon::report::Finding]s over the parsed metadata, no password required

Audit without the password

let findings = filevault_forensic::audit_path(std::path::Path::new("corestorage.raw"))?;
for f in &findings {
    println!("{}: {}", f.code, f.note);
}
# Ok::<(), filevault::FileVaultError>(())
code severity observation
FVDE-PROTECTOR-INVENTORY Info which protectors are present (password / recovery / institutional-key crypto users)
FVDE-ENCRYPTION-STATE Info conversion status — encrypted (Complete) / Converting / Pending
FVDE-WEAK-KDF-ITERATIONS Medium PBKDF2 iteration count below a defensible floor (with the observed count)

Findings are observations, never verdicts — they state what the metadata shows, not a conclusion.

Crypto

RustCrypto only — never a hand-rolled primitive: pbkdf2 + hmac + sha2 (KEK derivation), aes-kw (RFC 3394 key unwrap), aes + xts-mode (AES-XTS-128 sector decryption).

Trust, but verify

Panic-free by construction (unsafe forbidden; unwrap/expect/unchecked indexing denied in non-test code; every offset and length from the image is bounds-checked before use), fuzzed (cargo fuzz metadata target, must-not-panic), and validated against an independent oracle on real data — not fixtures we authored. See docs/validation.md.

Scope

CoreStorage / FileVault 2 (macOS 10.7 Lion – 10.15 Catalina), AES-XTS-128, password protector. APFS-native encryption (10.13+) is a separate format and is deferred — see docs/DEFERRED.md.

Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd