EaxModeTransform Class
Definition
- Namespace
- Bodu.Security.Cryptography
- Assembly
- Bodu.Security.Cryptography.dll
- Package
- Bodu.Security.Cryptography 1.2.0
- Source
- EaxModeTransform.cs
Applies EAX mode to an underlying IBlockCipher, providing two-pass authenticated encryption with associated data (AEAD) per Bellare, Rogaway and Wagner (FSE 2004).
public sealed class EaxModeTransform : IAeadBlockCipherModeTransform, IAeadTransform, IDisposable
- Inheritance
-
EaxModeTransform
- Implements
- Inherited Members
- Extension Methods
Examples
using System.Security.Cryptography;
using Bodu.Security.Cryptography;
using Bodu.Security.Cryptography.Extensions;
using IBlockCipher cipher = new AesBlockCipher(key);
byte[] nonce = RandomNumberGenerator.GetBytes(cipher.BlockSize / 8); // unique per message
using IAeadBlockCipherModeTransform eax = new EaxModeTransform(cipher, nonce);
byte[] sealed_ = eax.Encrypt(plaintext, associatedData: header);
using IAeadBlockCipherModeTransform dec = new EaxModeTransform(cipher, nonce);
byte[] recovered = dec.Decrypt(sealed_, associatedData: header);
Remarks
EAX is the CTR + OMAC(N ‖ A ‖ C) instantiation of the generic AEAD shape above. Three independent OMAC
invocations are performed with a single-byte tweak t ∈ {0, 1, 2} selecting the input kind:
N' = OMAC_K^0(nonce)- authenticates the nonce and seeds the CTR counter.H' = OMAC_K^1(associatedData)- authenticates the AAD.C' = OMAC_K^2(ciphertext)- authenticates the ciphertext.
The authentication tag is T = N' ⊕ H' ⊕ C', and the keystream is generated by encrypting successive
big-endian increments of N' with the underlying block cipher.
OMAC_K^t(M) is defined as CMAC_K([t]_n ‖ M), where [t]_n is the integer t encoded as a
full BlockSize-byte big-endian block. All three invocations therefore share the same CMAC subkeys K₁ =
dbl(E(0ⁿ)) and K₂ = dbl(K₁), derived from the cipher once per instance.
The tag size is fixed at 16 bytes (the full OMAC output). The IV is the raw nonce: the class computes N'
internally. Ciphertext is output as C ‖ T (ciphertext then tag), consistent with the
IAeadBlockCipherModeTransform convention.
When to use EAX. Pick EAX when an unencumbered, two-pass AEAD with a flexible nonce length (the
OMAC-derived N' means EAX accepts nonces up to the cipher block size) is wanted - some embedded protocols and
historical industry standards require it. EAX is roughly half the throughput of GcmModeTransform on
commodity hardware but does not depend on Galois-field arithmetic and has no patent concerns. For new
general-purpose AEAD prefer GCM; for nonce-misuse resistance prefer GcmSivModeTransform or
SivModeTransform; for single-pass AEAD without GCM's catastrophic-on-reuse profile prefer
OcbModeTransform.
Nonce uniqueness is required. EAX is not nonce-misuse resistant. Two messages encrypted under the
same (key, nonce) share the same N' seed, so they share the same CTR keystream and an attacker can
recover P1 XOR P2; the per-message OMAC tag inputs also overlap, weakening authentication. Callers must
guarantee that every (key, nonce) pair is used at most once - either via a deterministic per-message counter
or a fresh random nonce drawn from a CSPRNG. If nonce uniqueness cannot be guaranteed, prefer
GcmSivModeTransform or SivModeTransform.
Constructors
EaxModeTransform(IBlockCipher, byte[])
Initializes a new instance of the EaxModeTransform class.
public EaxModeTransform(IBlockCipher cipher, byte[] iv)
Parameters
cipherIBlockCipherThe block cipher used for both OMAC and the CTR keystream.
ivbyte[]The nonce
N. Must equal the cipher block size. A defensive copy is taken; the caller's array is not modified.
Exceptions
- ArgumentNullException
cipherorivis null.- ArgumentException
ivlength does not equal the cipher block size.
Properties
TagSize
Gets the authentication-tag size, in bits.
public int TagSize { get; }
Property Value
- int
The authentication-tag size, in bits.
Methods
Decrypt(ReadOnlySpan<byte>, Span<byte>)
Decrypts ciphertextWithTag and verifies the authentication tag.
public int Decrypt(ReadOnlySpan<byte> ciphertextWithTag, Span<byte> output)
Parameters
ciphertextWithTagReadOnlySpan<byte>The ciphertext followed immediately by the TagSize / 8 byte authentication tag. Must be at least TagSize / 8 bytes long.
outputSpan<byte>Receives the decrypted plaintext. Must be at least
ciphertextWithTag.Length - (TagSize / 8)bytes long.
Returns
- int
Bytes written:
ciphertextWithTag.Length - (TagSize / 8).
Remarks
Authentication failure contract. All implementations honour the same observable guarantee on tag mismatch: CryptographicException is thrown and no plaintext is released to the caller. Implementations achieve this in one of two ways:
-
Verify-before-release. The tag is compared in constant time before any plaintext byte is written to
output. Used by GCM, CCM, EAX, and OCB. -
Write-then-clear. The candidate plaintext is streamed into
outputfirst because the algorithm's structure requires the transform to complete before the tag can be computed. The tag is then compared in constant time; on mismatchoutputis zeroed via ZeroMemory(Span<byte>) before the exception is thrown. Used by Ascon-AEAD-128 and GCM-SIV.
In both cases the API is strictly one-shot: a failed decryption invalidates the instance, and subsequent calls throw InvalidOperationException. Construct a fresh instance per message.
Exceptions
- CryptographicException
The authentication tag did not match.
- ArgumentException
ciphertextWithTagis shorter than TagSize / 8 bytes, oroutputis too small.- InvalidOperationException
The instance has already encrypted or decrypted a message, including after a previous tag-mismatch failure. AEAD transforms are single-use per message - construct a fresh instance.
Dispose()
Releases the resources used by this instance and clears retained nonce and associated-data state from memory.
public void Dispose()
Remarks
The supplied IBlockCipher is not disposed by this type. Ownership remains with the caller.
Encrypt(ReadOnlySpan<byte>, Span<byte>)
Encrypts plaintext and appends the authentication tag to output.
public int Encrypt(ReadOnlySpan<byte> plaintext, Span<byte> output)
Parameters
plaintextReadOnlySpan<byte>The data to encrypt.
outputSpan<byte>Receives the ciphertext followed immediately by the TagSize / 8 byte tag. Must be at least
plaintext.Length + (TagSize / 8)bytes long.
Returns
- int
Total bytes written:
plaintext.Length + (TagSize / 8).
Exceptions
- ArgumentException
outputis too small.- InvalidOperationException
The instance has already encrypted or decrypted a message. AEAD transforms are single-use per message - construct a fresh instance.
ProcessAssociatedData(ReadOnlySpan<byte>)
Processes associated data (AAD) that will be authenticated but not encrypted. Must be called before Encrypt(ReadOnlySpan<byte>, Span<byte>) or Decrypt(ReadOnlySpan<byte>, Span<byte>).
public void ProcessAssociatedData(ReadOnlySpan<byte> associatedData)
Parameters
associatedDataReadOnlySpan<byte>The bytes to authenticate. May be empty to indicate no associated data.
Exceptions
- InvalidOperationException
Associated data has already been processed on this instance, or the instance has already completed an Encrypt(ReadOnlySpan<byte>, Span<byte>) or Decrypt(ReadOnlySpan<byte>, Span<byte>) operation.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |