aes-elk 0.1.0

ELK (Encrypted LFSR Keystream) mode of operation for block ciphers
Documentation

aes-elk

Apache2/MIT licensed Rust Version

Generic implementation of the ELK (Encrypted LFSR Keystream) mode of operation for block ciphers defined in §4.4 SP 800-197.

Mode functionality is accessed using traits from the re-exported cipher crate.

About ELK

ELK is a keystream-based stream cipher mode of operation that generates a keystream by encrypting the state of a Galois-Field Linear Feedback Shift Register (LFSR) with a block cipher.

Cipher & Block Size Compatibility

Unlike other modes that are restricted to a single block size, this implementation of ELK supports multiple block sizes:

  • 16-byte (128-bit) block ciphers (e.g., Aes128, Aes256, Serpent) using the self-computed $GF(2{128})$ polynomial: $$X{128} + X{113} + X{97} + X{89} + X{71} + X{59} + X{37} + X^{23} + 1$$
  • 32-byte (256-bit) block ciphers (e.g., Threefish256) using the NIST Samvadini-compliant polynomial: $$X{256} + X{229} + X{193} + X{167} + X{139} + X{109} + X{71} + X{37} + 1$$
  • 64-byte (512-bit) block ciphers (e.g., Threefish512) using the NIST Samvadini-compliant polynomial: $$X{512} + X{461} + X{397} + X{331} + X{281} + X{211} + X{139} + X{71} + 1$$

Ciphers with unsupported block sizes (such as Threefish1024 with 128-byte block size) are safely rejected at compile time by the crate's generic trait bounds (C::BlockSize: ElkPolynomial).

Usage

Because ELK implements RustCrypto's KeyIvInit traits, instantiating the cipher is straightforward:

use aes::cipher::KeyIvInit;
use aes_elk::Elk;

type Aes128Elk = Elk<aes::Aes128>;

let key = [0x42; 16];
let iv = [0x24; 16];
let plaintext = *b"hello world! this is my plaintext! it can be any length.";

// Encrypt in-place
let mut buf = plaintext.to_vec();
let mut encryptor = Aes128Elk::new(&key.into(), &iv.into());
let mut decryptor = encryptor.clone(); // Clone state or re-initialize for decryption

encryptor.apply_keystream(&mut buf).unwrap();
assert_ne!(buf[..], plaintext[..]);

// Decrypt in-place
decryptor.apply_keystream(&mut buf).unwrap();
assert_eq!(buf[..], plaintext[..]);

Formal Verification

The core ELK keystream application logic for 128-bit block ciphers is formally verified using the Kani Rust Verifier.

This verification mathematically proves the absence of undefined behavior and ensures panic-free execution across all possible initialization vectors and payloads up to the block boundary. Specifically, the Kani harness guarantees that the 128-bit ELK mode wrapper is completely free from:

  • Memory-safety violations (e.g., out-of-bounds reads/writes)
  • Arithmetic errors (e.g., integer overflows/underflows)
  • Unhandled runtime panics

⚠️ Security Warning: Hazmat!

This crate does not ensure ciphertexts are authentic! Thus ciphertext integrity is not verified, which can lead to serious vulnerabilities. It is highly recommended to use ELK in combination with a strong MAC (like BLAKE3) to provide robust authenticated encryption.

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.