# eme2
[![Docs][docs-image]][docs-link]
![Apache2/MIT licensed][license-image]
![Rust Version][rustc-image]
Generic implementation of the [EME2][EME2-IEEE] (ECB-Mask-ECB) wide-block cipher mode of operation.
Mode functionality is accessed using traits from the re-exported [`cipher`][cipher-doc] crate.
## ⚠️ 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 EME2 in combination with a strong MAC to provide robust authenticated encryption.
## Standards and Specifications
This crate implements **IEEE Std 1619.2 EME2-AES**, which is the original academic **EME\***
specification instantiated with a 128-bit block cipher and a concrete key schedule (one master
key split into Key1/Key2/Key3) in place of EME*'s independent masks L and R. The two specs
describe the same algorithm and share a single implementation here (`hash_ad`, `encrypt_with_ad`,
`decrypt_with_ad`, etc. — there are no separate `_eme2`/`_emestar`-suffixed methods). Note that
the two documents disagree on byte order for the underlying GF(2^128) doubling (IEEE's
`Mult-by-alpha` is little-endian; EME*'s `2L` is defined msb-first), so EME* and EME2-AES
ciphertexts are not byte-for-byte interchangeable even though the algorithm is identical. This
crate follows the IEEE convention throughout.
### Reference Documents
* **EME2 (Standard):** [IEEE Std 1619.2-2010: IEEE Standard for Wide-Block Encryption for Shared Storage Media][EME2-IEEE] (located at `docs/eme2-ieee.pdf`, which is an unpublished draft — verify against the published standard before relying on it for interop)
* **EME\* (Academic Paper):** ["EME*: extending EME to handle arbitrary-length messages with associated data" (Shai Halevi, 2004)][EME-Paper] (located at `docs/2004-125.pdf`)
## Cipher Compatibility
**By default, this crate ONLY supports block ciphers with a 16-byte (128-bit) block size.**
EME2 mathematically requires a 128-bit polynomial for its internal tweak processing. Ciphers with larger block sizes (such as `Threefish256`, `Threefish512`, or `Threefish1024`) are structurally incompatible with the default `Eme2<C>` and are safely rejected at compile time by the crate's generic trait bounds (`BlockSizeUser<BlockSize = U16>`).
The implementation is explictly tested against standard 128-bit block ciphers to guarantee compatibility across the ecosystem:
* `aes-128`
* `aes-256`
* `serpent`
### `extended` feature: 256/512/1024-bit blocks
The `extended` feature adds `eme2::extended::Eme2<C>`, a generalized version of the same
algorithm that accepts any block cipher with a matching `EmePoly` implementation — currently
128-, 256-, 512-, and 1024-bit blocks (e.g. `Threefish256`/`512`/`1024`). For 128-bit ciphers it
produces byte-identical output to the base `Eme2<C>` (verified by test).
> [!WARNING]
> **This goes beyond IEEE Std 1619.2, which only defines EME2-AES for 128-bit blocks.** The
> 256/512/1024-bit GF(2^n) moduli are not from any published standard. Each one has been
> verified **irreducible** over GF(2) (so the field arithmetic itself is sound), but EME*'s
> security proof also requires the doubling element to be **primitive** — order exactly
> `2^n − 1` — which is what the IEEE 128-bit polynomial was specifically chosen for. Primitivity
> for the larger moduli is **not independently verified**: it requires the complete prime
> factorization of `2^n − 1`, which for n = 1024 is not public knowledge. Treat block sizes above
> 128 bits as experimental until this is established or the constants are replaced with a
> citable reference. See the `eme2::extended` module docs for details.
## Migrating from Stream Ciphers (e.g., CTR Mode)
Because `eme2` strictly implements RustCrypto's `KeyIvInit` traits, instantiating the cipher is a 1:1 drop-in replacement for stream ciphers like `ctr`:
```rust,ignore
// CTR Mode Initialization
let cipher = Ctr128BE::<Aes128>::new(&key.into(), &nonce.into());
// EME2 Mode Initialization
let cipher = Eme2::<Aes128>::new(&key.into(), &tweak.into());
```
However, **execution differs**. Stream ciphers use the `StreamCipher` trait because their encryption and decryption processes are mathematically identical (XORing a keystream). EME2 is a **Wide-Block Cipher**, meaning its encryption and decryption passes are mathematically asymmetric. Therefore, it does not implement `StreamCipher` and instead exposes explicit `.encrypt()` and `.decrypt()` methods:
```rust,ignore
// Stream Ciphers (CTR)
cipher.apply_keystream(&mut data); // Handles both encryption and decryption
// Wide-Block Ciphers (EME2)
cipher.encrypt(&mut data).expect("encryption succeeded");
cipher.decrypt(&mut data).expect("decryption succeeded");
```
## Usage Examples
### 1. Encryption with a tweak
```rust
use aes::Aes256;
use cipher::KeyIvInit;
use eme2::Eme2;
type Aes256Eme2 = Eme2<Aes256>;
let key = [0x42; 64]; let tweak = [0x11; 16];
let mut data = vec![0u8; 64];
let cipher = Aes256Eme2::new(&key.into(), &tweak.into());
cipher.encrypt(&mut data).expect("encryption succeeded");
cipher.decrypt(&mut data).expect("decryption succeeded");
```
### 2. Encryption with associated data
```rust
use aes::Aes256;
use cipher::KeyInit;
use eme2::Eme2;
type Aes256Eme2 = Eme2<Aes256>;
let key = [0x42; 64];
let mut data = vec![0u8; 64];
let cipher = <Aes256Eme2 as cipher::KeyInit>::new(&key.into());
let associated_data = b"associated data";
cipher.encrypt_with_ad(associated_data, &mut data).expect("encryption succeeded");
cipher.decrypt_with_ad(associated_data, &mut data).expect("decryption succeeded");
```
## 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.
[//]: # (badges)
[docs-image]: https://docs.rs/eme2/badge.svg
[docs-link]: https://docs.rs/eme2/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.87+-blue.svg
[//]: # (general links)
[EME2-IEEE]: https://ieeexplore.ieee.org/servlet/opac?punumber=11277321
[EME-Paper]: https://eprint.iacr.org/2004/125.pdf
[cipher-doc]: https://docs.rs/cipher/