# aes-elk
[](#license)

Generic implementation of the ELK (Encrypted LFSR Keystream) mode of operation for block ciphers defined in §4.4 [SP 800-197](https://csrc.nist.gov/files/pubs/sp/800/197/iprd/docs/3_samvadini.pdf).
Mode functionality is accessed using traits from the re-exported [`cipher`][cipher-doc] 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:
```rust
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](https://github.com/model-checking/kani).
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 to provide robust authenticated encryption.
## License
Licensed under either of:
* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
* [MIT license](http://opensource.org/licenses/MIT)
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.
[cipher-doc]: https://docs.rs/cipher/