Windows X64 AMD Ryzen 5 7600X Cipher Benchmarks
Machine Profile
Machine Specification
The benchmarks were run on the following machine:
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8655/25H2/2025Update/HudsonValley2)
AMD Ryzen 5 7600X 4.70GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.301
[Host] : .NET 10.0.9 (10.0.9, 10.0.926.27113), X64 RyuJIT x86-64-v4
.NET 10.0 : .NET 10.0.9 (10.0.9, 10.0.926.27113), X64 RyuJIT x86-64-v4
Method=TryComputeHash Job=.NET 10.0 Runtime=.NET 10.0
Toolchain=net10.0
Note: Results are machine-specific and may vary between systems. Run benchmarks locally for your specific hardware.
BenchmarkDotNet measurements for all cipher algorithm implementations in CryptoHives.Foundation.Security.Cryptography. Each algorithm is benchmarked across representative payload sizes (17 bytes through 128 KiB) to capture both latency and throughput characteristics.
Implementation Variants
Each cipher family exposes multiple acceleration tiers. The runtime automatically selects the fastest tier supported by the host CPU via SimdSupport detection. Callers can also force a specific tier through the Create(SimdSupport) factory for testing or compatibility.
AES Family
| Variant | Instructions | .NET Target | When Selected | Description |
|---|---|---|---|---|
| Managed | Scalar | All | No AES-NI support | T-table AES (AESENC/AESDEC emulated via lookup tables). Fully portable, zero-allocation. ~3–16× slower than AES-NI depending on mode and payload size. |
| AES-NI | AES-NI | .NET 8+ | Aes.IsSupported |
Hardware AES round instructions (AESENC, AESDEC, AESIMC). For CBC, uses 8-block interleaved decrypt for maximum instruction-level parallelism. For GCM/CCM, accelerates counter-mode encryption and CBC-MAC. |
| AES-NI+PClMul | AES-NI, PCLMULQDQ | .NET 8+ | Pclmulqdq.IsSupported |
Adds carry-less multiplication for hardware-accelerated GHASH (GCM authentication). Uses an 8-block stitched pipeline that interleaves AES rounds with GHASH CLMUL operations across alternating CPU ports. Modular reduction uses a 2-CLMUL approach (SymCrypt-style MODREDUCE), replacing 26 shift/XOR operations with 2 carry-less multiplies + 6 vector ops. Pre-computes Karatsuba cross-term halves for H¹–H⁸ powers. |
| AES-NI+PClMulV256 | AES-NI, VPCLMULQDQ, AVX2 | .NET 10+ | Pclmulqdq.V256.IsSupported |
Extends PClMul with 256-bit carry-less multiply (VPCLMULQDQ) and AVX2 256-bit loads/stores. Processes two 128-bit GHASH blocks per CLMUL instruction. Counter blocks are generated in batches of 8 using Vector256 increments. Best path for payloads ≥256 bytes on CPUs with VPCLMULQDQ support (Ice Lake+). |
ChaCha20 Family
| Variant | Instructions | .NET Target | When Selected | Description |
|---|---|---|---|---|
| Managed | Scalar | All | No SSSE3 support | Quarter-round operations using scalar uint arithmetic. Fully portable. ~3–6× slower than SIMD paths. |
| SSSE3 | SSSE3 | .NET 8+ | Ssse3.IsSupported |
Maps the 4×4 ChaCha state to four Vector128<uint> rows. Uses Ssse3.Shuffle byte masks for 16-bit and 8-bit rotations (1 instruction vs 3 for shift+or). Diagonal rounds use Sse2.Shuffle to rotate rows. Processes one 64-byte block per iteration. |
| AVX2 | AVX2, SSSE3 | .NET 8+ | Avx2.IsSupported |
Dual-block processing: encrypts two 64-byte blocks per iteration using Vector256<uint>. Falls back to SSSE3 for a remaining single block. ~1.9× faster than SSSE3 at 128 KiB. |
When to Use Each Variant
- Small messages (≤128 B): AES-GCM with AES-NI is ~2× faster than OS due to zero P/Invoke overhead and no kernel transition. ChaCha20-Poly1305 AVX2 is competitive with OS at these sizes.
- Medium messages (256 B–1 KB): AES-GCM V256 stitched pipeline engages at >=256 B (>=16 blocks), providing the best throughput. This range covers QUIC (~1.4 KB), WireGuard (~1.4 KB), and IPsec packets.
- Large messages (8 KB–128 KB): AES-GCM V256 decrypt stays within 1.24× of OS. ChaCha20-Poly1305 AVX2 is ~1.53× faster than OS at 128 KiB. This range covers TLS records (1–16 KB) and OPC UA chunks (8 KB default).
- No hardware AES: Use ChaCha20-Poly1305 — it is designed for software-only execution and outperforms managed AES-GCM by 10–20×.
- IoT / constrained devices: AES-CCM with AES-NI provides ~3× speedup over managed. Supports variable nonce (7–13 bytes) and tag sizes.
Highlights
| Family | Leader | Key Insight |
|---|---|---|
| ChaCha20 | Managed AVX2 | AVX2 ~3× faster than BouncyCastle; SSSE3 ~1.7×; zero allocation |
| ChaCha20-Poly1305 | Managed AVX2 | ~1.53× faster than OS at 128 KiB; zero allocation |
| XChaCha20-Poly1305 | Managed AVX2 | Same core as ChaCha20-Poly1305; negligible overhead for extended nonce |
| AES-CBC | AES-NI | Decrypt ~5.8× faster than OS at 128 B; OS leads at ≥2 KB (wider AES pipeline); zero allocation |
| AES-GCM | AES-NI+PClMulV256 | ~2× faster than OS at 128 B encrypt; V256 decrypt within 1.24× of OS at 128 KiB; 8-block stitched AES+GHASH pipeline |
| AES-CCM | AES-NI | ~3× faster than Managed; zero allocation; no OS adapter available |
Stream Ciphers
ChaCha20
ChaCha20 is a stream cipher designed by Daniel J. Bernstein. Three acceleration tiers are available:
- AVX2: Dual-block processing — encrypts two 64-byte keystream blocks per iteration using
Vector256<uint>. Each block consists of 20 quarter-rounds operating on 8 lanes simultaneously. Falls back to SSSE3 for a remaining single block. Yields ~2 GB/s throughput at 128 KiB. - SSSE3: Single-block processing — maps the 4×4 state matrix to four
Vector128<uint>rows. UsesSsse3.Shufflebyte masks for 16-bit and 8-bit rotations (1 instruction vs 3 for shift+or). Yields ~1 GB/s throughput. - Managed: Scalar
uintquarter-round arithmetic. Fully portable across all .NET targets. ~3.4× slower than SSSE3.
Key observations:
- AVX2 is the fastest at all sizes, ~3× faster than BouncyCastle at 128 KiB
- SSSE3 is ~1.7× faster than BouncyCastle, processes single blocks via
Vector128<uint> - BouncyCastle allocates 96 B per call; NaCl.Core allocates 24 B per call
- Managed, SSSE3, and AVX2 paths are zero-allocation
| Description | TestDataSize | Mean | Error | StdDev | Median | Allocated |
|---|---|---|---|---|---|---|
| Decrypt · ChaCha20 (CryptoHives-AVX2) | 128B | 68.71 ns | 0.261 ns | 0.244 ns | 68.74 ns | - |
| Decrypt · ChaCha20 (CryptoHives-SSSE3) | 128B | 125.96 ns | 0.405 ns | 0.379 ns | 125.99 ns | - |
| Decrypt · ChaCha20 (NaCl.Core) | 128B | 279.83 ns | 0.529 ns | 0.442 ns | 280.00 ns | 24 B |
| Decrypt · ChaCha20 (BouncyCastle) | 128B | 317.57 ns | 0.470 ns | 0.393 ns | 317.56 ns | 96 B |
| Decrypt · ChaCha20 (CryptoHives-Scalar) | 128B | 461.65 ns | 0.718 ns | 0.637 ns | 461.69 ns | - |
| Encrypt · ChaCha20 (CryptoHives-AVX2) | 128B | 68.76 ns | 0.266 ns | 0.236 ns | 68.70 ns | - |
| Encrypt · ChaCha20 (CryptoHives-SSSE3) | 128B | 127.06 ns | 1.111 ns | 0.927 ns | 126.82 ns | - |
| Encrypt · ChaCha20 (NaCl.Core) | 128B | 275.58 ns | 1.010 ns | 0.895 ns | 275.48 ns | 24 B |
| Encrypt · ChaCha20 (BouncyCastle) | 128B | 316.48 ns | 0.675 ns | 0.599 ns | 316.45 ns | 96 B |
| Encrypt · ChaCha20 (CryptoHives-Scalar) | 128B | 460.43 ns | 0.487 ns | 0.431 ns | 460.37 ns | - |
| Decrypt · ChaCha20 (CryptoHives-AVX2) | 1KB | 520.18 ns | 1.450 ns | 1.356 ns | 520.28 ns | - |
| Decrypt · ChaCha20 (CryptoHives-SSSE3) | 1KB | 1,000.47 ns | 3.162 ns | 2.958 ns | 1,000.17 ns | - |
| Decrypt · ChaCha20 (NaCl.Core) | 1KB | 1,505.00 ns | 2.384 ns | 1.991 ns | 1,504.94 ns | 24 B |
| Decrypt · ChaCha20 (BouncyCastle) | 1KB | 1,805.21 ns | 3.823 ns | 3.389 ns | 1,805.38 ns | 96 B |
| Decrypt · ChaCha20 (CryptoHives-Scalar) | 1KB | 3,611.11 ns | 6.663 ns | 5.906 ns | 3,610.61 ns | - |
| Encrypt · ChaCha20 (CryptoHives-AVX2) | 1KB | 520.92 ns | 1.673 ns | 1.483 ns | 520.61 ns | - |
| Encrypt · ChaCha20 (CryptoHives-SSSE3) | 1KB | 1,003.75 ns | 3.649 ns | 3.413 ns | 1,003.05 ns | - |
| Encrypt · ChaCha20 (NaCl.Core) | 1KB | 1,500.57 ns | 2.154 ns | 2.015 ns | 1,500.45 ns | 24 B |
| Encrypt · ChaCha20 (BouncyCastle) | 1KB | 1,797.09 ns | 3.161 ns | 2.802 ns | 1,796.32 ns | 96 B |
| Encrypt · ChaCha20 (CryptoHives-Scalar) | 1KB | 3,592.26 ns | 4.760 ns | 4.220 ns | 3,591.55 ns | - |
| Decrypt · ChaCha20 (CryptoHives-AVX2) | 8KB | 4,151.85 ns | 13.677 ns | 11.421 ns | 4,152.57 ns | - |
| Decrypt · ChaCha20 (CryptoHives-SSSE3) | 8KB | 8,007.39 ns | 35.514 ns | 33.220 ns | 7,995.08 ns | - |
| Decrypt · ChaCha20 (NaCl.Core) | 8KB | 11,309.29 ns | 27.336 ns | 24.232 ns | 11,307.99 ns | 24 B |
| Decrypt · ChaCha20 (BouncyCastle) | 8KB | 13,659.25 ns | 11.274 ns | 9.994 ns | 13,657.57 ns | 96 B |
| Decrypt · ChaCha20 (CryptoHives-Scalar) | 8KB | 28,735.90 ns | 23.626 ns | 20.944 ns | 28,735.48 ns | - |
| Encrypt · ChaCha20 (CryptoHives-AVX2) | 8KB | 4,140.87 ns | 17.260 ns | 16.145 ns | 4,138.69 ns | - |
| Encrypt · ChaCha20 (CryptoHives-SSSE3) | 8KB | 8,062.35 ns | 147.176 ns | 130.468 ns | 8,010.07 ns | - |
| Encrypt · ChaCha20 (NaCl.Core) | 8KB | 11,353.58 ns | 145.656 ns | 136.247 ns | 11,246.86 ns | 24 B |
| Encrypt · ChaCha20 (BouncyCastle) | 8KB | 13,625.08 ns | 22.554 ns | 19.994 ns | 13,619.11 ns | 96 B |
| Encrypt · ChaCha20 (CryptoHives-Scalar) | 8KB | 28,662.90 ns | 44.668 ns | 41.782 ns | 28,652.48 ns | - |
| Decrypt · ChaCha20 (CryptoHives-AVX2) | 128KB | 66,263.43 ns | 345.620 ns | 306.383 ns | 66,179.12 ns | - |
| Decrypt · ChaCha20 (CryptoHives-SSSE3) | 128KB | 128,436.38 ns | 713.914 ns | 632.866 ns | 128,291.24 ns | - |
| Decrypt · ChaCha20 (NaCl.Core) | 128KB | 182,403.32 ns | 2,885.183 ns | 5,128.410 ns | 180,120.35 ns | 24 B |
| Decrypt · ChaCha20 (BouncyCastle) | 128KB | 217,864.72 ns | 692.249 ns | 613.661 ns | 217,605.69 ns | 96 B |
| Decrypt · ChaCha20 (CryptoHives-Scalar) | 128KB | 459,242.57 ns | 426.098 ns | 377.725 ns | 459,349.34 ns | - |
| Encrypt · ChaCha20 (CryptoHives-AVX2) | 128KB | 66,103.97 ns | 211.471 ns | 197.811 ns | 66,073.47 ns | - |
| Encrypt · ChaCha20 (CryptoHives-SSSE3) | 128KB | 128,136.21 ns | 719.607 ns | 600.905 ns | 128,075.02 ns | - |
| Encrypt · ChaCha20 (NaCl.Core) | 128KB | 178,490.04 ns | 217.570 ns | 181.681 ns | 178,474.37 ns | 24 B |
| Encrypt · ChaCha20 (BouncyCastle) | 128KB | 217,241.51 ns | 318.968 ns | 298.363 ns | 217,214.33 ns | 96 B |
| Encrypt · ChaCha20 (CryptoHives-Scalar) | 128KB | 457,646.76 ns | 462.641 ns | 410.120 ns | 457,697.05 ns | - |
Block Ciphers
AES-128-CBC
AES-CBC (Cipher Block Chaining) is the most widely deployed AES mode. Two acceleration tiers are available:
- AES-NI: Uses hardware
AESENC/AESDECinstructions. Decrypt uses 8-block interleaving — 8 ciphertext blocks are loaded and decrypted simultaneously, exploiting the fact that CBC decrypt is embarrassingly parallel (each block decrypts independently using only its predecessor as the XOR mask). This saturates the AES execution unit pipeline (10 rounds × 8 blocks = 80AESDECinstructions in flight). Encrypt remains serial because each plaintext block must be XORed with the previous ciphertext before encryption. - Managed: T-table AES using four 256-entry lookup tables per round. Fully portable, zero-allocation. Outperforms BouncyCastle by ~22% at small sizes.
Key observations:
- AES-NI Decrypt: ~5.8× faster than OS at 128 B (46 ns vs 268 ns); crossover at ~1 KB; OS is ~3× faster at 128 KiB — the OS uses a wider AES pipeline (potentially VAES/AVX-512 AES internally) for bulk operations
- AES-NI Encrypt: ~1.65× faster than OS at 128 B; ~2.4× slower than OS at 128 KiB (CBC encrypt is inherently serial; OS benefits from kernel-level prefetch and NUMA scheduling)
- Managed: Zero-allocation T-table AES; outperforms BouncyCastle by ~22% at small inputs; comparable at bulk sizes
- OS: Allocates 128 B per call (P/Invoke marshalling overhead)
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-128-CBC (CryptoHives-AES-NI) | 128B | 50.75 ns | 0.665 ns | 0.622 ns | - |
| Decrypt · AES-128-CBC (OS) | 128B | 259.28 ns | 3.436 ns | 3.046 ns | 128 B |
| Decrypt · AES-128-CBC (CryptoHives-Scalar) | 128B | 459.91 ns | 3.365 ns | 2.810 ns | - |
| Decrypt · AES-128-CBC (BouncyCastle) | 128B | 724.96 ns | 11.037 ns | 9.784 ns | 832 B |
| Encrypt · AES-128-CBC (CryptoHives-AES-NI) | 128B | 86.03 ns | 0.341 ns | 0.319 ns | - |
| Encrypt · AES-128-CBC (OS) | 128B | 281.92 ns | 2.968 ns | 2.631 ns | 128 B |
| Encrypt · AES-128-CBC (CryptoHives-Scalar) | 128B | 463.42 ns | 9.173 ns | 8.581 ns | - |
| Encrypt · AES-128-CBC (BouncyCastle) | 128B | 644.05 ns | 7.155 ns | 6.693 ns | 832 B |
| Decrypt · AES-128-CBC (CryptoHives-AES-NI) | 1KB | 221.59 ns | 2.074 ns | 1.940 ns | - |
| Decrypt · AES-128-CBC (OS) | 1KB | 326.26 ns | 3.053 ns | 2.549 ns | 128 B |
| Decrypt · AES-128-CBC (CryptoHives-Scalar) | 1KB | 3,244.04 ns | 38.375 ns | 35.896 ns | - |
| Decrypt · AES-128-CBC (BouncyCastle) | 1KB | 4,025.68 ns | 48.740 ns | 45.592 ns | 832 B |
| Encrypt · AES-128-CBC (CryptoHives-AES-NI) | 1KB | 530.67 ns | 10.477 ns | 12.867 ns | - |
| Encrypt · AES-128-CBC (OS) | 1KB | 710.89 ns | 9.922 ns | 9.281 ns | 128 B |
| Encrypt · AES-128-CBC (CryptoHives-Scalar) | 1KB | 3,693.67 ns | 42.842 ns | 40.074 ns | - |
| Encrypt · AES-128-CBC (BouncyCastle) | 1KB | 3,815.45 ns | 36.916 ns | 34.531 ns | 832 B |
| Decrypt · AES-128-CBC (OS) | 8KB | 801.01 ns | 15.972 ns | 28.391 ns | 128 B |
| Decrypt · AES-128-CBC (CryptoHives-AES-NI) | 8KB | 1,635.22 ns | 25.371 ns | 23.732 ns | - |
| Decrypt · AES-128-CBC (CryptoHives-Scalar) | 8KB | 25,519.65 ns | 280.294 ns | 248.473 ns | - |
| Decrypt · AES-128-CBC (BouncyCastle) | 8KB | 30,968.59 ns | 511.694 ns | 453.603 ns | 832 B |
| Encrypt · AES-128-CBC (OS) | 8KB | 4,096.32 ns | 6.893 ns | 5.756 ns | 128 B |
| Encrypt · AES-128-CBC (CryptoHives-AES-NI) | 8KB | 4,248.89 ns | 71.238 ns | 66.636 ns | - |
| Encrypt · AES-128-CBC (CryptoHives-Scalar) | 8KB | 25,190.52 ns | 263.730 ns | 233.790 ns | - |
| Encrypt · AES-128-CBC (BouncyCastle) | 8KB | 29,326.17 ns | 484.022 ns | 452.754 ns | 832 B |
| Decrypt · AES-128-CBC (OS) | 128KB | 8,966.72 ns | 33.686 ns | 29.861 ns | 128 B |
| Decrypt · AES-128-CBC (CryptoHives-AES-NI) | 128KB | 26,638.21 ns | 202.247 ns | 189.182 ns | - |
| Decrypt · AES-128-CBC (CryptoHives-Scalar) | 128KB | 426,122.10 ns | 2,724.730 ns | 2,415.402 ns | - |
| Decrypt · AES-128-CBC (BouncyCastle) | 128KB | 502,036.98 ns | 2,695.768 ns | 2,521.623 ns | 832 B |
| Encrypt · AES-128-CBC (OS) | 128KB | 65,444.28 ns | 1,278.862 ns | 1,522.395 ns | 128 B |
| Encrypt · AES-128-CBC (CryptoHives-AES-NI) | 128KB | 66,361.36 ns | 675.774 ns | 632.120 ns | - |
| Encrypt · AES-128-CBC (BouncyCastle) | 128KB | 464,628.84 ns | 4,527.173 ns | 3,780.395 ns | 832 B |
| Encrypt · AES-128-CBC (CryptoHives-Scalar) | 128KB | 467,512.10 ns | 5,175.913 ns | 4,041.012 ns | - |
AES-256-CBC
AES-256-CBC uses 14 rounds (vs 10 for AES-128), adding ~25-30% overhead. The same 8-block interleaved decrypt and serial encrypt architecture applies. The AES-NI decrypt path is ~5× faster than OS at 128 B; OS leads from ~2 KiB due to its wider bulk AES pipeline.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-256-CBC (CryptoHives-AES-NI) | 128B | 66.68 ns | 0.272 ns | 0.241 ns | - |
| Decrypt · AES-256-CBC (OS) | 128B | 290.44 ns | 2.560 ns | 2.270 ns | 128 B |
| Decrypt · AES-256-CBC (CryptoHives-Scalar) | 128B | 611.80 ns | 3.187 ns | 2.981 ns | - |
| Decrypt · AES-256-CBC (BouncyCastle) | 128B | 985.69 ns | 5.685 ns | 5.317 ns | 1024 B |
| Encrypt · AES-256-CBC (CryptoHives-AES-NI) | 128B | 114.24 ns | 0.345 ns | 0.306 ns | - |
| Encrypt · AES-256-CBC (OS) | 128B | 343.56 ns | 1.745 ns | 1.547 ns | 128 B |
| Encrypt · AES-256-CBC (CryptoHives-Scalar) | 128B | 613.36 ns | 4.484 ns | 4.194 ns | - |
| Encrypt · AES-256-CBC (BouncyCastle) | 128B | 886.79 ns | 10.073 ns | 9.422 ns | 1024 B |
| Decrypt · AES-256-CBC (CryptoHives-AES-NI) | 1KB | 319.77 ns | 1.596 ns | 1.493 ns | - |
| Decrypt · AES-256-CBC (OS) | 1KB | 366.77 ns | 2.422 ns | 2.265 ns | 128 B |
| Decrypt · AES-256-CBC (CryptoHives-Scalar) | 1KB | 4,328.26 ns | 40.939 ns | 38.295 ns | - |
| Decrypt · AES-256-CBC (BouncyCastle) | 1KB | 5,266.45 ns | 31.456 ns | 29.424 ns | 1024 B |
| Encrypt · AES-256-CBC (CryptoHives-AES-NI) | 1KB | 718.47 ns | 3.014 ns | 2.820 ns | - |
| Encrypt · AES-256-CBC (OS) | 1KB | 942.30 ns | 2.901 ns | 2.713 ns | 128 B |
| Encrypt · AES-256-CBC (CryptoHives-Scalar) | 1KB | 4,358.86 ns | 43.811 ns | 40.981 ns | - |
| Encrypt · AES-256-CBC (BouncyCastle) | 1KB | 5,129.30 ns | 40.913 ns | 38.270 ns | 1024 B |
| Decrypt · AES-256-CBC (OS) | 8KB | 1,014.12 ns | 6.862 ns | 5.730 ns | 128 B |
| Decrypt · AES-256-CBC (CryptoHives-AES-NI) | 8KB | 2,340.49 ns | 8.785 ns | 8.217 ns | - |
| Decrypt · AES-256-CBC (CryptoHives-Scalar) | 8KB | 33,904.69 ns | 287.835 ns | 269.241 ns | - |
| Decrypt · AES-256-CBC (BouncyCastle) | 8KB | 39,365.76 ns | 502.892 ns | 419.938 ns | 1024 B |
| Encrypt · AES-256-CBC (CryptoHives-AES-NI) | 8KB | 5,561.59 ns | 17.481 ns | 14.597 ns | - |
| Encrypt · AES-256-CBC (OS) | 8KB | 5,695.69 ns | 11.119 ns | 10.401 ns | 128 B |
| Encrypt · AES-256-CBC (CryptoHives-Scalar) | 8KB | 34,248.96 ns | 374.584 ns | 350.386 ns | - |
| Encrypt · AES-256-CBC (BouncyCastle) | 8KB | 39,408.37 ns | 244.538 ns | 216.776 ns | 1024 B |
| Decrypt · AES-256-CBC (OS) | 128KB | 12,171.58 ns | 241.450 ns | 225.853 ns | 128 B |
| Decrypt · AES-256-CBC (CryptoHives-AES-NI) | 128KB | 36,890.42 ns | 182.912 ns | 162.147 ns | - |
| Decrypt · AES-256-CBC (CryptoHives-Scalar) | 128KB | 541,261.19 ns | 2,943.075 ns | 2,608.959 ns | - |
| Decrypt · AES-256-CBC (BouncyCastle) | 128KB | 629,974.34 ns | 7,011.255 ns | 6,215.295 ns | 1024 B |
| Encrypt · AES-256-CBC (OS) | 128KB | 87,667.03 ns | 320.283 ns | 299.593 ns | 128 B |
| Encrypt · AES-256-CBC (CryptoHives-AES-NI) | 128KB | 88,415.27 ns | 256.733 ns | 240.148 ns | - |
| Encrypt · AES-256-CBC (CryptoHives-Scalar) | 128KB | 546,126.26 ns | 3,684.706 ns | 3,446.676 ns | - |
| Encrypt · AES-256-CBC (BouncyCastle) | 128KB | 624,853.57 ns | 4,598.242 ns | 4,301.199 ns | 1024 B |
AEAD Ciphers (Authenticated Encryption)
Authenticated Encryption with Associated Data (AEAD) ciphers provide both confidentiality and authenticity in a single operation. All CryptoHives AEAD implementations are zero-allocation.
AES-128-GCM
AES-GCM combines counter-mode AES encryption (GCTR) with GHASH polynomial authentication over GF(2¹²⁸). Four acceleration tiers are available:
- AES-NI+PClMulV256 (.NET 10+): The fastest path on CPUs with VPCLMULQDQ (Ice Lake and later). Uses 256-bit carry-less multiply instructions (
VPCLMULQDQ) to process two GHASH blocks per CLMUL instruction. Counter blocks are generated in batches of 8 usingVector256<uint>increments. The stitched loop interleaves 8 blocks of AES encryption with lagged GHASH of the previous 8 ciphertext blocks — AES rounds execute on port 0 while CLMUL operations execute on port 5, achieving near-full utilization of both execution units. Modular reduction uses a 2-CLMUL SymCrypt-styleMODREDUCE(constant0xc200000000000000compensates for reflected bit order). Pre-computed H¹–H⁸ Karatsuba cross-term halves eliminate redundant XORs in the aggregated multiply. Only engages for payloads >128 B (>8 blocks); smaller payloads use the non-stitched path to avoid method call overhead. - AES-NI+PClMul (.NET 8+): Uses 128-bit
PCLMULQDQfor GHASH with the same 8-block stitched architecture. Falls back to this path when VPCLMULQDQ is unavailable (Haswell through Cannon Lake). Within 1.67× of OS at 128 KiB. - AES-NI (.NET 8+): Hardware AES round instructions for GCTR without CLMUL-accelerated GHASH. Uses the managed 4-bit Shoup table for authentication. 14–16× faster than fully managed at 128 KiB.
- Managed: Scalar T-table AES with 4-bit Shoup table GHASH (16-entry reduction table, byte-by-byte multiplication). Fully portable, zero-allocation.
Key observations:
- AES-NI+PClMulV256: ~2× faster than OS at 128 B encrypt; within 1.24× of OS at 128 KiB decrypt
- AES-NI+PClMul: ~2× faster than OS at 128 B encrypt; within 1.67× of OS at 128 KiB
- AES-NI: 14–16× faster than Managed at 128 KiB, zero allocation
- Managed: Uses 4-bit Shoup table GHASH, T-table AES
- BouncyCastle: Uses AES-NI + PCLMULQDQ internally on .NET Core 3.0+; allocates ~1.6 KB per call
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-128-GCM (OS) | 17B | 117.81 ns | 0.387 ns | 0.323 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 120.68 ns | 0.246 ns | 0.218 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 17B | 125.04 ns | 0.221 ns | 0.207 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 17B | 347.19 ns | 0.824 ns | 0.730 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 17B | 587.58 ns | 2.472 ns | 2.313 ns | 1624 B |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 66.54 ns | 0.101 ns | 0.090 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 17B | 67.49 ns | 0.071 ns | 0.059 ns | - |
| Encrypt · AES-128-GCM (OS) | 17B | 122.84 ns | 0.171 ns | 0.143 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 17B | 317.65 ns | 0.523 ns | 0.463 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 17B | 566.44 ns | 3.521 ns | 3.294 ns | 1608 B |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 102.36 ns | 0.383 ns | 0.340 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 65B | 103.46 ns | 0.171 ns | 0.160 ns | - |
| Decrypt · AES-128-GCM (OS) | 65B | 122.84 ns | 0.356 ns | 0.315 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 65B | 593.71 ns | 1.330 ns | 1.179 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 65B | 779.70 ns | 3.011 ns | 2.817 ns | 1624 B |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 65B | 71.67 ns | 0.169 ns | 0.149 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 71.74 ns | 0.177 ns | 0.166 ns | - |
| Encrypt · AES-128-GCM (OS) | 65B | 127.24 ns | 0.534 ns | 0.446 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 65B | 564.17 ns | 1.586 ns | 1.406 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 65B | 680.58 ns | 2.944 ns | 2.609 ns | 1608 B |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 96.70 ns | 0.202 ns | 0.158 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 128B | 98.06 ns | 0.139 ns | 0.130 ns | - |
| Decrypt · AES-128-GCM (OS) | 128B | 126.33 ns | 0.407 ns | 0.340 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 128B | 839.97 ns | 2.033 ns | 1.698 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 128B | 903.47 ns | 1.874 ns | 1.565 ns | 1624 B |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 60.46 ns | 0.154 ns | 0.136 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 128B | 63.38 ns | 0.201 ns | 0.168 ns | - |
| Encrypt · AES-128-GCM (OS) | 128B | 119.13 ns | 0.247 ns | 0.206 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 128B | 812.25 ns | 1.403 ns | 1.313 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 128B | 823.44 ns | 4.457 ns | 4.169 ns | 1608 B |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 152B | 124.23 ns | 0.293 ns | 0.260 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 129.68 ns | 0.308 ns | 0.258 ns | - |
| Decrypt · AES-128-GCM (OS) | 152B | 138.24 ns | 0.465 ns | 0.363 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 152B | 1,027.69 ns | 1.986 ns | 1.858 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 152B | 1,042.76 ns | 1.850 ns | 1.640 ns | 1624 B |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 90.11 ns | 0.179 ns | 0.140 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 152B | 91.99 ns | 0.139 ns | 0.124 ns | - |
| Encrypt · AES-128-GCM (OS) | 152B | 137.48 ns | 0.383 ns | 0.320 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 152B | 940.85 ns | 3.121 ns | 2.920 ns | 1608 B |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 152B | 983.02 ns | 1.625 ns | 1.520 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 111.71 ns | 0.183 ns | 0.162 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 256B | 123.01 ns | 0.290 ns | 0.242 ns | - |
| Decrypt · AES-128-GCM (OS) | 256B | 131.11 ns | 0.162 ns | 0.136 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 256B | 1,310.09 ns | 3.564 ns | 3.159 ns | 1624 B |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 256B | 1,498.95 ns | 5.014 ns | 4.445 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 77.05 ns | 0.111 ns | 0.098 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 256B | 81.65 ns | 0.240 ns | 0.225 ns | - |
| Encrypt · AES-128-GCM (OS) | 256B | 132.90 ns | 0.221 ns | 0.207 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 256B | 1,222.44 ns | 2.941 ns | 2.296 ns | 1608 B |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 256B | 1,476.89 ns | 7.364 ns | 6.150 ns | - |
| Decrypt · AES-128-GCM (OS) | 1KB | 180.32 ns | 0.367 ns | 0.306 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 201.31 ns | 0.248 ns | 0.232 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 244.63 ns | 0.513 ns | 0.455 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 1KB | 3,753.43 ns | 4.031 ns | 3.366 ns | 1624 B |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 1KB | 5,444.19 ns | 18.118 ns | 16.061 ns | - |
| Encrypt · AES-128-GCM (OS) | 1KB | 174.21 ns | 0.776 ns | 0.648 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 177.52 ns | 0.364 ns | 0.340 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 200.05 ns | 0.225 ns | 0.176 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 1KB | 3,643.70 ns | 5.336 ns | 4.731 ns | 1608 B |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 1KB | 5,434.36 ns | 11.437 ns | 10.139 ns | - |
| Decrypt · AES-128-GCM (OS) | 8KB | 710.91 ns | 1.422 ns | 1.261 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,042.15 ns | 8.076 ns | 6.744 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,391.93 ns | 4.956 ns | 4.636 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 8KB | 26,228.89 ns | 78.670 ns | 69.739 ns | 1624 B |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 8KB | 42,211.55 ns | 79.233 ns | 70.238 ns | - |
| Encrypt · AES-128-GCM (OS) | 8KB | 665.34 ns | 1.408 ns | 1.317 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,107.08 ns | 3.038 ns | 2.841 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,320.55 ns | 3.013 ns | 2.671 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 8KB | 26,145.80 ns | 46.419 ns | 38.762 ns | 1608 B |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 8KB | 42,389.81 ns | 108.949 ns | 96.580 ns | - |
| Decrypt · AES-128-GCM (OS) | 128KB | 10,992.96 ns | 30.370 ns | 26.922 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 16,706.54 ns | 277.474 ns | 259.549 ns | - |
| Decrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 20,981.58 ns | 96.822 ns | 80.851 ns | - |
| Decrypt · AES-128-GCM (BouncyCastle) | 128KB | 412,144.78 ns | 2,466.792 ns | 2,059.883 ns | 1624 B |
| Decrypt · AES-128-GCM (CryptoHives-Scalar) | 128KB | 675,487.64 ns | 1,941.587 ns | 1,816.162 ns | - |
| Encrypt · AES-128-GCM (OS) | 128KB | 9,923.34 ns | 23.906 ns | 19.962 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 17,252.79 ns | 49.831 ns | 38.905 ns | - |
| Encrypt · AES-128-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 20,531.69 ns | 51.475 ns | 42.984 ns | - |
| Encrypt · AES-128-GCM (BouncyCastle) | 128KB | 412,313.24 ns | 684.916 ns | 607.161 ns | 1608 B |
| Encrypt · AES-128-GCM (CryptoHives-Scalar) | 128KB | 676,873.40 ns | 954.153 ns | 845.832 ns | - |
AES-192-GCM
AES-192-GCM uses 12 rounds (vs 10 for AES-128), adding ~15-20% overhead. The same stitched pipeline and SIMD dispatch tiers apply. Performance characteristics fall between AES-128-GCM and AES-256-GCM.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-192-GCM (OS) | 17B | 120.80 ns | 0.226 ns | 0.200 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 17B | 123.47 ns | 0.167 ns | 0.130 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 123.81 ns | 0.095 ns | 0.085 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 17B | 375.30 ns | 0.882 ns | 0.737 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 17B | 630.59 ns | 2.297 ns | 2.036 ns | 1728 B |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 17B | 69.29 ns | 0.119 ns | 0.105 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 69.36 ns | 0.167 ns | 0.148 ns | - |
| Encrypt · AES-192-GCM (OS) | 17B | 125.65 ns | 0.250 ns | 0.222 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 17B | 336.02 ns | 0.608 ns | 0.539 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 17B | 563.13 ns | 1.906 ns | 1.592 ns | 1712 B |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 108.17 ns | 0.205 ns | 0.171 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 65B | 111.93 ns | 0.208 ns | 0.174 ns | - |
| Decrypt · AES-192-GCM (OS) | 65B | 124.79 ns | 0.217 ns | 0.203 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 65B | 635.28 ns | 1.600 ns | 1.497 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 65B | 828.99 ns | 2.152 ns | 1.680 ns | 1728 B |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 76.16 ns | 0.090 ns | 0.079 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 65B | 76.45 ns | 0.147 ns | 0.131 ns | - |
| Encrypt · AES-192-GCM (OS) | 65B | 130.58 ns | 0.389 ns | 0.325 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 65B | 605.49 ns | 0.987 ns | 0.923 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 65B | 742.86 ns | 2.065 ns | 1.612 ns | 1712 B |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 100.27 ns | 0.159 ns | 0.141 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 128B | 100.84 ns | 0.320 ns | 0.284 ns | - |
| Decrypt · AES-192-GCM (OS) | 128B | 123.67 ns | 0.569 ns | 0.444 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 128B | 900.41 ns | 1.735 ns | 1.449 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 128B | 1,016.39 ns | 2.764 ns | 2.450 ns | 1728 B |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 63.76 ns | 0.112 ns | 0.100 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 128B | 65.97 ns | 0.105 ns | 0.093 ns | - |
| Encrypt · AES-192-GCM (OS) | 128B | 122.86 ns | 0.244 ns | 0.203 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 128B | 872.13 ns | 1.645 ns | 1.284 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 128B | 915.15 ns | 4.827 ns | 4.279 ns | 1712 B |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 131.02 ns | 0.167 ns | 0.148 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 152B | 132.29 ns | 0.367 ns | 0.325 ns | - |
| Decrypt · AES-192-GCM (OS) | 152B | 139.30 ns | 0.208 ns | 0.195 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 152B | 1,079.64 ns | 3.145 ns | 2.941 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 152B | 1,136.80 ns | 4.901 ns | 4.584 ns | 1728 B |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 91.07 ns | 0.121 ns | 0.113 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 152B | 92.81 ns | 0.202 ns | 0.168 ns | - |
| Encrypt · AES-192-GCM (OS) | 152B | 140.31 ns | 0.370 ns | 0.309 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 152B | 1,056.58 ns | 1.782 ns | 1.667 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 152B | 1,070.39 ns | 4.468 ns | 3.961 ns | 1712 B |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 122.90 ns | 0.541 ns | 0.451 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 256B | 128.34 ns | 0.275 ns | 0.229 ns | - |
| Decrypt · AES-192-GCM (OS) | 256B | 139.47 ns | 0.227 ns | 0.201 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 256B | 1,468.52 ns | 6.098 ns | 5.704 ns | 1728 B |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 256B | 1,611.16 ns | 4.268 ns | 3.992 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 82.39 ns | 0.232 ns | 0.206 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 256B | 87.45 ns | 0.236 ns | 0.209 ns | - |
| Encrypt · AES-192-GCM (OS) | 256B | 134.31 ns | 0.337 ns | 0.298 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 256B | 1,373.41 ns | 4.665 ns | 4.135 ns | 1712 B |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 256B | 1,583.42 ns | 3.265 ns | 2.895 ns | - |
| Decrypt · AES-192-GCM (OS) | 1KB | 193.13 ns | 0.785 ns | 0.696 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 208.56 ns | 0.296 ns | 0.262 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 268.47 ns | 0.984 ns | 0.921 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 1KB | 4,277.00 ns | 5.985 ns | 5.305 ns | 1728 B |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 1KB | 5,876.38 ns | 8.178 ns | 7.250 ns | - |
| Encrypt · AES-192-GCM (OS) | 1KB | 180.47 ns | 0.337 ns | 0.282 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 191.29 ns | 0.507 ns | 0.474 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 210.95 ns | 0.331 ns | 0.293 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 1KB | 4,167.29 ns | 9.854 ns | 8.735 ns | 1712 B |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 1KB | 5,899.56 ns | 12.058 ns | 10.069 ns | - |
| Decrypt · AES-192-GCM (OS) | 8KB | 774.53 ns | 1.855 ns | 1.645 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,114.36 ns | 1.952 ns | 1.731 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,479.76 ns | 4.129 ns | 3.660 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 8KB | 30,162.55 ns | 34.672 ns | 28.953 ns | 1728 B |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 8KB | 45,845.07 ns | 111.186 ns | 92.846 ns | - |
| Encrypt · AES-192-GCM (OS) | 8KB | 698.82 ns | 1.857 ns | 1.646 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,213.83 ns | 4.938 ns | 4.378 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,377.27 ns | 3.766 ns | 3.523 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 8KB | 30,072.43 ns | 33.706 ns | 31.528 ns | 1712 B |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 8KB | 45,959.71 ns | 153.950 ns | 136.473 ns | - |
| Decrypt · AES-192-GCM (OS) | 128KB | 11,884.81 ns | 17.907 ns | 16.751 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 17,050.61 ns | 304.750 ns | 270.153 ns | - |
| Decrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 22,215.62 ns | 61.871 ns | 51.665 ns | - |
| Decrypt · AES-192-GCM (BouncyCastle) | 128KB | 476,774.19 ns | 885.362 ns | 784.850 ns | 1728 B |
| Decrypt · AES-192-GCM (CryptoHives-Scalar) | 128KB | 730,811.60 ns | 1,700.731 ns | 1,420.187 ns | - |
| Encrypt · AES-192-GCM (OS) | 128KB | 10,380.00 ns | 25.911 ns | 22.970 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 18,860.65 ns | 104.917 ns | 98.139 ns | - |
| Encrypt · AES-192-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 21,431.82 ns | 59.238 ns | 49.466 ns | - |
| Encrypt · AES-192-GCM (BouncyCastle) | 128KB | 476,306.86 ns | 619.326 ns | 517.166 ns | 1712 B |
| Encrypt · AES-192-GCM (CryptoHives-Scalar) | 128KB | 730,918.98 ns | 1,590.454 ns | 1,328.101 ns | - |
AES-256-GCM
AES-256-GCM uses 14 rounds (vs 10 for AES-128), adding ~20-30% overhead per block. The same 4-tier acceleration architecture (V256 → PClMul → AES-NI → Managed) applies. The V256 stitched decrypt path achieves near-parity with OS at 1 KiB (1.00×) and stays within 1.24× at 128 KiB. Encrypt is ~2× faster than OS at 128 B due to the lagged GHASH pipeline and zero P/Invoke overhead. The remaining gap at large sizes is primarily due to OS/SymCrypt using VAES (256-bit AES round instructions) which CryptoHives does not yet use.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 121.71 ns | 0.373 ns | 0.331 ns | - |
| Decrypt · AES-256-GCM (OS) | 17B | 124.18 ns | 0.209 ns | 0.174 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 17B | 127.88 ns | 0.206 ns | 0.183 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 17B | 387.90 ns | 0.655 ns | 0.547 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 17B | 683.92 ns | 4.927 ns | 4.368 ns | 1832 B |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 17B | 72.01 ns | 0.112 ns | 0.104 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 17B | 72.78 ns | 0.116 ns | 0.108 ns | - |
| Encrypt · AES-256-GCM (OS) | 17B | 130.88 ns | 0.197 ns | 0.174 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 17B | 374.69 ns | 0.619 ns | 0.517 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 17B | 618.72 ns | 1.840 ns | 1.536 ns | 1816 B |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 112.57 ns | 0.270 ns | 0.240 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 65B | 116.54 ns | 0.251 ns | 0.235 ns | - |
| Decrypt · AES-256-GCM (OS) | 65B | 129.70 ns | 2.567 ns | 4.694 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 65B | 679.22 ns | 1.336 ns | 1.185 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 65B | 918.44 ns | 2.112 ns | 1.872 ns | 1832 B |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 65B | 79.88 ns | 0.156 ns | 0.139 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 65B | 80.32 ns | 0.168 ns | 0.157 ns | - |
| Encrypt · AES-256-GCM (OS) | 65B | 135.74 ns | 0.413 ns | 0.323 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 65B | 644.25 ns | 0.925 ns | 0.820 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 65B | 823.85 ns | 1.796 ns | 1.500 ns | 1816 B |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 103.51 ns | 0.403 ns | 0.357 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 128B | 105.75 ns | 0.158 ns | 0.140 ns | - |
| Decrypt · AES-256-GCM (OS) | 128B | 125.56 ns | 0.344 ns | 0.305 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 128B | 962.95 ns | 1.900 ns | 1.586 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 128B | 1,121.05 ns | 3.101 ns | 2.589 ns | 1832 B |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 128B | 66.51 ns | 0.149 ns | 0.140 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 128B | 69.66 ns | 0.136 ns | 0.120 ns | - |
| Encrypt · AES-256-GCM (OS) | 128B | 127.34 ns | 2.065 ns | 3.929 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 128B | 936.00 ns | 2.018 ns | 1.685 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 128B | 1,013.77 ns | 5.423 ns | 4.529 ns | 1816 B |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 139.12 ns | 0.171 ns | 0.151 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 152B | 140.05 ns | 0.284 ns | 0.252 ns | - |
| Decrypt · AES-256-GCM (OS) | 152B | 151.40 ns | 0.307 ns | 0.287 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 152B | 1,151.35 ns | 1.544 ns | 1.289 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 152B | 1,266.05 ns | 4.639 ns | 4.113 ns | 1832 B |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 152B | 94.84 ns | 0.109 ns | 0.097 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 152B | 97.39 ns | 0.102 ns | 0.085 ns | - |
| Encrypt · AES-256-GCM (OS) | 152B | 144.78 ns | 0.323 ns | 0.287 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 152B | 1,143.24 ns | 1.732 ns | 1.621 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 152B | 1,173.78 ns | 4.456 ns | 3.950 ns | 1816 B |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 117.95 ns | 0.307 ns | 0.272 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 256B | 134.19 ns | 0.221 ns | 0.173 ns | - |
| Decrypt · AES-256-GCM (OS) | 256B | 144.05 ns | 0.296 ns | 0.247 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 256B | 1,664.01 ns | 10.085 ns | 8.421 ns | 1832 B |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 256B | 1,728.74 ns | 6.542 ns | 6.119 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 256B | 86.99 ns | 0.129 ns | 0.114 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 256B | 91.56 ns | 0.189 ns | 0.177 ns | - |
| Encrypt · AES-256-GCM (OS) | 256B | 134.46 ns | 0.292 ns | 0.259 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 256B | 1,539.75 ns | 5.156 ns | 4.571 ns | 1816 B |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 256B | 1,700.23 ns | 2.247 ns | 2.102 ns | - |
| Decrypt · AES-256-GCM (OS) | 1KB | 213.54 ns | 0.320 ns | 0.284 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 215.50 ns | 0.490 ns | 0.459 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 268.78 ns | 0.531 ns | 0.443 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 1KB | 4,852.61 ns | 9.886 ns | 8.764 ns | 1832 B |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 1KB | 6,317.55 ns | 9.781 ns | 8.168 ns | - |
| Encrypt · AES-256-GCM (OS) | 1KB | 185.92 ns | 0.508 ns | 0.475 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 1KB | 205.50 ns | 0.391 ns | 0.346 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 1KB | 225.66 ns | 0.409 ns | 0.363 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 1KB | 4,729.14 ns | 9.580 ns | 8.493 ns | 1816 B |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 1KB | 6,308.98 ns | 8.586 ns | 7.169 ns | - |
| Decrypt · AES-256-GCM (OS) | 8KB | 939.09 ns | 1.851 ns | 1.641 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,145.26 ns | 2.611 ns | 2.314 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,566.65 ns | 3.584 ns | 3.177 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 8KB | 34,399.46 ns | 115.553 ns | 102.435 ns | 1832 B |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 8KB | 49,219.28 ns | 53.871 ns | 47.755 ns | - |
| Encrypt · AES-256-GCM (OS) | 8KB | 726.86 ns | 1.243 ns | 1.038 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 8KB | 1,328.76 ns | 3.504 ns | 2.736 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 8KB | 1,501.64 ns | 17.159 ns | 16.051 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 8KB | 34,112.69 ns | 64.403 ns | 57.091 ns | 1816 B |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 8KB | 49,187.45 ns | 58.387 ns | 48.756 ns | - |
| Decrypt · AES-256-GCM (OS) | 128KB | 14,661.12 ns | 28.951 ns | 24.175 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 18,570.83 ns | 169.777 ns | 158.810 ns | - |
| Decrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 23,677.30 ns | 78.994 ns | 70.026 ns | - |
| Decrypt · AES-256-GCM (BouncyCastle) | 128KB | 542,589.24 ns | 1,549.193 ns | 1,373.319 ns | 1832 B |
| Decrypt · AES-256-GCM (CryptoHives-Scalar) | 128KB | 786,476.43 ns | 1,105.307 ns | 979.826 ns | - |
| Encrypt · AES-256-GCM (OS) | 128KB | 10,917.80 ns | 52.355 ns | 43.719 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMulV256) | 128KB | 20,611.81 ns | 78.652 ns | 69.723 ns | - |
| Encrypt · AES-256-GCM (CryptoHives-AES-NI+PClMul) | 128KB | 23,284.73 ns | 60.690 ns | 53.800 ns | - |
| Encrypt · AES-256-GCM (BouncyCastle) | 128KB | 542,380.43 ns | 1,343.140 ns | 1,256.374 ns | 1816 B |
| Encrypt · AES-256-GCM (CryptoHives-Scalar) | 128KB | 788,912.01 ns | 943.250 ns | 836.167 ns | - |
AES-128-CCM
AES-CCM (Counter with CBC-MAC) combines CTR mode encryption with CBC-MAC authentication. Unlike GCM, CCM requires two sequential passes (encrypt + MAC or MAC + decrypt), making it inherently less parallelizable. It is widely used in IoT protocols (Bluetooth LE, ZigBee, Thread) and supports variable nonce (7–13 bytes) and tag sizes (4–16 bytes). Two acceleration tiers are available:
- AES-NI: Hardware
AESENCinstructions for all block operations — counter-mode encryption, CBC-MAC computation, and AAD processing. UsesVector128<byte>round keys viaMemoryMarshal.Castfrom the shareduint[]key schedule. Dispatched via_useAesNibool flag. - Managed: T-table AES for all block operations. Fully portable, zero-allocation.
Key observations:
- AES-NI: ~3× faster than Managed at 128 KiB, zero allocation
- Managed: T-table AES, outperforms BouncyCastle by ~15-20%
- BouncyCastle: Allocates ~2.4 KB per call
- No OS adapter available for comparison (System.Security.Cryptography does not expose AES-CCM on all platforms)
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-128-CCM (CryptoHives-AES-NI) | 128B | 406.2 ns | 0.58 ns | 0.52 ns | - |
| Decrypt · AES-128-CCM (CryptoHives-Scalar) | 128B | 1,026.0 ns | 3.44 ns | 3.05 ns | - |
| Decrypt · AES-128-CCM (BouncyCastle) | 128B | 1,640.9 ns | 3.78 ns | 3.35 ns | 2424 B |
| Encrypt · AES-128-CCM (CryptoHives-AES-NI) | 128B | 370.7 ns | 2.56 ns | 2.40 ns | - |
| Encrypt · AES-128-CCM (CryptoHives-Scalar) | 128B | 1,202.6 ns | 11.25 ns | 9.97 ns | - |
| Encrypt · AES-128-CCM (BouncyCastle) | 128B | 1,772.6 ns | 11.35 ns | 17.34 ns | 2464 B |
| Decrypt · AES-128-CCM (CryptoHives-AES-NI) | 1KB | 2,312.6 ns | 2.95 ns | 2.61 ns | - |
| Decrypt · AES-128-CCM (CryptoHives-Scalar) | 1KB | 6,506.7 ns | 21.36 ns | 19.98 ns | - |
| Decrypt · AES-128-CCM (BouncyCastle) | 1KB | 8,262.8 ns | 24.40 ns | 21.63 ns | 2424 B |
| Encrypt · AES-128-CCM (CryptoHives-AES-NI) | 1KB | 2,341.4 ns | 10.56 ns | 9.88 ns | - |
| Encrypt · AES-128-CCM (CryptoHives-Scalar) | 1KB | 6,766.3 ns | 131.49 ns | 122.99 ns | - |
| Encrypt · AES-128-CCM (BouncyCastle) | 1KB | 8,259.5 ns | 55.33 ns | 51.75 ns | 2464 B |
| Decrypt · AES-128-CCM (CryptoHives-AES-NI) | 8KB | 17,587.7 ns | 32.74 ns | 29.03 ns | - |
| Decrypt · AES-128-CCM (CryptoHives-Scalar) | 8KB | 49,560.8 ns | 86.50 ns | 76.68 ns | - |
| Decrypt · AES-128-CCM (BouncyCastle) | 8KB | 60,749.2 ns | 147.20 ns | 122.92 ns | 2424 B |
| Encrypt · AES-128-CCM (CryptoHives-AES-NI) | 8KB | 17,599.4 ns | 42.48 ns | 37.66 ns | - |
| Encrypt · AES-128-CCM (CryptoHives-Scalar) | 8KB | 49,970.9 ns | 348.39 ns | 308.84 ns | - |
| Encrypt · AES-128-CCM (BouncyCastle) | 8KB | 60,903.8 ns | 202.60 ns | 179.60 ns | 2464 B |
| Decrypt · AES-128-CCM (CryptoHives-AES-NI) | 128KB | 278,845.4 ns | 262.89 ns | 245.91 ns | - |
| Decrypt · AES-128-CCM (CryptoHives-Scalar) | 128KB | 793,776.4 ns | 3,275.83 ns | 2,903.93 ns | - |
| Decrypt · AES-128-CCM (BouncyCastle) | 128KB | 959,488.9 ns | 2,176.74 ns | 2,036.12 ns | 2424 B |
| Encrypt · AES-128-CCM (CryptoHives-AES-NI) | 128KB | 279,600.1 ns | 461.70 ns | 360.46 ns | - |
| Encrypt · AES-128-CCM (CryptoHives-Scalar) | 128KB | 795,114.2 ns | 2,637.06 ns | 2,466.71 ns | - |
| Encrypt · AES-128-CCM (BouncyCastle) | 128KB | 967,299.1 ns | 5,840.19 ns | 4,876.82 ns | 2464 B |
AES-256-CCM
AES-256-CCM uses 14 rounds (vs 10 for AES-128). The same AES-NI / Managed dispatch applies. The additional rounds add ~25-30% overhead.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · AES-256-CCM (CryptoHives-AES-NI) | 128B | 463.9 ns | 7.44 ns | 6.21 ns | - |
| Decrypt · AES-256-CCM (CryptoHives-Scalar) | 128B | 1,305.1 ns | 8.38 ns | 6.54 ns | - |
| Decrypt · AES-256-CCM (BouncyCastle) | 128B | 2,074.3 ns | 38.47 ns | 37.78 ns | 2808 B |
| Encrypt · AES-256-CCM (CryptoHives-AES-NI) | 128B | 415.1 ns | 1.80 ns | 1.50 ns | - |
| Encrypt · AES-256-CCM (CryptoHives-Scalar) | 128B | 1,254.4 ns | 13.20 ns | 14.12 ns | - |
| Encrypt · AES-256-CCM (BouncyCastle) | 128B | 1,987.9 ns | 21.51 ns | 19.07 ns | 2848 B |
| Decrypt · AES-256-CCM (CryptoHives-AES-NI) | 1KB | 2,750.2 ns | 4.21 ns | 3.73 ns | - |
| Decrypt · AES-256-CCM (CryptoHives-Scalar) | 1KB | 9,707.8 ns | 23.38 ns | 19.52 ns | - |
| Decrypt · AES-256-CCM (BouncyCastle) | 1KB | 10,474.1 ns | 43.64 ns | 38.69 ns | 2808 B |
| Encrypt · AES-256-CCM (CryptoHives-AES-NI) | 1KB | 2,696.1 ns | 6.66 ns | 5.91 ns | - |
| Encrypt · AES-256-CCM (CryptoHives-Scalar) | 1KB | 8,198.3 ns | 26.54 ns | 24.82 ns | - |
| Encrypt · AES-256-CCM (BouncyCastle) | 1KB | 10,423.5 ns | 26.85 ns | 20.96 ns | 2848 B |
| Decrypt · AES-256-CCM (CryptoHives-AES-NI) | 8KB | 21,095.0 ns | 45.78 ns | 40.58 ns | - |
| Decrypt · AES-256-CCM (CryptoHives-Scalar) | 8KB | 64,198.9 ns | 439.88 ns | 367.32 ns | - |
| Decrypt · AES-256-CCM (BouncyCastle) | 8KB | 77,031.4 ns | 195.02 ns | 162.85 ns | 2808 B |
| Encrypt · AES-256-CCM (CryptoHives-AES-NI) | 8KB | 20,981.6 ns | 43.11 ns | 40.32 ns | - |
| Encrypt · AES-256-CCM (CryptoHives-Scalar) | 8KB | 63,679.9 ns | 202.99 ns | 169.51 ns | - |
| Encrypt · AES-256-CCM (BouncyCastle) | 8KB | 76,446.9 ns | 145.93 ns | 121.85 ns | 2848 B |
| Decrypt · AES-256-CCM (CryptoHives-AES-NI) | 128KB | 334,618.3 ns | 302.22 ns | 267.91 ns | - |
| Decrypt · AES-256-CCM (CryptoHives-Scalar) | 128KB | 1,210,420.3 ns | 3,128.95 ns | 2,612.82 ns | - |
| Decrypt · AES-256-CCM (BouncyCastle) | 128KB | 1,219,205.7 ns | 6,322.52 ns | 5,604.75 ns | 2808 B |
| Encrypt · AES-256-CCM (CryptoHives-AES-NI) | 128KB | 334,240.8 ns | 628.48 ns | 557.13 ns | - |
| Encrypt · AES-256-CCM (CryptoHives-Scalar) | 128KB | 1,014,675.2 ns | 2,672.90 ns | 2,369.45 ns | - |
| Encrypt · AES-256-CCM (BouncyCastle) | 128KB | 1,219,478.3 ns | 2,980.67 ns | 3,548.28 ns | 2848 B |
ChaCha20-Poly1305
ChaCha20-Poly1305 is a software-friendly AEAD cipher (RFC 8439) that combines ChaCha20 stream encryption with Poly1305 MAC authentication. It is the recommended AEAD cipher when hardware AES acceleration is unavailable. Three acceleration tiers are available:
- AVX2: Dual-block ChaCha20 encryption via
Vector256<uint>, combined with Poly1305 donna-64 MAC (3×44-bit limbs, 9 multiplications per 16-byte block usingMath.BigMul). ~1.53× faster than OS at 128 KiB. - SSSE3: Single-block ChaCha20 via
Vector128<uint>with the same Poly1305 donna-64 MAC. ~6.5% faster than OS at 128 KiB. - Managed: Scalar ChaCha20 + Poly1305 donna-32 (5×26-bit limbs, 25 multiplications per block on .NET Framework / .NET Standard). Fully portable.
Key observations:
- AVX2 ~35% faster than OS at 128 KiB; SSSE3 ~6.5% faster than OS
- At smaller sizes (128 B), OS is competitive due to lower per-call overhead
- Managed, SSSE3, and AVX2 paths are zero-allocation
- BouncyCastle allocates 336–416 B per call; NaCl.Core allocates 48–72 B per call
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 128B | 338.0 ns | 0.78 ns | 0.69 ns | - |
| Decrypt · ChaCha20-Poly1305 (OS) | 128B | 345.8 ns | 0.38 ns | 0.34 ns | - |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 128B | 398.2 ns | 0.61 ns | 0.54 ns | - |
| Decrypt · ChaCha20-Poly1305 (NaCl.Core) | 128B | 579.4 ns | 1.40 ns | 1.31 ns | 48 B |
| Decrypt · ChaCha20-Poly1305 (BouncyCastle) | 128B | 721.9 ns | 0.99 ns | 0.83 ns | 416 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 128B | 892.7 ns | 0.86 ns | 0.77 ns | - |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 128B | 297.2 ns | 0.36 ns | 0.32 ns | - |
| Encrypt · ChaCha20-Poly1305 (OS) | 128B | 345.8 ns | 0.65 ns | 0.58 ns | - |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 128B | 354.0 ns | 0.53 ns | 0.44 ns | - |
| Encrypt · ChaCha20-Poly1305 (BouncyCastle) | 128B | 424.5 ns | 0.62 ns | 0.52 ns | 336 B |
| Encrypt · ChaCha20-Poly1305 (NaCl.Core) | 128B | 541.3 ns | 1.34 ns | 1.19 ns | 48 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 128B | 849.0 ns | 2.07 ns | 1.83 ns | - |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 1KB | 1,265.7 ns | 1.06 ns | 0.88 ns | - |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 1KB | 1,720.7 ns | 1.34 ns | 1.12 ns | - |
| Decrypt · ChaCha20-Poly1305 (BouncyCastle) | 1KB | 1,721.4 ns | 3.07 ns | 2.87 ns | 416 B |
| Decrypt · ChaCha20-Poly1305 (OS) | 1KB | 1,751.1 ns | 2.92 ns | 2.44 ns | - |
| Decrypt · ChaCha20-Poly1305 (NaCl.Core) | 1KB | 2,566.5 ns | 3.86 ns | 3.42 ns | 72 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 1KB | 4,561.5 ns | 5.00 ns | 4.43 ns | - |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 1KB | 1,216.8 ns | 2.65 ns | 2.35 ns | - |
| Encrypt · ChaCha20-Poly1305 (BouncyCastle) | 1KB | 1,424.8 ns | 3.09 ns | 2.89 ns | 336 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 1KB | 1,672.3 ns | 2.94 ns | 2.61 ns | - |
| Encrypt · ChaCha20-Poly1305 (OS) | 1KB | 1,749.5 ns | 1.24 ns | 1.10 ns | - |
| Encrypt · ChaCha20-Poly1305 (NaCl.Core) | 1KB | 2,514.2 ns | 4.34 ns | 3.63 ns | 72 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 1KB | 4,499.4 ns | 9.28 ns | 8.22 ns | - |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 8KB | 8,742.8 ns | 15.60 ns | 14.59 ns | - |
| Decrypt · ChaCha20-Poly1305 (BouncyCastle) | 8KB | 9,643.1 ns | 26.63 ns | 22.24 ns | 416 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 8KB | 12,360.9 ns | 12.34 ns | 10.31 ns | - |
| Decrypt · ChaCha20-Poly1305 (OS) | 8KB | 13,030.5 ns | 80.19 ns | 66.96 ns | - |
| Decrypt · ChaCha20-Poly1305 (NaCl.Core) | 8KB | 18,375.1 ns | 47.47 ns | 44.40 ns | 72 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 8KB | 33,889.7 ns | 49.10 ns | 43.53 ns | - |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 8KB | 8,697.3 ns | 8.99 ns | 7.02 ns | - |
| Encrypt · ChaCha20-Poly1305 (BouncyCastle) | 8KB | 9,455.2 ns | 25.22 ns | 23.59 ns | 336 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 8KB | 12,336.5 ns | 17.77 ns | 16.62 ns | - |
| Encrypt · ChaCha20-Poly1305 (OS) | 8KB | 12,961.4 ns | 8.55 ns | 7.14 ns | - |
| Encrypt · ChaCha20-Poly1305 (NaCl.Core) | 8KB | 18,275.4 ns | 49.21 ns | 43.62 ns | 72 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 8KB | 33,786.7 ns | 34.05 ns | 30.18 ns | - |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 128KB | 136,820.5 ns | 231.75 ns | 205.44 ns | - |
| Decrypt · ChaCha20-Poly1305 (BouncyCastle) | 128KB | 148,013.6 ns | 216.92 ns | 181.14 ns | 416 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 128KB | 194,703.5 ns | 330.69 ns | 293.14 ns | - |
| Decrypt · ChaCha20-Poly1305 (OS) | 128KB | 205,388.9 ns | 164.56 ns | 153.93 ns | - |
| Decrypt · ChaCha20-Poly1305 (NaCl.Core) | 128KB | 295,118.7 ns | 742.13 ns | 694.19 ns | 72 B |
| Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 128KB | 536,341.7 ns | 660.56 ns | 617.89 ns | - |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-AVX2) | 128KB | 136,528.2 ns | 348.46 ns | 325.95 ns | - |
| Encrypt · ChaCha20-Poly1305 (BouncyCastle) | 128KB | 149,583.8 ns | 184.12 ns | 143.75 ns | 336 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-SSSE3) | 128KB | 194,357.2 ns | 376.34 ns | 333.62 ns | - |
| Encrypt · ChaCha20-Poly1305 (OS) | 128KB | 205,550.4 ns | 412.50 ns | 385.85 ns | - |
| Encrypt · ChaCha20-Poly1305 (NaCl.Core) | 128KB | 290,186.7 ns | 1,190.92 ns | 994.47 ns | 72 B |
| Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) | 128KB | 536,618.9 ns | 359.05 ns | 280.32 ns | - |
XChaCha20-Poly1305
XChaCha20-Poly1305 extends ChaCha20-Poly1305 with a 24-byte nonce (vs 12 bytes), making random nonce generation safe against collisions (2⁹² birthday bound vs 2³² for ChaCha20-Poly1305). The implementation prepends an HChaCha20 key derivation step that derives a subkey from the first 16 bytes of the nonce. The same AVX2 / SSSE3 / Managed acceleration tiers apply to the inner ChaCha20-Poly1305 operation.
Key observations:
- Performance nearly identical to ChaCha20-Poly1305 (HChaCha20 adds ~200 ns constant overhead)
- No OS or BouncyCastle implementations available for comparison
- NaCl.Core allocates 48–72 B per call
- Managed, SSSE3, and AVX2 paths are zero-allocation
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 128B | 561.5 ns | 0.44 ns | 0.37 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 128B | 627.3 ns | 0.60 ns | 0.50 ns | - |
| Decrypt · XChaCha20-Poly1305 (NaCl.Core) | 128B | 912.1 ns | 1.07 ns | 0.95 ns | 48 B |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 128B | 1,121.4 ns | 2.29 ns | 2.03 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 128B | 509.2 ns | 0.77 ns | 0.69 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 128B | 583.3 ns | 1.00 ns | 0.93 ns | - |
| Encrypt · XChaCha20-Poly1305 (NaCl.Core) | 128B | 871.9 ns | 1.67 ns | 1.48 ns | 48 B |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 128B | 1,078.7 ns | 1.13 ns | 0.94 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 1KB | 1,495.5 ns | 2.71 ns | 2.54 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 1KB | 1,947.1 ns | 5.18 ns | 4.59 ns | - |
| Decrypt · XChaCha20-Poly1305 (NaCl.Core) | 1KB | 4,082.9 ns | 10.98 ns | 10.27 ns | 72 B |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 1KB | 4,796.5 ns | 13.78 ns | 12.89 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 1KB | 1,451.3 ns | 2.45 ns | 1.91 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 1KB | 1,902.6 ns | 3.39 ns | 2.64 ns | - |
| Encrypt · XChaCha20-Poly1305 (NaCl.Core) | 1KB | 4,039.0 ns | 19.62 ns | 17.39 ns | 72 B |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 1KB | 4,768.0 ns | 9.61 ns | 8.52 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 8KB | 8,975.9 ns | 11.51 ns | 10.20 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 8KB | 12,615.6 ns | 17.26 ns | 16.14 ns | - |
| Decrypt · XChaCha20-Poly1305 (NaCl.Core) | 8KB | 29,297.7 ns | 69.06 ns | 64.60 ns | 72 B |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 8KB | 34,340.1 ns | 51.36 ns | 45.53 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 8KB | 8,926.9 ns | 13.06 ns | 11.57 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 8KB | 12,549.0 ns | 25.91 ns | 22.97 ns | - |
| Encrypt · XChaCha20-Poly1305 (NaCl.Core) | 8KB | 29,033.4 ns | 39.45 ns | 32.94 ns | 72 B |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 8KB | 34,162.4 ns | 33.25 ns | 31.10 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 128KB | 137,509.7 ns | 174.43 ns | 154.62 ns | - |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 128KB | 195,040.1 ns | 197.63 ns | 165.03 ns | - |
| Decrypt · XChaCha20-Poly1305 (NaCl.Core) | 128KB | 463,772.7 ns | 701.71 ns | 622.04 ns | 72 B |
| Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 128KB | 539,500.8 ns | 695.45 ns | 616.50 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-AVX2) | 128KB | 137,591.1 ns | 223.36 ns | 198.00 ns | - |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-SSSE3) | 128KB | 194,991.9 ns | 286.67 ns | 254.12 ns | - |
| Encrypt · XChaCha20-Poly1305 (NaCl.Core) | 128KB | 458,852.0 ns | 776.69 ns | 688.51 ns | 72 B |
| Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) | 128KB | 539,116.8 ns | 702.43 ns | 657.06 ns | - |
Regional Block Ciphers
Regional block ciphers implement national cryptographic standards. All operate on 128-bit blocks in CBC mode. Benchmarks compare Managed implementations against BouncyCastle where available.
SM4-CBC (China)
SM4 is the Chinese national block cipher (GB/T 32907-2016). It uses a 128-bit key with 32 rounds of nonlinear key mixing.
- Managed: Lookup-table implementation with 32-bit word operations. Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · SM4-CBC (CryptoHives-Scalar) | 128B | 817.3 ns | 1.31 ns | 1.16 ns | - |
| Decrypt · SM4-CBC (BouncyCastle) | 128B | 1,303.7 ns | 5.11 ns | 4.27 ns | 40 B |
| Encrypt · SM4-CBC (CryptoHives-Scalar) | 128B | 871.9 ns | 0.80 ns | 0.71 ns | - |
| Encrypt · SM4-CBC (BouncyCastle) | 128B | 1,314.6 ns | 1.82 ns | 1.70 ns | 40 B |
| Decrypt · SM4-CBC (CryptoHives-Scalar) | 1KB | 5,805.4 ns | 8.52 ns | 7.12 ns | - |
| Decrypt · SM4-CBC (BouncyCastle) | 1KB | 8,205.3 ns | 17.46 ns | 15.47 ns | 40 B |
| Encrypt · SM4-CBC (CryptoHives-Scalar) | 1KB | 6,233.3 ns | 11.37 ns | 10.08 ns | - |
| Encrypt · SM4-CBC (BouncyCastle) | 1KB | 8,342.4 ns | 8.84 ns | 7.38 ns | 40 B |
| Decrypt · SM4-CBC (CryptoHives-Scalar) | 8KB | 45,685.6 ns | 73.29 ns | 64.97 ns | - |
| Decrypt · SM4-CBC (BouncyCastle) | 8KB | 63,440.4 ns | 121.66 ns | 107.84 ns | 40 B |
| Encrypt · SM4-CBC (CryptoHives-Scalar) | 8KB | 49,100.0 ns | 90.69 ns | 84.83 ns | - |
| Encrypt · SM4-CBC (BouncyCastle) | 8KB | 64,509.4 ns | 109.14 ns | 96.75 ns | 40 B |
| Decrypt · SM4-CBC (CryptoHives-Scalar) | 128KB | 727,746.9 ns | 970.63 ns | 860.44 ns | - |
| Decrypt · SM4-CBC (BouncyCastle) | 128KB | 1,005,229.8 ns | 1,246.91 ns | 1,041.23 ns | 40 B |
| Encrypt · SM4-CBC (CryptoHives-Scalar) | 128KB | 784,189.1 ns | 1,390.73 ns | 1,300.89 ns | - |
| Encrypt · SM4-CBC (BouncyCastle) | 128KB | 1,026,462.0 ns | 2,253.74 ns | 2,108.15 ns | 40 B |
ARIA-128-CBC (Korea)
ARIA is a Korean national cipher (KS X 1213) with an involutional SPN structure. ARIA-128 uses 12 rounds.
- Managed: S-box substitution with byte-level diffusion layer. Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Median | Allocated |
|---|---|---|---|---|---|---|
| Decrypt · ARIA-128-CBC (CryptoHives-Scalar) | 128B | 1.480 μs | 0.0050 μs | 0.0044 μs | 1.480 μs | - |
| Decrypt · ARIA-128-CBC (BouncyCastle) | 128B | 2.587 μs | 0.0038 μs | 0.0034 μs | 2.587 μs | 1288 B |
| Encrypt · ARIA-128-CBC (CryptoHives-Scalar) | 128B | 1.503 μs | 0.0158 μs | 0.0280 μs | 1.489 μs | - |
| Encrypt · ARIA-128-CBC (BouncyCastle) | 128B | 2.395 μs | 0.0049 μs | 0.0046 μs | 2.396 μs | 1288 B |
| Decrypt · ARIA-128-CBC (CryptoHives-Scalar) | 1KB | 10.607 μs | 0.0172 μs | 0.0144 μs | 10.605 μs | - |
| Decrypt · ARIA-128-CBC (BouncyCastle) | 1KB | 15.412 μs | 0.0470 μs | 0.0440 μs | 15.405 μs | 3528 B |
| Encrypt · ARIA-128-CBC (CryptoHives-Scalar) | 1KB | 10.656 μs | 0.0220 μs | 0.0206 μs | 10.656 μs | - |
| Encrypt · ARIA-128-CBC (BouncyCastle) | 1KB | 15.449 μs | 0.0170 μs | 0.0142 μs | 15.447 μs | 3528 B |
| Decrypt · ARIA-128-CBC (CryptoHives-Scalar) | 8KB | 83.686 μs | 0.1391 μs | 0.1233 μs | 83.671 μs | - |
| Decrypt · ARIA-128-CBC (BouncyCastle) | 8KB | 118.785 μs | 0.1506 μs | 0.1257 μs | 118.777 μs | 21448 B |
| Encrypt · ARIA-128-CBC (CryptoHives-Scalar) | 8KB | 83.098 μs | 0.0940 μs | 0.0734 μs | 83.093 μs | - |
| Encrypt · ARIA-128-CBC (BouncyCastle) | 8KB | 122.575 μs | 0.3250 μs | 0.2881 μs | 122.520 μs | 21448 B |
| Decrypt · ARIA-128-CBC (CryptoHives-Scalar) | 128KB | 1,335.802 μs | 2.8293 μs | 2.5081 μs | 1,335.501 μs | - |
| Decrypt · ARIA-128-CBC (BouncyCastle) | 128KB | 1,894.525 μs | 1.7955 μs | 1.5917 μs | 1,894.395 μs | 328648 B |
| Encrypt · ARIA-128-CBC (CryptoHives-Scalar) | 128KB | 1,327.938 μs | 2.1681 μs | 2.0281 μs | 1,327.733 μs | - |
| Encrypt · ARIA-128-CBC (BouncyCastle) | 128KB | 1,914.929 μs | 2.1421 μs | 1.7888 μs | 1,915.559 μs | 328648 B |
ARIA-256-CBC (Korea)
ARIA-256 uses 16 rounds for 256-bit key security. The same SPN structure applies with additional rounds.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · ARIA-256-CBC (CryptoHives-Scalar) | 128B | 1.931 μs | 0.0051 μs | 0.0046 μs | - |
| Decrypt · ARIA-256-CBC (BouncyCastle) | 128B | 3.331 μs | 0.0047 μs | 0.0042 μs | 1496 B |
| Encrypt · ARIA-256-CBC (CryptoHives-Scalar) | 128B | 1.925 μs | 0.0027 μs | 0.0024 μs | - |
| Encrypt · ARIA-256-CBC (BouncyCastle) | 128B | 3.118 μs | 0.0083 μs | 0.0065 μs | 1496 B |
| Decrypt · ARIA-256-CBC (CryptoHives-Scalar) | 1KB | 13.850 μs | 0.0372 μs | 0.0330 μs | - |
| Decrypt · ARIA-256-CBC (BouncyCastle) | 1KB | 20.354 μs | 0.0779 μs | 0.0650 μs | 3736 B |
| Encrypt · ARIA-256-CBC (CryptoHives-Scalar) | 1KB | 13.877 μs | 0.0237 μs | 0.0198 μs | - |
| Encrypt · ARIA-256-CBC (BouncyCastle) | 1KB | 20.349 μs | 0.0390 μs | 0.0346 μs | 3736 B |
| Decrypt · ARIA-256-CBC (CryptoHives-Scalar) | 8KB | 108.874 μs | 0.2079 μs | 0.1843 μs | - |
| Decrypt · ARIA-256-CBC (BouncyCastle) | 8KB | 156.986 μs | 0.4342 μs | 0.3849 μs | 21656 B |
| Encrypt · ARIA-256-CBC (CryptoHives-Scalar) | 8KB | 108.869 μs | 0.3092 μs | 0.2414 μs | - |
| Encrypt · ARIA-256-CBC (BouncyCastle) | 8KB | 159.121 μs | 0.2537 μs | 0.2249 μs | 21656 B |
| Decrypt · ARIA-256-CBC (CryptoHives-Scalar) | 128KB | 1,744.593 μs | 4.7876 μs | 4.4783 μs | - |
| Decrypt · ARIA-256-CBC (BouncyCastle) | 128KB | 2,493.428 μs | 4.1157 μs | 3.6484 μs | 328856 B |
| Encrypt · ARIA-256-CBC (CryptoHives-Scalar) | 128KB | 1,742.158 μs | 5.4415 μs | 5.0900 μs | - |
| Encrypt · ARIA-256-CBC (BouncyCastle) | 128KB | 2,540.042 μs | 3.8058 μs | 3.3737 μs | 328856 B |
Camellia-128-CBC (Japan)
Camellia is a Japanese CRYPTREC/NESSIE cipher (RFC 3713) with a Feistel structure and FL/FL⁻¹ key-dependent layers.
- Managed: Pre-computed SP-box tables with 6 S-boxes. Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · Camellia-128-CBC (CryptoHives-Scalar) | 128B | 572.1 ns | 3.05 ns | 2.54 ns | - |
| Decrypt · Camellia-128-CBC (BouncyCastle) | 128B | 1,059.4 ns | 1.80 ns | 1.51 ns | 576 B |
| Encrypt · Camellia-128-CBC (CryptoHives-Scalar) | 128B | 609.1 ns | 0.74 ns | 0.65 ns | - |
| Encrypt · Camellia-128-CBC (BouncyCastle) | 128B | 1,031.0 ns | 1.18 ns | 0.98 ns | 576 B |
| Decrypt · Camellia-128-CBC (CryptoHives-Scalar) | 1KB | 4,071.7 ns | 4.21 ns | 3.51 ns | - |
| Decrypt · Camellia-128-CBC (BouncyCastle) | 1KB | 6,771.5 ns | 8.97 ns | 7.49 ns | 2816 B |
| Encrypt · Camellia-128-CBC (CryptoHives-Scalar) | 1KB | 4,261.9 ns | 7.83 ns | 6.11 ns | - |
| Encrypt · Camellia-128-CBC (BouncyCastle) | 1KB | 6,701.1 ns | 7.49 ns | 7.00 ns | 2816 B |
| Decrypt · Camellia-128-CBC (CryptoHives-Scalar) | 8KB | 32,642.9 ns | 42.31 ns | 37.51 ns | - |
| Decrypt · Camellia-128-CBC (BouncyCastle) | 8KB | 52,593.0 ns | 85.84 ns | 71.68 ns | 20736 B |
| Encrypt · Camellia-128-CBC (CryptoHives-Scalar) | 8KB | 33,687.6 ns | 68.51 ns | 57.21 ns | - |
| Encrypt · Camellia-128-CBC (BouncyCastle) | 8KB | 52,035.0 ns | 124.37 ns | 103.86 ns | 20736 B |
| Decrypt · Camellia-128-CBC (CryptoHives-Scalar) | 128KB | 527,990.4 ns | 634.18 ns | 593.21 ns | - |
| Decrypt · Camellia-128-CBC (BouncyCastle) | 128KB | 838,826.8 ns | 1,491.24 ns | 1,245.26 ns | 327936 B |
| Encrypt · Camellia-128-CBC (CryptoHives-Scalar) | 128KB | 535,373.5 ns | 592.31 ns | 525.07 ns | - |
| Encrypt · Camellia-128-CBC (BouncyCastle) | 128KB | 830,353.8 ns | 1,370.91 ns | 1,144.77 ns | 327936 B |
Camellia-256-CBC (Japan)
Camellia-256 uses 24 rounds (vs 18 for 128-bit). The additional FL/FL⁻¹ layers add minimal overhead.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · Camellia-256-CBC (CryptoHives-Scalar) | 128B | 763.4 ns | 0.48 ns | 0.40 ns | - |
| Decrypt · Camellia-256-CBC (BouncyCastle) | 128B | 1,267.2 ns | 1.64 ns | 1.37 ns | 592 B |
| Encrypt · Camellia-256-CBC (CryptoHives-Scalar) | 128B | 815.7 ns | 1.05 ns | 0.93 ns | - |
| Encrypt · Camellia-256-CBC (BouncyCastle) | 128B | 1,306.7 ns | 1.42 ns | 1.26 ns | 592 B |
| Decrypt · Camellia-256-CBC (CryptoHives-Scalar) | 1KB | 5,349.4 ns | 8.27 ns | 7.33 ns | - |
| Decrypt · Camellia-256-CBC (BouncyCastle) | 1KB | 8,386.7 ns | 12.94 ns | 10.80 ns | 2832 B |
| Encrypt · Camellia-256-CBC (CryptoHives-Scalar) | 1KB | 5,708.9 ns | 8.03 ns | 7.12 ns | - |
| Encrypt · Camellia-256-CBC (BouncyCastle) | 1KB | 8,284.2 ns | 9.56 ns | 8.94 ns | 2832 B |
| Decrypt · Camellia-256-CBC (CryptoHives-Scalar) | 8KB | 43,093.4 ns | 52.50 ns | 46.54 ns | - |
| Decrypt · Camellia-256-CBC (BouncyCastle) | 8KB | 65,804.9 ns | 169.67 ns | 141.68 ns | 20752 B |
| Encrypt · Camellia-256-CBC (CryptoHives-Scalar) | 8KB | 44,978.7 ns | 116.48 ns | 108.96 ns | - |
| Encrypt · Camellia-256-CBC (BouncyCastle) | 8KB | 66,098.2 ns | 102.88 ns | 85.91 ns | 20752 B |
| Decrypt · Camellia-256-CBC (CryptoHives-Scalar) | 128KB | 700,271.0 ns | 1,685.08 ns | 1,493.78 ns | - |
| Decrypt · Camellia-256-CBC (BouncyCastle) | 128KB | 1,051,202.3 ns | 2,110.87 ns | 1,871.24 ns | 327952 B |
| Encrypt · Camellia-256-CBC (CryptoHives-Scalar) | 128KB | 728,863.9 ns | 1,232.06 ns | 1,092.18 ns | - |
| Encrypt · Camellia-256-CBC (BouncyCastle) | 128KB | 1,033,551.0 ns | 2,375.47 ns | 2,105.79 ns | 327952 B |
Kuznyechik-CBC (Russia)
Kuznyechik (GOST R 34.12-2015) is the modern Russian cipher with a 256-bit key and 10 rounds. It replaces the older GOST 28147-89.
- Managed: Pre-computed S-box and linear transformation tables. Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 128B | 406.9 μs | 1.04 μs | 0.97 μs | - |
| Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 128B | 425.8 μs | 2.55 μs | 2.26 μs | - |
| Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 1KB | 3,164.5 μs | 17.73 μs | 16.59 μs | - |
| Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 1KB | 3,115.5 μs | 7.93 μs | 7.42 μs | - |
| Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 8KB | 24,817.0 μs | 179.33 μs | 158.97 μs | - |
| Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 8KB | 24,976.8 μs | 109.57 μs | 102.50 μs | - |
| Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 128KB | 396,979.4 μs | 2,688.72 μs | 2,383.48 μs | - |
| Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) | 128KB | 395,530.5 μs | 1,779.83 μs | 1,577.78 μs | - |
Kalyna-128-CBC (Ukraine)
Kalyna (DSTU 7624:2014) is the Ukrainian national cipher paired with the Kupyna hash family. Uses MDS matrix diffusion.
- Managed: S-box substitution with MDS matrix multiplication. Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 128B | 933.8 ns | 1.32 ns | 1.17 ns | - |
| Decrypt · Kalyna-128-CBC (BouncyCastle) | 128B | 2,461.0 ns | 6.82 ns | 6.04 ns | 872 B |
| Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 128B | 407.2 ns | 0.61 ns | 0.54 ns | - |
| Encrypt · Kalyna-128-CBC (BouncyCastle) | 128B | 1,374.2 ns | 3.91 ns | 3.26 ns | 872 B |
| Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 1KB | 6,635.1 ns | 5.87 ns | 5.49 ns | - |
| Decrypt · Kalyna-128-CBC (BouncyCastle) | 1KB | 14,855.9 ns | 22.05 ns | 19.54 ns | 872 B |
| Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 1KB | 2,821.9 ns | 6.11 ns | 5.10 ns | - |
| Encrypt · Kalyna-128-CBC (BouncyCastle) | 1KB | 7,208.9 ns | 9.57 ns | 7.99 ns | 872 B |
| Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 8KB | 52,478.9 ns | 71.54 ns | 55.85 ns | - |
| Decrypt · Kalyna-128-CBC (BouncyCastle) | 8KB | 113,068.6 ns | 221.71 ns | 196.54 ns | 872 B |
| Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 8KB | 22,032.9 ns | 17.96 ns | 15.00 ns | - |
| Encrypt · Kalyna-128-CBC (BouncyCastle) | 8KB | 53,799.7 ns | 103.36 ns | 91.62 ns | 872 B |
| Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 128KB | 835,971.6 ns | 1,014.67 ns | 847.29 ns | - |
| Decrypt · Kalyna-128-CBC (BouncyCastle) | 128KB | 1,801,318.7 ns | 3,535.37 ns | 2,952.19 ns | 872 B |
| Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) | 128KB | 353,480.4 ns | 452.41 ns | 401.05 ns | - |
| Encrypt · Kalyna-128-CBC (BouncyCastle) | 128KB | 851,175.7 ns | 1,023.60 ns | 907.40 ns | 872 B |
Kalyna-256-CBC (Ukraine)
Kalyna-256 uses 14 rounds (vs 10 for 128-bit key). The same MDS-based architecture applies.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 128B | 1,270.8 ns | 2.72 ns | 2.41 ns | - |
| Decrypt · Kalyna-256-CBC (BouncyCastle) | 128B | 3,256.7 ns | 5.23 ns | 4.89 ns | 1112 B |
| Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 128B | 555.3 ns | 1.45 ns | 1.36 ns | - |
| Encrypt · Kalyna-256-CBC (BouncyCastle) | 128B | 1,772.6 ns | 3.45 ns | 3.22 ns | 1112 B |
| Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 1KB | 9,106.9 ns | 17.18 ns | 14.35 ns | - |
| Decrypt · Kalyna-256-CBC (BouncyCastle) | 1KB | 20,134.7 ns | 43.75 ns | 40.92 ns | 1112 B |
| Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 1KB | 3,909.5 ns | 7.99 ns | 7.08 ns | - |
| Encrypt · Kalyna-256-CBC (BouncyCastle) | 1KB | 9,610.5 ns | 19.66 ns | 17.43 ns | 1112 B |
| Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 8KB | 71,420.0 ns | 109.93 ns | 97.45 ns | - |
| Decrypt · Kalyna-256-CBC (BouncyCastle) | 8KB | 155,555.3 ns | 377.70 ns | 334.82 ns | 1112 B |
| Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 8KB | 30,734.0 ns | 42.76 ns | 35.71 ns | - |
| Encrypt · Kalyna-256-CBC (BouncyCastle) | 8KB | 71,946.8 ns | 89.65 ns | 83.86 ns | 1112 B |
| Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 128KB | 1,137,122.7 ns | 1,711.80 ns | 1,429.43 ns | - |
| Decrypt · Kalyna-256-CBC (BouncyCastle) | 128KB | 2,467,322.8 ns | 7,261.35 ns | 5,669.19 ns | 1112 B |
| Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) | 128KB | 490,099.1 ns | 1,084.17 ns | 961.09 ns | - |
| Encrypt · Kalyna-256-CBC (BouncyCastle) | 128KB | 1,145,118.8 ns | 2,679.18 ns | 2,375.02 ns | 1112 B |
SEED-CBC (Korea)
SEED is a Korean cipher (RFC 4269, KISA) with a 128-bit key and 16-round Feistel structure. S-boxes are derived from the golden ratio.
- Managed: Pre-computed 32-bit SS-boxes (SS0–SS3). Zero allocation.
| Description | TestDataSize | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|---|
| Decrypt · SEED-CBC (CryptoHives-Scalar) | 128B | 1.172 μs | 0.0011 μs | 0.0010 μs | - |
| Decrypt · SEED-CBC (BouncyCastle) | 128B | 1.301 μs | 0.0015 μs | 0.0014 μs | 152 B |
| Encrypt · SEED-CBC (CryptoHives-Scalar) | 128B | 1.172 μs | 0.0033 μs | 0.0031 μs | - |
| Encrypt · SEED-CBC (BouncyCastle) | 128B | 1.299 μs | 0.0018 μs | 0.0015 μs | 152 B |
| Decrypt · SEED-CBC (CryptoHives-Scalar) | 1KB | 8.297 μs | 0.0105 μs | 0.0082 μs | - |
| Decrypt · SEED-CBC (BouncyCastle) | 1KB | 8.775 μs | 0.0155 μs | 0.0138 μs | 152 B |
| Encrypt · SEED-CBC (CryptoHives-Scalar) | 1KB | 8.391 μs | 0.0244 μs | 0.0216 μs | - |
| Encrypt · SEED-CBC (BouncyCastle) | 1KB | 8.839 μs | 0.0168 μs | 0.0149 μs | 152 B |
| Decrypt · SEED-CBC (CryptoHives-Scalar) | 8KB | 65.332 μs | 0.0791 μs | 0.0740 μs | - |
| Decrypt · SEED-CBC (BouncyCastle) | 8KB | 68.672 μs | 0.1475 μs | 0.1379 μs | 152 B |
| Encrypt · SEED-CBC (CryptoHives-Scalar) | 8KB | 66.188 μs | 0.1036 μs | 0.0969 μs | - |
| Encrypt · SEED-CBC (BouncyCastle) | 8KB | 69.140 μs | 0.0993 μs | 0.0880 μs | 152 B |
| Decrypt · SEED-CBC (CryptoHives-Scalar) | 128KB | 1,044.445 μs | 1.3474 μs | 1.2603 μs | - |
| Decrypt · SEED-CBC (BouncyCastle) | 128KB | 1,108.726 μs | 3.9076 μs | 3.6552 μs | 152 B |
| Encrypt · SEED-CBC (CryptoHives-Scalar) | 128KB | 1,053.903 μs | 1.2117 μs | 1.0742 μs | - |
| Encrypt · SEED-CBC (BouncyCastle) | 128KB | 1,107.289 μs | 3.6531 μs | 3.4171 μs | 152 B |
Allocation Summary
All CryptoHives cipher implementations achieve zero heap allocation for both encrypt and decrypt operations across all payload sizes. This is critical for high-throughput scenarios such as network packet processing, where GC pressure directly impacts tail latency.
| Implementation | Allocation | Notes |
|---|---|---|
| CryptoHives (all variants) | 0 B | All tiers (Managed, AES-NI, PClMul, V256, SSSE3, AVX2) are zero-allocation at all payload sizes |
| OS (.NET) — GCM / ChaCha20-Poly1305 | 0 B | OS AEAD implementations are zero-allocation |
| OS (.NET) — CBC | 128 B | Fixed P/Invoke marshalling overhead per call, independent of payload size |
| BouncyCastle — CBC | 832–1,024 B | Fixed per-call allocation (832 B for AES-128, 1,024 B for AES-256) |
| BouncyCastle — GCM | 1,608–1,832 B | Fixed per-call allocation (1,608 B for AES-128, 1,832 B for AES-256) |
| BouncyCastle — CCM | 2,424–2,848 B | Fixed per-call allocation (2,424 B for AES-128, 2,848 B for AES-256) |
| BouncyCastle — ChaCha20-Poly1305 | 336–416 B | Varies slightly by payload size |
| BouncyCastle — ChaCha20 | 96 B | Fixed per-call allocation |
| NaCl.Core — ChaCha20 | 24 B | Small fixed allocation |
| NaCl.Core — ChaCha20-Poly1305 / XChaCha20 | 48–72 B | Small allocation, varies by payload size |