elephant-diffuser 0.1.0

The BitLocker Elephant Diffuser (Diffuser A + Diffuser B + sector-key XOR) — the pure format primitive with no ecosystem crate, validated in-situ against libbde
Documentation
  • Coverage
  • 100%
    3 out of 3 items documented1 out of 3 items with examples
  • Size
  • Source code size: 37.16 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 269.96 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • SecurityRonin/elephant-diffuser
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • h4x0r

elephant-diffuser

Crates.io Docs.rs Rust 1.81+ License: Apache-2.0 Sponsor

CI Coverage unsafe forbidden Security advisories

The BitLocker Elephant Diffuser as a standalone, dependency-free Rust primitive — the one part of BitLocker's sector cipher no RustCrypto crate provides, validated byte-for-byte against libbde on a real volume.

BitLocker's CBC-plus-diffuser methods (0x8000, 0x8001) wrap AES-CBC in a keyed byte-mixing layer — the Elephant Diffuser. AES, CBC, CCM and SHA-256 all have audited crates; the diffuser does not. This crate is that missing piece, extracted from bitlocker-core so every consumer shares one reviewed implementation.

use elephant_diffuser::{decrypt, encrypt};

let mut sector = vec![0u8; 512];
let sector_key = [0u8; 32]; // caller-derived (BitLocker: AES-ECB over the offset with the TWEAK key)

// Decrypt: Diffuser B, then Diffuser A, then XOR the sector key.
decrypt(&mut sector, &sector_key);

// Encrypt is the exact inverse: XOR, then Diffuser A, then Diffuser B.
encrypt(&mut sector, &sector_key);

What it is (and isn't)

The Elephant Diffuser is a keyed, invertible diffusion transform, not a cipher: it holds no secret and provides no confidentiality. Applied to a sector after AES-CBC decryption (and before AES-CBC encryption), it spreads each bit across the whole sector so a one-bit change cascades. Confidentiality comes from AES; this is the diffusion layer around it.

  • decrypt(sector, sector_key) — Diffuser B → Diffuser A → XOR the 32-byte sector key.
  • encrypt(sector, sector_key) — the exact inverse: XOR → Diffuser A → Diffuser B.

Both operate in place on a sector of any length (BitLocker uses 512-byte sectors).

Why hand-written — the one documented exception

The fleet rule is never hand-roll crypto — use an audited crate. The Elephant Diffuser is the exception, because no crate exists: it is a format-specific transform defined only by Microsoft's implementation and the community reverse engineering in dislocker (diffuser.c) and libbde. The rotation constants (Ra = {9,0,13,0}, Rb = {0,10,0,25}), the five- and three-cycle counts, and the B-then-A-then-XOR order follow that reference. Isolating it in one crate — reviewed, fuzzed, and validated against real data — is how the exception stays disciplined.

Trust but verify

  • #![forbid(unsafe_code)], panic-free, zero dependencies. No unwrap/expect in production; every index is computed with underflow-free modular arithmetic, so the transform never panics on any input length. A cargo-fuzz target drives decrypt/encrypt over arbitrary bytes with the "must not panic" invariant.
  • Tier-1 validated, in situ. The authoritative proof is bitlocker-core's oracle: this code decrypts the real dfvfs bdetogo.raw volume byte-for-byte against pybde. It is correctness-validated against libbde on real data, not independently security-audited — a keyed diffusion transform, not a secret-branching cipher. See docs/validation.md.

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