Skip to main content

Module xts

Module xts 

Source
Expand description

AES-XTS tweakable block cipher (IEEE 1619, NIST SP 800-38E).

XTS = XEX-based Tweaked codebook with ciphertext Stealing.

XTS is the disk encryption mode of AES. Unlike GCM and CCM, it is not an AEAD: there is no authentication tag, no associated data, and no nonce-uniqueness assumption. Instead it is a length-preserving, deterministic, tweakable cipher designed for storage scenarios where:

  • Each storage unit (typically a 512-byte or 4096-byte sector) has a stable identifier — its sector number — which is used as the tweak.
  • Encrypted sectors are written in place at the same byte position they had in plaintext (length-preserving).
  • The ciphertext for sector n is independent of every other sector, so single-sector reads / writes are possible.

Used by LUKS2 (Linux full-disk encryption), BitLocker (Windows since Vista), FileVault (macOS), VeraCrypt, and the embedded SSD self-encryption layers (Opal SED, eDrive).

§Construction (IEEE 1619 §5.3)

Two AES keys: K = K1 || K2 (so 32 bytes for XTS-AES-128 and 64 bytes for XTS-AES-256). For each 16-byte block j of a sector with sequence number i:

    T = AES_K2(i)             ; encrypt the tweak (once per sector)
    for j in 0..n_blocks:
        C_j = AES_K1(P_j XOR T) XOR T
        T   = T * α  in GF(2^128)    ; α = 0x02

i is the data unit sequence number, encoded as 16 little-endian bytes. The multiplication by α = 0x02 in GF(2^128) reduces by x^128 + x^7 + x^2 + x + 1 (the standard XEX polynomial; 0x87 byte for the high-bit reduction).

When the sector length is not a multiple of 16, the last block uses ciphertext stealing: the last full block and the short tail block are processed jointly so that the output is the same length as the input. See AesXts::encrypt_sector for the details.

§API

use arcana::cipher::xts::AesXts;

let key:    [u8; 32]   = /* K1 || K2, 32 bytes for XTS-AES-128 */;
let tweak:  [u8; 16]   = sector_number_le_padded;
let mut buf            = sector_plaintext.to_vec();

let xts = AesXts::new(&key).unwrap();
xts.encrypt_sector(&tweak, &mut buf);
// ... write `buf` to disk ...
xts.decrypt_sector(&tweak, &mut buf);

§Key reuse warning

XTS is not an AEAD. It does not detect tampering — flipping one ciphertext bit just flips the same bit in plaintext (within a single 16-byte block). Disk encryption tools deal with this at a higher layer (file checksums, file system journals, application-level MACs).

XTS does offer per-sector independence: rewriting sector 100 does not affect sector 101. But within a sector, an attacker who can corrupt ciphertext bytes can corrupt plaintext bytes one-for-one. Don’t use XTS for anything that needs end-to-end integrity.

§Tests

Pinned against the standard IEEE 1619 test vectors (the same ones used by OpenSSL, Crypto++, and BoringSSL).

Structs§

AesXts
AES-XTS state. Holds the two AES key schedules K1 (for the data block encryption) and K2 (for the tweak encryption).