Table of Contents

Cipher Algorithms Reference

This page provides detailed documentation for all cipher algorithms implemented in the CryptoHives.Foundation.Security.Cryptography package.

Namespace

using CryptoHives.Foundation.Security.Cryptography.Cipher;

AEAD Ciphers (Authenticated Encryption)

AEAD (Authenticated Encryption with Associated Data) ciphers provide both confidentiality and authenticity in a single operation.

AES-GCM (Galois/Counter Mode)

public sealed class AesGcm128 : AesGcm
public sealed class AesGcm192 : AesGcm
public sealed class AesGcm256 : AesGcm

Properties:

  • Key Sizes: 128, 192, or 256 bits
  • Nonce Size: 12 bytes (recommended), variable supported
  • Tag Size: 16 bytes (default), configurable
  • Performance: Very fast with AES-NI + PCLMULQDQ/VPCLMULQDQ hardware support; 8-block stitched pipeline; ~2× faster than OS at small sizes

Security:

  • ✅ Widely used in TLS 1.3, IPsec, QUIC
  • ✅ NIST approved (SP 800-38D)
  • ⚠️ Nonce reuse catastrophic - each (key, nonce) pair must be unique

Usage:

// Create instance with key
byte[] key = new byte[32]; // 256-bit key
using var aesGcm = AesGcm256.Create(key);

// Encrypt with authentication
byte[] nonce = new byte[12];
byte[] plaintext = Encoding.UTF8.GetBytes("Hello, World!");
byte[] aad = Encoding.UTF8.GetBytes("header");

byte[] ciphertext = new byte[plaintext.Length];
byte[] tag = new byte[16];
aesGcm.Encrypt(nonce, plaintext, ciphertext, tag, aad);

// Decrypt and verify
byte[] decrypted = new byte[plaintext.Length];
bool success = aesGcm.Decrypt(nonce, ciphertext, tag, decrypted, aad);

See Also:

AES-CCM (Counter with CBC-MAC)

public sealed class AesCcm128 : AesCcm
public sealed class AesCcm192 : AesCcm
public sealed class AesCcm256 : AesCcm

Properties:

  • Key Sizes: 128, 192, or 256 bits
  • Nonce Size: 7-13 bytes (12 bytes recommended)
  • Tag Size: 4-16 bytes (must be even)
  • Performance: Slower than GCM, 2.8–3× faster with AES-NI, more compact for small messages

Security:

  • ✅ NIST approved (SP 800-38C)
  • ✅ Widely used in IoT, Bluetooth LE, ZigBee, Thread
  • ✅ RFC 3610 compliant
  • ⚠️ Nonce reuse catastrophic - each (key, nonce) pair must be unique

Usage:

// Create instance with key
byte[] key = new byte[16]; // 128-bit key
using var aesCcm = AesCcm128.Create(key);

// Encrypt with authentication
byte[] nonce = new byte[12]; // 96-bit nonce
byte[] plaintext = Encoding.UTF8.GetBytes("Sensor data");
byte[] aad = Encoding.UTF8.GetBytes("device-id");

byte[] ciphertext = new byte[plaintext.Length];
byte[] tag = new byte[8]; // 64-bit tag
aesCcm.Encrypt(nonce, plaintext, ciphertext, tag, aad);

// Decrypt and verify
byte[] decrypted = new byte[plaintext.Length];
bool success = aesCcm.Decrypt(nonce, ciphertext, tag, decrypted, aad);

See Also:

  • AES-CCM Test Vectors (Coming soon)

ChaCha20-Poly1305

public sealed class ChaCha20Poly1305 : IAeadCipher

Properties:

  • Key Size: 256 bits (32 bytes)
  • Nonce Size: 12 bytes (96 bits)
  • Tag Size: 16 bytes (128 bits)
  • Performance: Fast on all platforms; SSSE3/AVX2 accelerated, no AES-NI dependency

Security:

  • ✅ IETF standard (RFC 8439)
  • ✅ Used in TLS 1.3, WireGuard, SSH
  • ✅ Software-friendly alternative to AES-GCM
  • ⚠️ Nonce reuse catastrophic - each (key, nonce) pair must be unique

Usage:

// Create instance with key
byte[] key = new byte[32]; // 256-bit key
using var chacha = ChaCha20Poly1305.Create(key);

// Encrypt
byte[] nonce = new byte[12];
byte[] plaintext = Encoding.UTF8.GetBytes("Message");
byte[] ciphertext = chacha.Encrypt(nonce, plaintext);

// Decrypt
byte[] decrypted = chacha.Decrypt(nonce, ciphertext);

See Also:

XChaCha20-Poly1305

public sealed class XChaCha20Poly1305 : IAeadCipher

Properties:

  • Key Size: 256 bits (32 bytes)
  • Nonce Size: 24 bytes (192 bits) - larger than ChaCha20
  • Tag Size: 16 bytes (128 bits)
  • Performance: Same as ChaCha20-Poly1305; SSSE3/AVX2 accelerated

Security:

  • ✅ Extended nonce version of ChaCha20-Poly1305
  • ✅ Safer for random nonces (negligible collision probability)
  • ✅ Used in libsodium, age encryption
  • ✅ More forgiving of nonce generation mistakes

Usage:

// Create instance with key
byte[] key = new byte[32];
using var xchacha = XChaCha20Poly1305.Create(key);

// Generate random nonce (safe with 192-bit nonce)
byte[] nonce = new byte[24];
RandomNumberGenerator.Fill(nonce);

// Encrypt
byte[] plaintext = Encoding.UTF8.GetBytes("Secret");
byte[] ciphertext = xchacha.Encrypt(nonce, plaintext);

// Decrypt
byte[] decrypted = xchacha.Decrypt(nonce, ciphertext);

See Also:


Block Ciphers

Block ciphers encrypt fixed-size blocks of data. They require a mode of operation (ECB, CBC, CTR) to encrypt data larger than a single block.

All block ciphers extend SymmetricCipher (which inherits from System.Security.Cryptography.SymmetricAlgorithm) and implement ICipherTransform for span-based streaming transformations.

AES (Advanced Encryption Standard)

public sealed class Aes128 : SymmetricCipher
public sealed class Aes192 : SymmetricCipher
public sealed class Aes256 : SymmetricCipher

Properties:

  • Key Sizes: 128, 192, or 256 bits
  • Block Size: 128 bits (16 bytes)
  • IV Size: 16 bytes (CBC, CTR) or none (ECB)
  • Modes: ECB, CBC, CTR
  • Padding: PKCS#7, None, Zeros, ANSIX923, ISO10126
  • Performance: Hardware accelerated with AES-NI; vectorized CBC decrypt (4/8-block interleaved)

Security:

  • ✅ NIST approved (FIPS 197)
  • ✅ The most widely used symmetric cipher in the world
  • ⚠️ ECB mode is insecure for multi-block data — use CBC or CTR
  • ⚠️ CBC mode requires unpredictable IVs and is vulnerable to padding oracle attacks without authentication

Usage — CTR Mode (Recommended):

using CryptoHives.Foundation.Security.Cryptography.Cipher;

// Create AES-256 in CTR mode
using var aes = Aes256.Create();
aes.Mode = CipherMode.CTR;
aes.Padding = PaddingMode.None; // CTR does not require padding

// Set key and IV
aes.Key = new byte[32]; // 256-bit key
aes.IV = new byte[16]; // 128-bit nonce/counter

// Single-operation
byte[] ciphertext = aes.Encrypt(plaintext);
byte[] decrypted = aes.Decrypt(ciphertext);

Usage — CBC Mode:

using var aes = Aes128.Create();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = new byte[16]; // 128-bit key
aes.GenerateIV(); // Random IV

byte[] ciphertext = aes.Encrypt(plaintext);
byte[] decrypted = aes.Decrypt(ciphertext);

Usage — Streaming (ICipherTransform):

using var aes = Aes256.Create();
aes.Mode = CipherMode.CTR;
aes.Padding = PaddingMode.None;
aes.Key = new byte[32];
aes.IV = new byte[16];

// Create transform for incremental encryption
using var encryptor = aes.CreateEncryptor();

// Process multiple blocks
Span<byte> output = new byte[inputChunk.Length];
int written = encryptor.TransformBlock(inputChunk, output);

// Final block (handles padding for CBC)
written = encryptor.TransformFinalBlock(lastChunk, output);
Warning

ECB mode encrypts each block independently. Identical plaintext blocks produce identical ciphertext, leaking patterns. Use CTR or CBC mode instead. For authenticated encryption, prefer AES-GCM or AES-CCM.


Stream Ciphers

Stream ciphers generate a keystream that is XORed with the plaintext. They do not require padding and can process data of any length.

ChaCha20

public sealed class ChaCha20 : SymmetricCipher

Properties:

  • Key Size: 256 bits (32 bytes)
  • Nonce Size: 12 bytes (96 bits) — IETF variant (RFC 8439)
  • Block Size: 1 byte (stream cipher, processes any length)
  • Counter: 32-bit initial block counter (configurable via InitialCounter)
  • Performance: SSSE3/AVX2 hardware accelerated

Security:

  • ✅ IETF standard (RFC 8439)
  • ✅ Constant-time — no timing side channels
  • ✅ Fast in software without dedicated hardware (unlike AES without AES-NI)
  • ⚠️ No authentication — use ChaCha20-Poly1305 for authenticated encryption
  • ⚠️ Nonce reuse is catastrophic — never reuse a (key, nonce) pair

Usage:

using CryptoHives.Foundation.Security.Cryptography.Cipher;

// Create ChaCha20 stream cipher
using var chacha = ChaCha20.Create();
chacha.Key = new byte[32]; // 256-bit key
chacha.IV = new byte[12]; // 96-bit nonce

// Single-operation encryption (XOR with keystream)
byte[] ciphertext = chacha.Encrypt(plaintext);

// Decryption is the same operation (XOR is symmetric)
byte[] decrypted = chacha.Decrypt(ciphertext);

Usage — Streaming:

using var chacha = ChaCha20.Create();
chacha.Key = key;
chacha.IV = nonce;

using var encryptor = chacha.CreateEncryptor();

// Stream cipher: process any amount of data
Span<byte> output = new byte[chunk.Length];
encryptor.TransformBlock(chunk, output);

// No padding needed for final block
encryptor.TransformFinalBlock(lastChunk, output);

Usage — Custom Initial Counter:

// RFC 8439 §2.4: AEAD construction uses counter = 1 (block 0 for Poly1305 key)
using var chacha = ChaCha20.Create();
chacha.InitialCounter = 1;
chacha.Key = key;
chacha.IV = nonce;
Tip

ChaCha20 is the preferred stream cipher when AES-NI hardware is not available. It is faster than AES in software and has no timing side channels from table lookups. For authenticated encryption, use ChaCha20-Poly1305.


Block/Stream Cipher Comparison

Algorithm Type Key Size Block/IV Modes Hardware Accel Best For
AES-128 Block 128 bits 16B / 16B ECB, CBC, CTR AES-NI General purpose, compliance
AES-192 Block 192 bits 16B / 16B ECB, CBC, CTR AES-NI Higher security margin
AES-256 Block 256 bits 16B / 16B ECB, CBC, CTR AES-NI Maximum AES security
ChaCha20 Stream 256 bits — / 12B Stream SSSE3/AVX2 Software-only, mobile

Cipher Modes of Operation

Mode Type Padding Parallel Encrypt Parallel Decrypt Notes
ECB Block Required ⚠️ Insecure for multi-block
CBC Block Required Needs unpredictable IV
CTR Stream None Recommended for most uses
Stream Stream None ChaCha20 native mode
Algorithm Key Size Nonce Size Tag Size Performance Hardware Accel Best For
AES-GCM 128/192/256 12 bytes 16 bytes Very fast* AES-NI + PCLMULQDQ/VPCLMULQDQ General purpose, high throughput
AES-CCM 128/192/256 7-13 bytes 4-16 bytes Moderate* AES-NI IoT, small messages
ChaCha20-Poly1305 256 12 bytes 16 bytes Fast SSSE3/AVX2 Software-only, mobile
XChaCha20-Poly1305 256 24 bytes 16 bytes Fast SSSE3/AVX2 Random nonces safe

*With AES-NI hardware acceleration. Without hardware: ChaCha20 is typically faster.


Security Considerations

Critical: Nonce Uniqueness

All AEAD ciphers require unique (key, nonce) pairs:

// ❌ WRONG - Nonce reuse destroys security
var aesGcm = AesGcm256.Create(key);
byte[] nonce = new byte[12]; // Same nonce!
aesGcm.Encrypt(nonce, message1, ...); // First use: OK
aesGcm.Encrypt(nonce, message2, ...); // Reuse: CATASTROPHIC FAILURE

// ✅ CORRECT - Unique nonce for each message
var aesGcm = AesGcm256.Create(key);
byte[] nonce1 = GenerateUniqueNonce(); // Method 1: Counter
aesGcm.Encrypt(nonce1, message1, ...);

byte[] nonce2 = GenerateUniqueNonce(); // Method 2: Random (XChaCha20 preferred)
aesGcm.Encrypt(nonce2, message2, ...);

Nonce Generation Strategies

Method 1: Counter (Recommended for most cases)

private ulong _counter = 0;

byte[] GenerateNonce()
{
    byte[] nonce = new byte[12];
    BinaryPrimitives.WriteUInt64LittleEndian(nonce, _counter++);
    return nonce;
}

Method 2: Random (XChaCha20-Poly1305 only)

// Safe only with 192-bit nonces (XChaCha20)
byte[] nonce = new byte[24];
RandomNumberGenerator.Fill(nonce);
// Collision probability negligible with 192 bits

Method 3: Random + Counter (Hybrid)

// 64-bit random + 32-bit counter
byte[] nonce = new byte[12];
RandomNumberGenerator.Fill(nonce.AsSpan(0, 8)); // Random prefix
BinaryPrimitives.WriteUInt32LittleEndian(nonce.AsSpan(8), counter++);

Additional Authenticated Data (AAD)

AAD is authenticated but not encrypted (useful for headers, metadata):

// Encrypt message with authenticated header
byte[] header = Encoding.UTF8.GetBytes("User-ID: 12345");
byte[] message = Encoding.UTF8.GetBytes("Secret message");

aesGcm.Encrypt(nonce, message, ciphertext, tag, header);
// Result: message is encrypted, header is authenticated but plaintext

References

Standards

  • NIST FIPS 197 - Advanced Encryption Standard (AES)
  • NIST SP 800-38A - Recommendation for Block Cipher Modes: ECB, CBC, CFB, OFB, CTR
  • NIST SP 800-38C - Recommendation for Block Cipher Modes: CCM
  • NIST SP 800-38D - Recommendation for Block Cipher Modes: GCM
  • RFC 3610 - Counter with CBC-MAC (CCM)
  • RFC 8439 - ChaCha20 and Poly1305 for IETF Protocols
  • draft-irtf-cfrg-xchacha - XChaCha20-Poly1305

Test Vectors

Test vector documentation is coming soon.

Benchmarks