https://github.com/securityronin/veracrypt-forensic
VeraCrypt/TrueCrypt forensic library — brute the header PRF+cipher from a password, recover the master key, and decrypt the volume (AES/Serpent/Twofish, 5 PRFs, hidden volumes). Panic-free, no unsafe.
https://github.com/securityronin/veracrypt-forensic
cryptography dfir digital-forensics encryption forensics incident-response rust truecrypt veracrypt xts
Last synced: 1 day ago
JSON representation
VeraCrypt/TrueCrypt forensic library — brute the header PRF+cipher from a password, recover the master key, and decrypt the volume (AES/Serpent/Twofish, 5 PRFs, hidden volumes). Panic-free, no unsafe.
- Host: GitHub
- URL: https://github.com/securityronin/veracrypt-forensic
- Owner: SecurityRonin
- License: apache-2.0
- Created: 2026-07-10T16:04:16.000Z (8 days ago)
- Default Branch: main
- Last Pushed: 2026-07-10T19:07:56.000Z (7 days ago)
- Last Synced: 2026-07-11T18:16:29.315Z (6 days ago)
- Topics: cryptography, dfir, digital-forensics, encryption, forensics, incident-response, rust, truecrypt, veracrypt, xts
- Language: Rust
- Size: 70.3 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# veracrypt-forensic
[](https://crates.io/crates/veracrypt-core)
[](https://crates.io/crates/veracrypt-forensic)
[](https://docs.rs/veracrypt-core)
[](https://www.rust-lang.org)
[](LICENSE)
[](https://github.com/sponsors/h4x0r)
[](https://github.com/SecurityRonin/veracrypt-forensic/actions/workflows/ci.yml)
[](docs/validation.md)
[](https://github.com/rust-secure-code/safety-dance)
[](https://rustsec.org)
**Unlock a VeraCrypt (or legacy TrueCrypt) volume from its password and read the
plaintext — a from-scratch, pure-Rust decryptor validated byte-for-byte against
both the real VeraCrypt binary and `cryptsetup` on a real volume.**
No `veracrypt` binary, no `cryptsetup`, no FUSE, no mounting: one library that
brutes the header PRF and cipher from a password, recovers the master key, and
decrypts the data area as AES-256 or Twofish-256 XTS.
```rust,ignore
use std::fs::File;
use veracrypt::VeraVolume;
// Unlock a VeraCrypt volume with its password (no PIM).
let mut vol = VeraVolume::unlock_with_password(File::open("container.vc")?, b"passphrase")?;
let mut first = [0u8; 512];
vol.read_at(0, &mut first)?; // first decrypted sector of the data area
println!("{:?} / {}", vol.info().flavor, vol.info().cipher.name());
# Ok::<(), Box>(())
```
## Scope
This build brutes the header across **all five VeraCrypt PRFs** and decrypts
**both single ciphers**, with support for a PIM and for normal *and* hidden
volumes:
| Axis | Supported |
|---|---|
| PRF (header key derivation) | SHA-512 · SHA-256 · Whirlpool · Streebog-512 · RIPEMD-160 |
| Cipher (data area) | AES-256-XTS · Serpent-256-XTS · Twofish-256-XTS · all VeraCrypt cascades |
| PIM | yes — `unlock_with_pim` / `unlock_hidden_with_pim` |
| Volume layout | normal (header @ 0) · hidden (header @ 64 KiB) |
| Flavor | VeraCrypt (`VERA`) · legacy TrueCrypt (`TRUE`) |
`VeraVolume::unlock_with_password(reader, password)` tries every PRF × cipher
until one decrypts the header to a valid `VERA`/`TRUE` signature with both CRC-32s
matching, then exposes a plaintext `Read + Seek` view (`read_at`).
`unlock_hidden_with_password` reads the hidden header at 64 KiB — used to access,
or to prove the presence of, a deniable hidden volume.
All three single ciphers — **AES-256**, **Serpent-256**, **Twofish-256** — are
supported, each via an audited RustCrypto crate (Serpent through
`serpent::Serpent::new_from_slice`, which takes the full 256-bit key), and so are
**all VeraCrypt cipher cascades** (AES-Twofish, AES-Twofish-Serpent, Serpent-AES,
Serpent-Twofish-AES, Twofish-Serpent) — stacked XTS layers keyed exactly as
cryptsetup's `TCRYPT_decrypt_hdr`. `VolumeInfo::cipher_display()` names the chain
(e.g. `aes-twofish-serpent`). See [`docs/RESEARCH.md`](docs/RESEARCH.md).
## The two-crate split
Following the fleet reader/analyzer standard:
| Crate | Role | Emits |
|---|---|---|
| **`veracrypt-core`** | reader / decryptor (`aes` · `twofish` · `xts-mode` · `pbkdf2` · `sha2` · `whirlpool` · `streebog` · `ripemd`) | plaintext `Read + Seek` view + typed `VolumeInfo` |
| **`veracrypt-forensic`** | anomaly analyzer over the recovered facts | graded observations |
### Analyzer findings
| Code | Severity | Meaning |
|---|---|---|
| `VC-LEGACY-TRUECRYPT` | Low | the volume is a legacy TrueCrypt (not VeraCrypt) container |
| `VC-HIDDEN-VOLUME-DECLARED` | Medium | the outer header declares a hidden volume (deniable-encryption indicator) |
| `VC-CIPHER-INVENTORY` | Info | the recovered PRF, cipher, and data-area offset |
Findings are **observations, never verdicts** — the examiner draws conclusions.
## Trust but verify
- **Every primitive is an audited RustCrypto crate** — `aes`, `twofish`,
`xts-mode`, `pbkdf2`, `hmac`, `sha2`, `whirlpool`, `streebog`, `ripemd`,
`crc32fast`. No cryptography is hand-rolled.
- **Unimpeachable Tier-1**: on a real VeraCrypt volume with a published password,
the decrypted sectors of **three independent implementations agree
byte-for-byte** — VeraCrypt 1.26.20 (Idrix, the format's own reference),
`cryptsetup` 2.7.0 (an independent reimplementation), and this crate. See
[`docs/validation.md`](docs/validation.md).
- **Panic-free, bounds-checked** parsing of untrusted volumes;
`unwrap`/`expect` denied in production code (`#![forbid(unsafe_code)]`); the
header parser is fuzzed.
[Privacy Policy](https://securityronin.github.io/veracrypt-forensic/privacy/) · [Terms of Service](https://securityronin.github.io/veracrypt-forensic/terms/) · © 2026 Security Ronin Ltd