Table of Contents

macOS Arm64 Apple M4 Cipher Benchmarks

Machine Profile

Machine Specification

The benchmarks were run on the following machine:

BenchmarkDotNet v0.15.8, macOS Tahoe 26.4.1 (25E253) [Darwin 25.4.0]
Apple M4, 1 CPU, 10 logical and 10 physical cores
.NET SDK 10.0.301
[Host]    : .NET 10.0.9 (10.0.9, 10.0.926.27113), Arm64 RyuJIT armv8.0-a
.NET 10.0 : .NET 10.0.9 (10.0.9, 10.0.926.27113), Arm64 RyuJIT armv8.0-a
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 ARM Crypto support T-table AES using scalar uint arithmetic. Fully portable, zero-allocation. ~10–16× slower than ArmAes depending on mode and payload size.
ArmAes AES (ARM Crypto Ext.) .NET 8+ ArmBase.IsSupported Hardware AES round instructions (AESD, AESE, AESMC, AESIMC). For CBC, uses 8-block interleaved decrypt for maximum instruction-level parallelism — all 8 plaintext blocks decoded simultaneously via parallel AESD dispatch. For GCM/CCM, accelerates counter-mode encryption and CBC-MAC. Decrypt is ~5.8× faster than OS at 128 B; at bulk sizes Apple CommonCrypto leads via Apple Silicon–specific AES pipelining.
ArmAes+ArmPmull AES + PMULL (ARM Crypto Ext.) .NET 8+ AdvSimd.Arm64.IsSupported Adds carry-less polynomial multiplication (PMULL/PMULL2) for hardware-accelerated GHASH over GF(2¹²⁸). PMULL operates on 64-bit polynomial operands to produce 128-bit products; PMULL2 reads from the upper halves of 128-bit NEON registers (a free lane-select requiring no additional instruction). Uses the same 8-block stitched AES+GHASH pipeline as the x86 PClMul path. Modular reduction uses a 2-PMULL SymCrypt-style MODREDUCE. Pre-computes Karatsuba cross-term halves for H¹–H⁸ powers. Encrypt: ~120× faster than OS at 17 B; ~14× at 128 B (OS CommonCrypto incurs ~8 μs per-call overhead at these sizes). OS leads at ≥8 KiB due to Apple Silicon–specific bulk AES acceleration.

ChaCha20 Family

Variant Instructions .NET Target When Selected Description
Managed Scalar All No NEON support Quarter-round operations using scalar uint arithmetic. Fully portable. ~4× slower than Neon at all payload sizes.
Neon AdvSIMD (NEON) .NET 8+ AdvSimd.IsSupported Maps the 4×4 ChaCha state to four Vector128<uint> rows. Uses ARM NEON shift-left, shift-right, and byte-table permute instructions for the 16-bit, 12-bit, 8-bit, and 7-bit rotations. Diagonal rounds use AdvSimd.ExtractVector128 to rotate rows by one element. Processes one 64-byte keystream block per iteration. ~4× faster than Managed; faster than BouncyCastle at all sizes up to 1 KiB; OS leads from ~8 KiB.

When to Use Each Variant

  • Small messages (≤256 B): AES-GCM with ArmAes+ArmPmull eliminates the ~8 μs CommonCrypto per-call overhead entirely — ~120× faster than OS at 17 B encrypt and ~14× at 128 B. ChaCha20-Poly1305 NEON is ~5× faster than OS at 128 B.
  • Medium messages (256 B–4 KB): ArmAes+ArmPmull leads through ~1 KiB. ChaCha20-Poly1305 NEON remains competitive at 1 KiB (~1.4× faster than OS). This range covers QUIC (~1.4 KB), WireGuard (~1.4 KB), and IPsec packets.
  • Large messages (8 KB–128 KB): Apple CommonCrypto dominates — OS is ~2× faster for AES-GCM and ~1.54× faster for ChaCha20-Poly1305. This is due to Apple Silicon–specific AES/PMULL micro-architectural pipelining that .NET's current ARMv8 paths do not yet fully exploit. This range covers TLS records (1–16 KB) and OPC UA chunks (8 KB default).
  • No hardware AES: Use ChaCha20-Poly1305 NEON — it outperforms Managed AES-GCM by 3–10× depending on payload size and is always zero-allocation.
  • IoT / constrained devices: AES-CCM with ArmAes provides ~4× speedup over BouncyCastle at 128 KiB. Supports variable nonce (7–13 bytes) and tag sizes.

Highlights

Family Leader Key Insight
ChaCha20 Neon NEON ~4× faster than Managed; faster than BouncyCastle at all sizes up to 1 KiB; zero allocation
ChaCha20-Poly1305 Neon ~5× faster than OS at 128 B; OS leads at ≥8 KiB; Neon on par with BouncyCastle at 128 KiB; zero allocation
XChaCha20-Poly1305 Neon ~3.3× faster than Managed at 128 KiB; zero allocation
AES-CBC ArmAes Decrypt ~5.8× faster than OS at 128 B; OS leads at ≥8 KiB (Apple Silicon bulk path); zero allocation
AES-GCM ArmAes+ArmPmull ~120× faster than OS encrypt at 17 B; ~14× at 128 B; OS leads at ≥8 KiB; 8-block stitched AES+GHASH pipeline
AES-CCM ArmAes ~4× faster than BouncyCastle at 128 KiB; zero allocation; no OS adapter available

Stream Ciphers

ChaCha20

ChaCha20 is a stream cipher designed by Daniel J. Bernstein. Two acceleration tiers are available on ARM:

  • Neon: Single-block processing — maps the 4×4 ChaCha state matrix to four Vector128<uint> rows. Uses ARM NEON vshl/vsri (shift-and-insert) and vtbl (byte-table permute) instructions for the four rotation widths (16-bit, 12-bit, 8-bit, 7-bit). Diagonal rounds use AdvSimd.ExtractVector128 to rotate rows by one element. Yields ~750 MB/s throughput at 128 KiB; ~1.24× faster than BouncyCastle.
  • Managed: Scalar uint quarter-round arithmetic. Fully portable across all .NET targets. ~4.1× slower than Neon at 128 KiB.

Key observations:

  • Neon is the fastest at all sizes; ~1.24× faster than BouncyCastle at 128 KiB; ~1.35× at 1 KiB
  • BouncyCastle allocates 96 B per call; NaCl.Core allocates 24 B per call
  • Managed and Neon paths are zero-allocation
Description TestDataSize Mean Error StdDev Allocated
Decrypt · ChaCha20 (CryptoHives-Neon) 128B 169.8 ns 0.07 ns 0.06 ns -
Decrypt · ChaCha20 (BouncyCastle) 128B 304.8 ns 3.22 ns 3.02 ns 96 B
Decrypt · ChaCha20 (NaCl.Core) 128B 521.1 ns 0.09 ns 0.08 ns 24 B
Decrypt · ChaCha20 (CryptoHives-Scalar) 128B 708.6 ns 2.10 ns 1.96 ns -
Encrypt · ChaCha20 (CryptoHives-Neon) 128B 169.7 ns 0.12 ns 0.10 ns -
Encrypt · ChaCha20 (BouncyCastle) 128B 303.9 ns 4.41 ns 4.12 ns 96 B
Encrypt · ChaCha20 (NaCl.Core) 128B 521.1 ns 0.20 ns 0.15 ns 24 B
Encrypt · ChaCha20 (CryptoHives-Scalar) 128B 708.5 ns 2.08 ns 1.94 ns -
Decrypt · ChaCha20 (CryptoHives-Neon) 1KB 1,337.1 ns 0.40 ns 0.36 ns -
Decrypt · ChaCha20 (BouncyCastle) 1KB 1,826.0 ns 34.56 ns 32.32 ns 96 B
Decrypt · ChaCha20 (NaCl.Core) 1KB 2,935.9 ns 0.72 ns 0.64 ns 24 B
Decrypt · ChaCha20 (CryptoHives-Scalar) 1KB 5,593.2 ns 15.50 ns 14.50 ns -
Encrypt · ChaCha20 (CryptoHives-Neon) 1KB 1,337.3 ns 0.73 ns 0.61 ns -
Encrypt · ChaCha20 (BouncyCastle) 1KB 1,890.4 ns 35.29 ns 37.76 ns 96 B
Encrypt · ChaCha20 (NaCl.Core) 1KB 2,935.8 ns 1.13 ns 1.00 ns 24 B
Encrypt · ChaCha20 (CryptoHives-Scalar) 1KB 5,603.2 ns 12.97 ns 12.13 ns -
Decrypt · ChaCha20 (CryptoHives-Neon) 8KB 10,672.4 ns 7.30 ns 6.47 ns -
Decrypt · ChaCha20 (BouncyCastle) 8KB 13,612.7 ns 208.54 ns 195.07 ns 96 B
Decrypt · ChaCha20 (NaCl.Core) 8KB 22,290.6 ns 23.55 ns 22.03 ns 24 B
Decrypt · ChaCha20 (CryptoHives-Scalar) 8KB 44,682.0 ns 146.71 ns 137.23 ns -
Encrypt · ChaCha20 (CryptoHives-Neon) 8KB 10,673.6 ns 7.05 ns 5.89 ns -
Encrypt · ChaCha20 (BouncyCastle) 8KB 13,594.4 ns 187.00 ns 174.92 ns 96 B
Encrypt · ChaCha20 (NaCl.Core) 8KB 22,278.1 ns 28.81 ns 26.95 ns 24 B
Encrypt · ChaCha20 (CryptoHives-Scalar) 8KB 44,701.9 ns 120.88 ns 100.94 ns -
Decrypt · ChaCha20 (CryptoHives-Neon) 128KB 170,647.8 ns 58.97 ns 52.28 ns -
Decrypt · ChaCha20 (BouncyCastle) 128KB 213,044.1 ns 156.11 ns 146.03 ns 96 B
Decrypt · ChaCha20 (NaCl.Core) 128KB 353,484.2 ns 53.85 ns 47.73 ns 24 B
Decrypt · ChaCha20 (CryptoHives-Scalar) 128KB 715,376.1 ns 1,205.07 ns 1,068.26 ns -
Encrypt · ChaCha20 (CryptoHives-Neon) 128KB 170,542.3 ns 70.32 ns 54.90 ns -
Encrypt · ChaCha20 (BouncyCastle) 128KB 212,602.1 ns 148.61 ns 124.10 ns 96 B
Encrypt · ChaCha20 (NaCl.Core) 128KB 353,402.2 ns 145.97 ns 121.89 ns 24 B
Encrypt · ChaCha20 (CryptoHives-Scalar) 128KB 715,358.5 ns 1,416.82 ns 1,183.10 ns -

Block Ciphers

AES-128-CBC

AES-CBC (Cipher Block Chaining) is the most widely deployed AES mode. Two acceleration tiers are available on Apple M4:

  • ArmAes: Uses ARM Cryptography Extension AESD/AESE/AESMC/AESIMC instructions. Decrypt uses 8-block interleaving — 8 ciphertext blocks are loaded and decrypted simultaneously via parallel AESD dispatch. Each block decrypts independently, requiring only the preceding ciphertext block as an XOR mask (10 rounds × 8 blocks = 80 AESD instructions in flight). Encrypt remains serial because each plaintext block must be XORed with the previous ciphertext before the next AESE can proceed.
  • Managed: T-table AES using four 256-entry lookup tables per round. Fully portable, zero-allocation. Comparable to BouncyCastle at large sizes.

Key observations:

  • ArmAes Decrypt: ~5.8× faster than OS at 128 B; near OS at 4 KiB; OS leads from ~8 KiB (Apple Silicon uses a wider AES pipeline at bulk sizes)
  • ArmAes Encrypt: ~1.5× faster than OS at 128 B; OS leads from 1 KiB (CBC encrypt is inherently serial; CommonCrypto uses NEON-assisted interleaving for partial parallelism)
  • Managed: Zero-allocation T-table AES; comparable to BouncyCastle at large sizes
  • OS: Allocates 72 B per call (P/Invoke marshalling overhead)
Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-128-CBC (CryptoHives-ARM-AES) 128B 23.19 ns 0.007 ns 0.007 ns -
Decrypt · AES-128-CBC (OS) 128B 192.01 ns 0.889 ns 0.788 ns 72 B
Decrypt · AES-128-CBC (CryptoHives-Scalar) 128B 386.49 ns 0.065 ns 0.057 ns -
Decrypt · AES-128-CBC (BouncyCastle) 128B 617.72 ns 0.471 ns 0.441 ns 832 B
Encrypt · AES-128-CBC (CryptoHives-ARM-AES) 128B 41.23 ns 0.158 ns 0.148 ns -
Encrypt · AES-128-CBC (OS) 128B 201.05 ns 1.076 ns 0.840 ns 72 B
Encrypt · AES-128-CBC (CryptoHives-Scalar) 128B 437.71 ns 1.098 ns 0.917 ns -
Encrypt · AES-128-CBC (BouncyCastle) 128B 575.40 ns 0.335 ns 0.314 ns 832 B
Decrypt · AES-128-CBC (CryptoHives-ARM-AES) 1KB 90.87 ns 0.150 ns 0.141 ns -
Decrypt · AES-128-CBC (OS) 1KB 234.00 ns 0.502 ns 0.470 ns 72 B
Decrypt · AES-128-CBC (CryptoHives-Scalar) 1KB 2,704.25 ns 0.871 ns 0.772 ns -
Decrypt · AES-128-CBC (BouncyCastle) 1KB 3,382.69 ns 2.480 ns 2.071 ns 832 B
Encrypt · AES-128-CBC (CryptoHives-ARM-AES) 1KB 380.61 ns 2.884 ns 2.556 ns -
Encrypt · AES-128-CBC (OS) 1KB 564.03 ns 3.757 ns 3.515 ns 72 B
Encrypt · AES-128-CBC (CryptoHives-Scalar) 1KB 3,138.87 ns 5.853 ns 5.188 ns -
Encrypt · AES-128-CBC (BouncyCastle) 1KB 3,266.56 ns 5.467 ns 4.565 ns 832 B
Decrypt · AES-128-CBC (OS) 8KB 581.36 ns 2.844 ns 2.660 ns 72 B
Decrypt · AES-128-CBC (CryptoHives-ARM-AES) 8KB 640.09 ns 1.202 ns 1.065 ns -
Decrypt · AES-128-CBC (CryptoHives-Scalar) 8KB 21,343.26 ns 21.504 ns 19.063 ns -
Decrypt · AES-128-CBC (BouncyCastle) 8KB 25,300.61 ns 60.646 ns 56.728 ns 832 B
Encrypt · AES-128-CBC (OS) 8KB 3,273.80 ns 9.650 ns 8.555 ns 72 B
Encrypt · AES-128-CBC (CryptoHives-ARM-AES) 8KB 3,450.27 ns 32.636 ns 30.528 ns -
Encrypt · AES-128-CBC (BouncyCastle) 8KB 24,689.08 ns 3.414 ns 2.665 ns 832 B
Encrypt · AES-128-CBC (CryptoHives-Scalar) 8KB 24,724.25 ns 86.110 ns 71.906 ns -
Decrypt · AES-128-CBC (OS) 128KB 6,629.29 ns 18.800 ns 17.586 ns 72 B
Decrypt · AES-128-CBC (CryptoHives-ARM-AES) 128KB 10,038.25 ns 8.793 ns 8.225 ns -
Decrypt · AES-128-CBC (CryptoHives-Scalar) 128KB 342,411.79 ns 69.569 ns 65.075 ns -
Decrypt · AES-128-CBC (BouncyCastle) 128KB 403,306.84 ns 776.467 ns 726.308 ns 832 B
Encrypt · AES-128-CBC (OS) 128KB 50,702.29 ns 148.293 ns 138.713 ns 72 B
Encrypt · AES-128-CBC (CryptoHives-ARM-AES) 128KB 55,703.13 ns 11.048 ns 9.794 ns -
Encrypt · AES-128-CBC (CryptoHives-Scalar) 128KB 393,947.83 ns 233.883 ns 207.332 ns -
Encrypt · AES-128-CBC (BouncyCastle) 128KB 395,797.91 ns 64.196 ns 60.049 ns 832 B

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 via ArmAes. Decrypt is ~1.65× faster than OS at 128 B; OS leads from ~8 KiB. Encrypt is slower than OS from 1 KiB (serial CBC encrypt bottleneck on Apple Silicon).

Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-256-CBC (CryptoHives-ARM-AES) 128B 25.94 ns 0.012 ns 0.011 ns -
Decrypt · AES-256-CBC (OS) 128B 228.65 ns 0.760 ns 0.711 ns 72 B
Decrypt · AES-256-CBC (CryptoHives-Scalar) 128B 520.73 ns 0.409 ns 0.383 ns -
Decrypt · AES-256-CBC (BouncyCastle) 128B 796.21 ns 0.478 ns 0.447 ns 1024 B
Encrypt · AES-256-CBC (CryptoHives-ARM-AES) 128B 51.21 ns 0.133 ns 0.125 ns -
Encrypt · AES-256-CBC (OS) 128B 249.99 ns 1.042 ns 0.975 ns 72 B
Encrypt · AES-256-CBC (CryptoHives-Scalar) 128B 569.79 ns 0.102 ns 0.090 ns -
Encrypt · AES-256-CBC (BouncyCastle) 128B 736.16 ns 0.332 ns 0.310 ns 1024 B
Decrypt · AES-256-CBC (CryptoHives-ARM-AES) 1KB 110.75 ns 0.171 ns 0.160 ns -
Decrypt · AES-256-CBC (OS) 1KB 283.38 ns 2.026 ns 1.796 ns 72 B
Decrypt · AES-256-CBC (CryptoHives-Scalar) 1KB 3,675.46 ns 1.102 ns 0.977 ns -
Decrypt · AES-256-CBC (BouncyCastle) 1KB 4,457.34 ns 22.236 ns 20.800 ns 1024 B
Encrypt · AES-256-CBC (CryptoHives-ARM-AES) 1KB 502.20 ns 2.961 ns 2.770 ns -
Encrypt · AES-256-CBC (OS) 1KB 740.11 ns 3.304 ns 3.090 ns 72 B
Encrypt · AES-256-CBC (CryptoHives-Scalar) 1KB 4,094.64 ns 4.150 ns 3.882 ns -
Encrypt · AES-256-CBC (BouncyCastle) 1KB 4,279.88 ns 0.877 ns 0.777 ns 1024 B
Decrypt · AES-256-CBC (OS) 8KB 737.84 ns 2.291 ns 2.143 ns 72 B
Decrypt · AES-256-CBC (CryptoHives-ARM-AES) 8KB 784.13 ns 1.241 ns 1.161 ns -
Decrypt · AES-256-CBC (CryptoHives-Scalar) 8KB 28,876.69 ns 31.235 ns 27.689 ns -
Decrypt · AES-256-CBC (BouncyCastle) 8KB 33,243.01 ns 57.197 ns 53.502 ns 1024 B
Encrypt · AES-256-CBC (CryptoHives-ARM-AES) 8KB 4,416.69 ns 2.514 ns 2.099 ns -
Encrypt · AES-256-CBC (OS) 8KB 4,431.78 ns 29.443 ns 27.541 ns 72 B
Encrypt · AES-256-CBC (CryptoHives-Scalar) 8KB 32,276.93 ns 19.301 ns 18.054 ns -
Encrypt · AES-256-CBC (BouncyCastle) 8KB 32,513.05 ns 15.985 ns 13.348 ns 1024 B
Decrypt · AES-256-CBC (OS) 128KB 8,687.05 ns 35.014 ns 32.752 ns 72 B
Decrypt · AES-256-CBC (CryptoHives-ARM-AES) 128KB 12,332.70 ns 18.755 ns 17.544 ns -
Decrypt · AES-256-CBC (CryptoHives-Scalar) 128KB 463,437.70 ns 85.650 ns 80.117 ns -
Decrypt · AES-256-CBC (BouncyCastle) 128KB 527,909.74 ns 1,089.556 ns 965.863 ns 1024 B
Encrypt · AES-256-CBC (OS) 128KB 69,064.77 ns 295.145 ns 276.079 ns 72 B
Encrypt · AES-256-CBC (CryptoHives-ARM-AES) 128KB 72,581.96 ns 323.630 ns 302.723 ns -
Encrypt · AES-256-CBC (CryptoHives-Scalar) 128KB 515,155.44 ns 145.406 ns 128.898 ns -
Encrypt · AES-256-CBC (BouncyCastle) 128KB 518,235.92 ns 127.222 ns 112.779 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¹²⁸). Two acceleration tiers are available on Apple M4:

  • ArmAes+ArmPmull (.NET 8+): Uses ARM Cryptography Extension AESD/AESE for counter-mode encryption and PMULL/PMULL2 for GHASH polynomial multiplication. PMULL operates on 64-bit polynomial operands to produce 128-bit products; PMULL2 reads from the upper halves of 128-bit NEON registers (a free lane-select requiring no additional instruction). Uses an 8-block stitched loop that interleaves AES rounds with lagged GHASH of the previous 8 blocks. Modular reduction uses a 2-PMULL SymCrypt-style MODREDUCE. Pre-computes Karatsuba cross-term halves for H¹–H⁸ powers. Small payloads use the non-stitched path (≤8 blocks). ~120× faster than OS encrypt at 17 B; ~14× at 128 B (OS CommonCrypto incurs ~8 μs per-call overhead for small payloads). At bulk sizes (≥8 KiB), Apple CommonCrypto leads — due to Apple Silicon–specific AES pipelining not accessible via the .NET ARM intrinsics layer.
  • 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:

  • ArmAes+ArmPmull: ~120× faster than OS encrypt at 17 B; ~14× at 128 B; ~2.5× at 1 KiB; OS leads from ~4–8 KiB
  • ArmAes+ArmPmull at 128 KiB: OS is ~4.8× faster for both encrypt and decrypt
  • Managed: Uses 4-bit Shoup table GHASH, T-table AES; zero allocation
  • BouncyCastle: Uses ARM AES + PMULL internally on ARM64; allocates ~1.5 KB per call
Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 17B 79.64 ns 0.436 ns 0.408 ns -
Decrypt · AES-128-GCM (CryptoHives-Scalar) 17B 350.02 ns 0.840 ns 0.786 ns -
Decrypt · AES-128-GCM (BouncyCastle) 17B 572.51 ns 0.736 ns 0.688 ns 1536 B
Decrypt · AES-128-GCM (OS) 17B 1,885.58 ns 13.577 ns 12.700 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 17B 52.51 ns 0.043 ns 0.040 ns -
Encrypt · AES-128-GCM (CryptoHives-Scalar) 17B 310.59 ns 0.190 ns 0.159 ns -
Encrypt · AES-128-GCM (BouncyCastle) 17B 496.23 ns 0.478 ns 0.447 ns 1520 B
Encrypt · AES-128-GCM (OS) 17B 1,692.15 ns 7.893 ns 6.997 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 65B 114.79 ns 0.411 ns 0.384 ns -
Decrypt · AES-128-GCM (CryptoHives-Scalar) 65B 605.83 ns 0.505 ns 0.473 ns -
Decrypt · AES-128-GCM (BouncyCastle) 65B 765.98 ns 0.681 ns 0.604 ns 1536 B
Decrypt · AES-128-GCM (OS) 65B 1,876.95 ns 18.788 ns 17.574 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 65B 82.88 ns 0.359 ns 0.336 ns -
Encrypt · AES-128-GCM (CryptoHives-Scalar) 65B 572.53 ns 0.763 ns 0.676 ns -
Encrypt · AES-128-GCM (BouncyCastle) 65B 709.60 ns 0.750 ns 0.702 ns 1520 B
Encrypt · AES-128-GCM (OS) 65B 1,696.23 ns 12.227 ns 11.437 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 128B 147.79 ns 0.908 ns 0.850 ns -
Decrypt · AES-128-GCM (CryptoHives-Scalar) 128B 863.46 ns 1.779 ns 1.486 ns -
Decrypt · AES-128-GCM (BouncyCastle) 128B 969.52 ns 1.201 ns 1.124 ns 1536 B
Decrypt · AES-128-GCM (OS) 128B 1,925.13 ns 25.271 ns 23.639 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 128B 113.89 ns 0.242 ns 0.226 ns -
Encrypt · AES-128-GCM (CryptoHives-Scalar) 128B 832.75 ns 4.600 ns 4.303 ns -
Encrypt · AES-128-GCM (BouncyCastle) 128B 923.72 ns 0.595 ns 0.497 ns 1520 B
Encrypt · AES-128-GCM (OS) 128B 1,715.82 ns 14.610 ns 13.667 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 152B 185.84 ns 1.189 ns 1.112 ns -
Decrypt · AES-128-GCM (CryptoHives-Scalar) 152B 1,044.51 ns 1.328 ns 1.242 ns -
Decrypt · AES-128-GCM (BouncyCastle) 152B 1,093.77 ns 0.668 ns 0.625 ns 1536 B
Decrypt · AES-128-GCM (OS) 152B 1,920.54 ns 13.832 ns 12.939 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 152B 145.46 ns 0.762 ns 0.712 ns -
Encrypt · AES-128-GCM (CryptoHives-Scalar) 152B 1,000.48 ns 0.576 ns 0.450 ns -
Encrypt · AES-128-GCM (BouncyCastle) 152B 1,058.16 ns 1.101 ns 1.030 ns 1520 B
Encrypt · AES-128-GCM (OS) 152B 1,715.92 ns 9.608 ns 8.988 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 256B 252.74 ns 2.047 ns 1.915 ns -
Decrypt · AES-128-GCM (BouncyCastle) 256B 1,475.79 ns 0.551 ns 0.488 ns 1536 B
Decrypt · AES-128-GCM (CryptoHives-Scalar) 256B 1,571.21 ns 0.875 ns 0.776 ns -
Decrypt · AES-128-GCM (OS) 256B 1,925.63 ns 14.809 ns 13.852 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 256B 210.00 ns 1.095 ns 1.024 ns -
Encrypt · AES-128-GCM (BouncyCastle) 256B 1,482.78 ns 0.960 ns 0.851 ns 1520 B
Encrypt · AES-128-GCM (CryptoHives-Scalar) 256B 1,537.68 ns 0.246 ns 0.218 ns -
Encrypt · AES-128-GCM (OS) 256B 1,751.74 ns 8.227 ns 7.696 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 1KB 818.30 ns 4.786 ns 4.477 ns -
Decrypt · AES-128-GCM (OS) 1KB 2,040.43 ns 18.153 ns 16.981 ns -
Decrypt · AES-128-GCM (BouncyCastle) 1KB 4,497.94 ns 2.218 ns 1.966 ns 1536 B
Decrypt · AES-128-GCM (CryptoHives-Scalar) 1KB 5,616.40 ns 0.977 ns 0.866 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 1KB 777.00 ns 3.165 ns 2.960 ns -
Encrypt · AES-128-GCM (OS) 1KB 1,852.33 ns 12.683 ns 11.864 ns -
Encrypt · AES-128-GCM (BouncyCastle) 1KB 4,736.94 ns 3.530 ns 3.129 ns 1520 B
Encrypt · AES-128-GCM (CryptoHives-Scalar) 1KB 5,482.91 ns 0.975 ns 0.865 ns -
Decrypt · AES-128-GCM (OS) 8KB 2,906.59 ns 13.994 ns 13.090 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,139.28 ns 19.513 ns 18.252 ns -
Decrypt · AES-128-GCM (BouncyCastle) 8KB 32,159.29 ns 8.218 ns 7.285 ns 1536 B
Decrypt · AES-128-GCM (CryptoHives-Scalar) 8KB 43,142.20 ns 13.286 ns 12.428 ns -
Encrypt · AES-128-GCM (OS) 8KB 2,746.25 ns 19.581 ns 17.358 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,089.00 ns 35.385 ns 31.368 ns -
Encrypt · AES-128-GCM (BouncyCastle) 8KB 34,529.97 ns 16.794 ns 14.023 ns 1520 B
Encrypt · AES-128-GCM (CryptoHives-Scalar) 8KB 42,980.38 ns 61.427 ns 54.454 ns -
Decrypt · AES-128-GCM (OS) 128KB 18,348.94 ns 93.843 ns 87.781 ns -
Decrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 128KB 98,310.10 ns 636.842 ns 595.703 ns -
Decrypt · AES-128-GCM (BouncyCastle) 128KB 508,739.90 ns 210.798 ns 197.181 ns 1536 B
Decrypt · AES-128-GCM (CryptoHives-Scalar) 128KB 686,348.60 ns 243.045 ns 227.344 ns -
Encrypt · AES-128-GCM (OS) 128KB 19,632.89 ns 78.093 ns 65.211 ns -
Encrypt · AES-128-GCM (CryptoHives-ARM-AES+PMULL) 128KB 97,961.03 ns 609.987 ns 540.737 ns -
Encrypt · AES-128-GCM (BouncyCastle) 128KB 550,114.42 ns 692.387 ns 647.660 ns 1520 B
Encrypt · AES-128-GCM (CryptoHives-Scalar) 128KB 685,222.76 ns 88.668 ns 78.602 ns -

AES-192-GCM

AES-192-GCM uses 12 rounds (vs 10 for AES-128), adding ~10-15% overhead. The same ArmAes+ArmPmull pipeline applies. The performance pattern mirrors AES-128-GCM: dominant over OS at small payloads, OS leads at bulk sizes.

Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 17B 81.62 ns 0.904 ns 0.846 ns -
Decrypt · AES-192-GCM (CryptoHives-Scalar) 17B 370.10 ns 0.686 ns 0.642 ns -
Decrypt · AES-192-GCM (BouncyCastle) 17B 623.17 ns 0.565 ns 0.528 ns 1640 B
Decrypt · AES-192-GCM (OS) 17B 1,866.41 ns 12.850 ns 12.020 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 17B 53.69 ns 0.034 ns 0.032 ns -
Encrypt · AES-192-GCM (CryptoHives-Scalar) 17B 333.71 ns 0.059 ns 0.055 ns -
Encrypt · AES-192-GCM (BouncyCastle) 17B 537.94 ns 0.774 ns 0.724 ns 1624 B
Encrypt · AES-192-GCM (OS) 17B 1,677.55 ns 10.117 ns 9.463 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 65B 115.21 ns 0.506 ns 0.473 ns -
Decrypt · AES-192-GCM (CryptoHives-Scalar) 65B 649.73 ns 0.767 ns 0.717 ns -
Decrypt · AES-192-GCM (BouncyCastle) 65B 840.54 ns 0.722 ns 0.675 ns 1640 B
Decrypt · AES-192-GCM (OS) 65B 1,905.10 ns 9.644 ns 8.549 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 65B 84.41 ns 0.276 ns 0.258 ns -
Encrypt · AES-192-GCM (CryptoHives-Scalar) 65B 616.70 ns 0.449 ns 0.398 ns -
Encrypt · AES-192-GCM (BouncyCastle) 65B 768.36 ns 0.575 ns 0.538 ns 1624 B
Encrypt · AES-192-GCM (OS) 65B 1,691.62 ns 12.867 ns 12.035 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 128B 154.25 ns 0.684 ns 0.640 ns -
Decrypt · AES-192-GCM (CryptoHives-Scalar) 128B 928.81 ns 0.381 ns 0.337 ns -
Decrypt · AES-192-GCM (BouncyCastle) 128B 1,062.42 ns 1.025 ns 0.856 ns 1640 B
Decrypt · AES-192-GCM (OS) 128B 1,912.29 ns 16.900 ns 15.808 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 128B 117.01 ns 0.403 ns 0.377 ns -
Encrypt · AES-192-GCM (CryptoHives-Scalar) 128B 894.13 ns 0.112 ns 0.105 ns -
Encrypt · AES-192-GCM (BouncyCastle) 128B 1,009.75 ns 0.609 ns 0.570 ns 1624 B
Encrypt · AES-192-GCM (OS) 128B 1,729.30 ns 9.252 ns 8.201 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 152B 187.65 ns 1.166 ns 1.091 ns -
Decrypt · AES-192-GCM (CryptoHives-Scalar) 152B 1,125.93 ns 1.015 ns 0.792 ns -
Decrypt · AES-192-GCM (BouncyCastle) 152B 1,217.13 ns 0.582 ns 0.516 ns 1640 B
Decrypt · AES-192-GCM (OS) 152B 1,914.29 ns 14.994 ns 14.025 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 152B 147.21 ns 0.737 ns 0.689 ns -
Encrypt · AES-192-GCM (CryptoHives-Scalar) 152B 1,082.85 ns 0.568 ns 0.474 ns -
Encrypt · AES-192-GCM (BouncyCastle) 152B 1,156.52 ns 1.524 ns 1.426 ns 1624 B
Encrypt · AES-192-GCM (OS) 152B 1,723.15 ns 10.124 ns 9.470 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 256B 255.82 ns 2.105 ns 1.866 ns -
Decrypt · AES-192-GCM (BouncyCastle) 256B 1,636.81 ns 0.935 ns 0.829 ns 1640 B
Decrypt · AES-192-GCM (CryptoHives-Scalar) 256B 1,691.78 ns 0.476 ns 0.422 ns -
Decrypt · AES-192-GCM (OS) 256B 1,910.88 ns 9.973 ns 8.841 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 256B 213.26 ns 0.915 ns 0.856 ns -
Encrypt · AES-192-GCM (BouncyCastle) 256B 1,612.55 ns 1.439 ns 1.276 ns 1624 B
Encrypt · AES-192-GCM (CryptoHives-Scalar) 256B 1,655.74 ns 0.214 ns 0.189 ns -
Encrypt · AES-192-GCM (OS) 256B 1,756.52 ns 12.565 ns 11.754 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 1KB 829.29 ns 2.973 ns 2.781 ns -
Decrypt · AES-192-GCM (OS) 1KB 2,052.01 ns 15.344 ns 14.353 ns -
Decrypt · AES-192-GCM (BouncyCastle) 1KB 5,016.23 ns 3.877 ns 3.627 ns 1640 B
Decrypt · AES-192-GCM (CryptoHives-Scalar) 1KB 6,100.72 ns 2.250 ns 2.104 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 1KB 783.51 ns 4.139 ns 3.871 ns -
Encrypt · AES-192-GCM (OS) 1KB 1,862.16 ns 16.471 ns 15.407 ns -
Encrypt · AES-192-GCM (BouncyCastle) 1KB 5,230.86 ns 1.743 ns 1.545 ns 1624 B
Encrypt · AES-192-GCM (CryptoHives-Scalar) 1KB 5,962.33 ns 1.588 ns 1.326 ns -
Decrypt · AES-192-GCM (OS) 8KB 2,950.89 ns 13.615 ns 11.369 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,137.21 ns 34.518 ns 32.288 ns -
Decrypt · AES-192-GCM (BouncyCastle) 8KB 36,043.71 ns 33.620 ns 31.448 ns 1640 B
Decrypt · AES-192-GCM (CryptoHives-Scalar) 8KB 46,889.80 ns 7.282 ns 6.455 ns -
Encrypt · AES-192-GCM (OS) 8KB 2,836.81 ns 21.205 ns 18.798 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,106.32 ns 42.994 ns 40.216 ns -
Encrypt · AES-192-GCM (BouncyCastle) 8KB 38,505.62 ns 33.372 ns 31.216 ns 1624 B
Encrypt · AES-192-GCM (CryptoHives-Scalar) 8KB 46,819.49 ns 33.849 ns 31.663 ns -
Decrypt · AES-192-GCM (OS) 128KB 19,419.47 ns 64.891 ns 57.524 ns -
Decrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 128KB 98,833.62 ns 448.633 ns 419.652 ns -
Decrypt · AES-192-GCM (BouncyCastle) 128KB 570,219.57 ns 402.324 ns 376.334 ns 1640 B
Decrypt · AES-192-GCM (CryptoHives-Scalar) 128KB 747,091.74 ns 195.242 ns 152.432 ns -
Encrypt · AES-192-GCM (OS) 128KB 20,499.65 ns 67.806 ns 63.426 ns -
Encrypt · AES-192-GCM (CryptoHives-ARM-AES+PMULL) 128KB 98,640.93 ns 588.235 ns 550.236 ns -
Encrypt · AES-192-GCM (BouncyCastle) 128KB 610,048.24 ns 335.106 ns 297.063 ns 1624 B
Encrypt · AES-192-GCM (CryptoHives-Scalar) 128KB 745,908.59 ns 154.941 ns 129.382 ns -

AES-256-GCM

AES-256-GCM uses 14 rounds (vs 10 for AES-128), adding ~20-30% overhead per block. The same 2-tier architecture (ArmAes+ArmPmull → Managed) applies. Encrypt is ~14–16× faster than OS at 128 B; OS leads from ~4–8 KiB. The large-payload gap mirrors AES-128-GCM — Apple CommonCrypto likely exploits Apple Silicon–specific AES/PMULL execution units that are not yet accessible through the .NET ARMv8 intrinsics layer.

Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 17B 81.93 ns 0.459 ns 0.407 ns -
Decrypt · AES-256-GCM (CryptoHives-Scalar) 17B 399.45 ns 3.125 ns 2.770 ns -
Decrypt · AES-256-GCM (BouncyCastle) 17B 664.17 ns 0.965 ns 0.903 ns 1744 B
Decrypt · AES-256-GCM (OS) 17B 1,908.36 ns 8.973 ns 8.393 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 17B 55.20 ns 0.049 ns 0.043 ns -
Encrypt · AES-256-GCM (CryptoHives-Scalar) 17B 357.59 ns 0.186 ns 0.165 ns -
Encrypt · AES-256-GCM (BouncyCastle) 17B 586.16 ns 0.571 ns 0.534 ns 1728 B
Encrypt · AES-256-GCM (OS) 17B 1,716.04 ns 9.017 ns 8.435 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 65B 117.85 ns 0.839 ns 0.785 ns -
Decrypt · AES-256-GCM (CryptoHives-Scalar) 65B 700.25 ns 0.476 ns 0.445 ns -
Decrypt · AES-256-GCM (BouncyCastle) 65B 904.71 ns 0.543 ns 0.508 ns 1744 B
Decrypt · AES-256-GCM (OS) 65B 1,916.60 ns 12.581 ns 11.768 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 65B 85.40 ns 0.238 ns 0.222 ns -
Encrypt · AES-256-GCM (CryptoHives-Scalar) 65B 660.42 ns 0.378 ns 0.316 ns -
Encrypt · AES-256-GCM (BouncyCastle) 65B 844.02 ns 0.934 ns 0.873 ns 1728 B
Encrypt · AES-256-GCM (OS) 65B 1,709.95 ns 10.773 ns 10.077 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 128B 158.28 ns 0.706 ns 0.660 ns -
Decrypt · AES-256-GCM (CryptoHives-Scalar) 128B 1,007.02 ns 0.432 ns 0.404 ns -
Decrypt · AES-256-GCM (BouncyCastle) 128B 1,151.65 ns 0.485 ns 0.453 ns 1744 B
Decrypt · AES-256-GCM (OS) 128B 1,944.51 ns 22.287 ns 20.847 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 128B 118.28 ns 0.646 ns 0.604 ns -
Encrypt · AES-256-GCM (CryptoHives-Scalar) 128B 960.14 ns 0.300 ns 0.266 ns -
Encrypt · AES-256-GCM (BouncyCastle) 128B 1,105.29 ns 0.954 ns 0.892 ns 1728 B
Encrypt · AES-256-GCM (OS) 128B 1,739.64 ns 7.510 ns 6.271 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 152B 192.12 ns 1.691 ns 1.582 ns -
Decrypt · AES-256-GCM (CryptoHives-Scalar) 152B 1,206.38 ns 0.889 ns 0.832 ns -
Decrypt · AES-256-GCM (BouncyCastle) 152B 1,307.17 ns 0.698 ns 0.653 ns 1744 B
Decrypt · AES-256-GCM (OS) 152B 1,934.32 ns 15.577 ns 14.571 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 152B 148.44 ns 0.566 ns 0.529 ns -
Encrypt · AES-256-GCM (CryptoHives-Scalar) 152B 1,165.28 ns 2.019 ns 1.889 ns -
Encrypt · AES-256-GCM (BouncyCastle) 152B 1,268.83 ns 0.553 ns 0.432 ns 1728 B
Encrypt · AES-256-GCM (OS) 152B 1,752.40 ns 12.081 ns 11.301 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 256B 260.26 ns 1.620 ns 1.516 ns -
Decrypt · AES-256-GCM (BouncyCastle) 256B 1,777.70 ns 0.663 ns 0.588 ns 1744 B
Decrypt · AES-256-GCM (CryptoHives-Scalar) 256B 1,821.35 ns 2.425 ns 2.150 ns -
Decrypt · AES-256-GCM (OS) 256B 1,960.40 ns 21.716 ns 20.313 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 256B 218.57 ns 1.039 ns 0.972 ns -
Encrypt · AES-256-GCM (OS) 256B 1,765.22 ns 8.841 ns 8.270 ns -
Encrypt · AES-256-GCM (BouncyCastle) 256B 1,770.47 ns 1.662 ns 1.473 ns 1728 B
Encrypt · AES-256-GCM (CryptoHives-Scalar) 256B 1,774.43 ns 0.262 ns 0.232 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 1KB 846.82 ns 3.809 ns 3.563 ns -
Decrypt · AES-256-GCM (OS) 1KB 2,070.91 ns 9.462 ns 7.901 ns -
Decrypt · AES-256-GCM (BouncyCastle) 1KB 5,527.45 ns 0.963 ns 0.900 ns 1744 B
Decrypt · AES-256-GCM (CryptoHives-Scalar) 1KB 6,584.67 ns 6.798 ns 5.677 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 1KB 801.30 ns 5.143 ns 4.810 ns -
Encrypt · AES-256-GCM (OS) 1KB 1,901.97 ns 15.642 ns 14.632 ns -
Encrypt · AES-256-GCM (BouncyCastle) 1KB 5,751.49 ns 2.852 ns 2.529 ns 1728 B
Encrypt · AES-256-GCM (CryptoHives-Scalar) 1KB 6,443.43 ns 0.727 ns 0.680 ns -
Decrypt · AES-256-GCM (OS) 8KB 3,074.88 ns 24.702 ns 23.107 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,266.34 ns 29.429 ns 27.528 ns -
Decrypt · AES-256-GCM (BouncyCastle) 8KB 40,035.64 ns 11.713 ns 10.956 ns 1744 B
Decrypt · AES-256-GCM (CryptoHives-Scalar) 8KB 50,778.44 ns 6.445 ns 6.029 ns -
Encrypt · AES-256-GCM (OS) 8KB 2,913.78 ns 13.955 ns 13.053 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 8KB 6,244.50 ns 49.260 ns 46.078 ns -
Encrypt · AES-256-GCM (BouncyCastle) 8KB 42,620.19 ns 11.059 ns 9.804 ns 1728 B
Encrypt · AES-256-GCM (CryptoHives-Scalar) 8KB 50,556.94 ns 21.089 ns 19.727 ns -
Decrypt · AES-256-GCM (OS) 128KB 20,630.64 ns 113.702 ns 106.357 ns -
Decrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 128KB 100,350.23 ns 483.408 ns 428.529 ns -
Decrypt · AES-256-GCM (BouncyCastle) 128KB 633,296.41 ns 237.810 ns 210.813 ns 1744 B
Decrypt · AES-256-GCM (CryptoHives-Scalar) 128KB 808,200.48 ns 378.984 ns 295.886 ns -
Encrypt · AES-256-GCM (OS) 128KB 21,509.75 ns 57.782 ns 54.049 ns -
Encrypt · AES-256-GCM (CryptoHives-ARM-AES+PMULL) 128KB 100,238.85 ns 389.967 ns 345.695 ns -
Encrypt · AES-256-GCM (BouncyCastle) 128KB 672,608.54 ns 261.288 ns 244.409 ns 1728 B
Encrypt · AES-256-GCM (CryptoHives-Scalar) 128KB 806,265.04 ns 98.784 ns 92.403 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:

  • ArmAes: ARM Cryptography Extension AESD/AESE instructions for all block operations — counter-mode encryption, CBC-MAC computation, and AAD processing. Uses Vector128<byte> round keys via MemoryMarshal.Cast from the shared uint[] key schedule. Dispatched via _useAesNi bool flag (shared with x86 dispatch; indicates hardware AES availability on any ISA).
  • Managed: T-table AES for all block operations. Fully portable, zero-allocation.

Key observations:

  • ArmAes: ~4× faster than Managed at 128 KiB; ~4.3× faster than BouncyCastle; zero allocation
  • Managed: T-table AES; comparable to BouncyCastle at large sizes
  • BouncyCastle: Allocates ~2.4–2.5 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-ARM-AES) 128B 279.8 ns 0.12 ns 0.10 ns -
Decrypt · AES-128-CCM (CryptoHives-Scalar) 128B 958.4 ns 0.49 ns 0.45 ns -
Decrypt · AES-128-CCM (BouncyCastle) 128B 1,447.1 ns 1.42 ns 1.26 ns 2424 B
Encrypt · AES-128-CCM (CryptoHives-ARM-AES) 128B 243.0 ns 0.38 ns 0.32 ns -
Encrypt · AES-128-CCM (CryptoHives-Scalar) 128B 922.0 ns 0.24 ns 0.22 ns -
Encrypt · AES-128-CCM (BouncyCastle) 128B 1,398.9 ns 1.04 ns 0.97 ns 2464 B
Decrypt · AES-128-CCM (CryptoHives-ARM-AES) 1KB 1,569.7 ns 1.54 ns 1.37 ns -
Decrypt · AES-128-CCM (CryptoHives-Scalar) 1KB 5,992.7 ns 1.87 ns 1.66 ns -
Decrypt · AES-128-CCM (BouncyCastle) 1KB 6,892.1 ns 5.37 ns 4.19 ns 2424 B
Encrypt · AES-128-CCM (CryptoHives-ARM-AES) 1KB 1,537.4 ns 1.39 ns 1.30 ns -
Encrypt · AES-128-CCM (CryptoHives-Scalar) 1KB 5,957.0 ns 1.73 ns 1.53 ns -
Encrypt · AES-128-CCM (BouncyCastle) 1KB 6,836.5 ns 5.20 ns 4.86 ns 2464 B
Decrypt · AES-128-CCM (CryptoHives-ARM-AES) 8KB 11,836.4 ns 15.60 ns 13.83 ns -
Decrypt · AES-128-CCM (CryptoHives-Scalar) 8KB 46,222.8 ns 6.91 ns 6.46 ns -
Decrypt · AES-128-CCM (BouncyCastle) 8KB 50,122.1 ns 18.06 ns 16.89 ns 2424 B
Encrypt · AES-128-CCM (CryptoHives-ARM-AES) 8KB 11,796.4 ns 11.17 ns 9.90 ns -
Encrypt · AES-128-CCM (CryptoHives-Scalar) 8KB 46,166.9 ns 7.87 ns 7.36 ns -
Encrypt · AES-128-CCM (BouncyCastle) 8KB 49,993.8 ns 14.17 ns 11.06 ns 2464 B
Decrypt · AES-128-CCM (CryptoHives-ARM-AES) 128KB 189,387.4 ns 167.50 ns 148.49 ns -
Decrypt · AES-128-CCM (CryptoHives-Scalar) 128KB 736,442.0 ns 104.72 ns 97.95 ns -
Decrypt · AES-128-CCM (BouncyCastle) 128KB 793,476.2 ns 316.57 ns 296.12 ns 2424 B
Encrypt · AES-128-CCM (CryptoHives-ARM-AES) 128KB 187,476.9 ns 274.05 ns 256.34 ns -
Encrypt · AES-128-CCM (CryptoHives-Scalar) 128KB 736,311.0 ns 122.17 ns 114.28 ns -
Encrypt · AES-128-CCM (BouncyCastle) 128KB 794,560.2 ns 272.32 ns 254.73 ns 2464 B

AES-256-CCM

AES-256-CCM uses 14 rounds (vs 10 for AES-128). The same ArmAes / Managed dispatch applies. The additional rounds add ~10-15% overhead on the Apple M4.

Description TestDataSize Mean Error StdDev Allocated
Decrypt · AES-256-CCM (CryptoHives-ARM-AES) 128B 307.7 ns 0.63 ns 0.59 ns -
Decrypt · AES-256-CCM (CryptoHives-Scalar) 128B 1,252.8 ns 0.77 ns 0.64 ns -
Decrypt · AES-256-CCM (BouncyCastle) 128B 1,807.3 ns 2.40 ns 2.25 ns 2808 B
Encrypt · AES-256-CCM (CryptoHives-ARM-AES) 128B 271.0 ns 0.33 ns 0.30 ns -
Encrypt · AES-256-CCM (CryptoHives-Scalar) 128B 1,209.3 ns 0.47 ns 0.44 ns -
Encrypt · AES-256-CCM (BouncyCastle) 128B 1,759.6 ns 0.84 ns 0.74 ns 2848 B
Decrypt · AES-256-CCM (CryptoHives-ARM-AES) 1KB 1,742.3 ns 2.72 ns 2.55 ns -
Decrypt · AES-256-CCM (CryptoHives-Scalar) 1KB 8,051.2 ns 1.68 ns 1.49 ns -
Decrypt · AES-256-CCM (BouncyCastle) 1KB 8,921.5 ns 6.03 ns 5.35 ns 2808 B
Encrypt · AES-256-CCM (CryptoHives-ARM-AES) 1KB 1,704.6 ns 1.92 ns 1.70 ns -
Encrypt · AES-256-CCM (CryptoHives-Scalar) 1KB 7,904.1 ns 2.70 ns 2.53 ns -
Encrypt · AES-256-CCM (BouncyCastle) 1KB 8,884.8 ns 4.87 ns 4.55 ns 2848 B
Decrypt · AES-256-CCM (CryptoHives-ARM-AES) 8KB 13,151.6 ns 28.84 ns 25.57 ns -
Decrypt · AES-256-CCM (CryptoHives-Scalar) 8KB 61,426.7 ns 23.03 ns 17.98 ns -
Decrypt · AES-256-CCM (BouncyCastle) 8KB 65,671.8 ns 90.82 ns 80.51 ns 2808 B
Encrypt · AES-256-CCM (CryptoHives-ARM-AES) 8KB 13,111.9 ns 33.27 ns 29.50 ns -
Encrypt · AES-256-CCM (CryptoHives-Scalar) 8KB 61,372.1 ns 84.31 ns 70.40 ns -
Encrypt · AES-256-CCM (BouncyCastle) 8KB 65,466.4 ns 19.28 ns 18.03 ns 2848 B
Decrypt · AES-256-CCM (CryptoHives-ARM-AES) 128KB 209,624.1 ns 260.19 ns 243.38 ns -
Decrypt · AES-256-CCM (CryptoHives-Scalar) 128KB 978,324.4 ns 181.35 ns 169.63 ns -
Decrypt · AES-256-CCM (BouncyCastle) 128KB 1,056,633.1 ns 766.94 ns 717.39 ns 2808 B
Encrypt · AES-256-CCM (CryptoHives-ARM-AES) 128KB 208,898.2 ns 277.94 ns 246.39 ns -
Encrypt · AES-256-CCM (CryptoHives-Scalar) 128KB 978,369.4 ns 296.87 ns 277.69 ns -
Encrypt · AES-256-CCM (BouncyCastle) 128KB 1,042,585.9 ns 316.74 ns 280.78 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. Two acceleration tiers are available on ARM:

  • Neon: Single-block ChaCha20 via Vector128<uint> combined with Poly1305 donna-64 MAC (3×44-bit limbs, 9 multiplications per 16-byte block using Math.BigMul). ~5× faster than OS at 128 B (1.84 μs vs 9.58 μs); competitive with OS at 1 KiB; OS leads from 8 KiB. At 128 KiB, Neon (~1.19 ms) is ~1.54× slower than OS (~0.77 ms) and on par with BouncyCastle (~1.18 ms). A dual-block NEON path (comparable to the x86 AVX2 path) would be required to close this gap.
  • Managed: Scalar ChaCha20 + Poly1305 donna-32 (5×26-bit limbs, 25 multiplications per block on .NET Framework / .NET Standard). Fully portable.

Key observations:

  • Neon ~5× faster than OS at 128 B; ~1.4× faster than OS at 1 KiB; OS leads from ~8 KiB (~1.54× faster at 128 KiB)
  • Neon beats BouncyCastle at all sizes up to ~4 KiB; on par with BouncyCastle at 128 KiB (potential improvement area: a dual-block NEON path)
  • Managed and Neon 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-Neon) 128B 416.4 ns 1.51 ns 1.41 ns -
Decrypt · ChaCha20-Poly1305 (BouncyCastle) 128B 695.1 ns 1.59 ns 1.49 ns 416 B
Decrypt · ChaCha20-Poly1305 (NaCl.Core) 128B 826.0 ns 3.22 ns 3.01 ns 48 B
Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 128B 1,361.1 ns 18.77 ns 17.56 ns -
Decrypt · ChaCha20-Poly1305 (OS) 128B 2,293.3 ns 12.33 ns 11.53 ns -
Encrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 128B 354.9 ns 0.93 ns 0.82 ns -
Encrypt · ChaCha20-Poly1305 (BouncyCastle) 128B 498.5 ns 0.41 ns 0.35 ns 336 B
Encrypt · ChaCha20-Poly1305 (NaCl.Core) 128B 791.8 ns 0.56 ns 0.52 ns 48 B
Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 128B 1,346.5 ns 5.66 ns 5.30 ns -
Encrypt · ChaCha20-Poly1305 (OS) 128B 1,978.4 ns 4.84 ns 4.04 ns -
Decrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 1KB 2,006.7 ns 4.96 ns 4.39 ns -
Decrypt · ChaCha20-Poly1305 (BouncyCastle) 1KB 2,410.7 ns 2.28 ns 2.13 ns 416 B
Decrypt · ChaCha20-Poly1305 (OS) 1KB 3,253.4 ns 16.95 ns 15.86 ns -
Decrypt · ChaCha20-Poly1305 (NaCl.Core) 1KB 3,676.4 ns 5.41 ns 5.06 ns 72 B
Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 1KB 6,902.8 ns 20.10 ns 18.80 ns -
Encrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 1KB 1,940.8 ns 4.20 ns 3.73 ns -
Encrypt · ChaCha20-Poly1305 (BouncyCastle) 1KB 2,211.3 ns 1.42 ns 1.26 ns 336 B
Encrypt · ChaCha20-Poly1305 (OS) 1KB 2,913.0 ns 13.28 ns 12.42 ns -
Encrypt · ChaCha20-Poly1305 (NaCl.Core) 1KB 3,629.1 ns 1.37 ns 1.22 ns 72 B
Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 1KB 6,864.7 ns 13.85 ns 12.96 ns -
Decrypt · ChaCha20-Poly1305 (OS) 8KB 10,902.5 ns 41.51 ns 38.82 ns -
Decrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 8KB 14,535.6 ns 9.43 ns 8.36 ns -
Decrypt · ChaCha20-Poly1305 (BouncyCastle) 8KB 15,876.2 ns 12.97 ns 10.83 ns 416 B
Decrypt · ChaCha20-Poly1305 (NaCl.Core) 8KB 26,306.3 ns 14.49 ns 12.10 ns 72 B
Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 8KB 49,612.1 ns 158.03 ns 147.83 ns -
Encrypt · ChaCha20-Poly1305 (OS) 8KB 10,391.7 ns 60.62 ns 56.70 ns -
Encrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 8KB 14,470.9 ns 5.98 ns 5.59 ns -
Encrypt · ChaCha20-Poly1305 (BouncyCastle) 8KB 15,753.4 ns 9.06 ns 8.47 ns 336 B
Encrypt · ChaCha20-Poly1305 (NaCl.Core) 8KB 26,241.8 ns 6.90 ns 6.12 ns 72 B
Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 8KB 49,627.3 ns 105.83 ns 98.99 ns -
Decrypt · ChaCha20-Poly1305 (OS) 128KB 150,325.2 ns 611.41 ns 571.91 ns -
Decrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 128KB 228,442.7 ns 504.39 ns 471.81 ns -
Decrypt · ChaCha20-Poly1305 (BouncyCastle) 128KB 248,892.6 ns 170.05 ns 159.07 ns 416 B
Decrypt · ChaCha20-Poly1305 (NaCl.Core) 128KB 422,416.7 ns 421.49 ns 373.64 ns 72 B
Decrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 128KB 783,090.5 ns 2,470.46 ns 2,310.87 ns -
Encrypt · ChaCha20-Poly1305 (OS) 128KB 140,386.8 ns 716.27 ns 669.99 ns -
Encrypt · ChaCha20-Poly1305 (CryptoHives-Neon) 128KB 228,966.8 ns 93.92 ns 83.26 ns -
Encrypt · ChaCha20-Poly1305 (BouncyCastle) 128KB 250,398.7 ns 441.82 ns 413.28 ns 336 B
Encrypt · ChaCha20-Poly1305 (NaCl.Core) 128KB 415,249.9 ns 395.86 ns 370.29 ns 72 B
Encrypt · ChaCha20-Poly1305 (CryptoHives-Scalar) 128KB 783,435.5 ns 2,575.63 ns 2,409.25 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 Neon / Managed acceleration tiers apply to the inner ChaCha20-Poly1305 operation.

Key observations:

  • Performance nearly identical to ChaCha20-Poly1305 (HChaCha20 adds ~400 ns constant overhead)
  • Neon ~3.3× faster than Managed at 128 KiB; ~3.3× faster than NaCl.Core at 128 KiB
  • No OS or BouncyCastle implementations available for comparison
  • NaCl.Core allocates 48–72 B per call
  • Managed and Neon paths are zero-allocation
Description TestDataSize Mean Error StdDev Allocated
Decrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 128B 891.7 ns 3.00 ns 2.80 ns -
Decrypt · XChaCha20-Poly1305 (NaCl.Core) 128B 1,481.4 ns 1.53 ns 1.43 ns 48 B
Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 128B 1,730.5 ns 3.32 ns 2.94 ns -
Encrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 128B 753.2 ns 3.40 ns 2.65 ns -
Encrypt · XChaCha20-Poly1305 (NaCl.Core) 128B 1,465.8 ns 16.78 ns 14.01 ns 48 B
Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 128B 1,725.9 ns 6.40 ns 5.99 ns -
Decrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 1KB 2,486.6 ns 13.83 ns 12.93 ns -
Decrypt · XChaCha20-Poly1305 (NaCl.Core) 1KB 6,624.1 ns 0.98 ns 0.82 ns 72 B
Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 1KB 7,368.3 ns 15.60 ns 14.59 ns -
Encrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 1KB 2,407.2 ns 31.38 ns 27.82 ns -
Encrypt · XChaCha20-Poly1305 (NaCl.Core) 1KB 6,579.0 ns 4.67 ns 3.90 ns 72 B
Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 1KB 7,358.9 ns 18.70 ns 17.49 ns -
Decrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 8KB 14,969.0 ns 30.79 ns 28.80 ns -
Decrypt · XChaCha20-Poly1305 (NaCl.Core) 8KB 47,610.7 ns 28.53 ns 23.82 ns 72 B
Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 8KB 50,421.4 ns 107.91 ns 100.94 ns -
Encrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 8KB 14,890.3 ns 22.12 ns 17.27 ns -
Encrypt · XChaCha20-Poly1305 (NaCl.Core) 8KB 47,555.8 ns 29.49 ns 24.62 ns 72 B
Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 8KB 50,528.6 ns 91.02 ns 85.14 ns -
Decrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 128KB 229,285.2 ns 486.52 ns 455.09 ns -
Decrypt · XChaCha20-Poly1305 (NaCl.Core) 128KB 750,792.2 ns 148.83 ns 131.94 ns 72 B
Decrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 128KB 789,487.3 ns 1,833.32 ns 1,714.89 ns -
Encrypt · XChaCha20-Poly1305 (CryptoHives-Neon) 128KB 230,297.4 ns 451.66 ns 400.39 ns -
Encrypt · XChaCha20-Poly1305 (NaCl.Core) 128KB 750,301.6 ns 362.22 ns 302.47 ns 72 B
Encrypt · XChaCha20-Poly1305 (CryptoHives-Scalar) 128KB 790,587.7 ns 1,823.69 ns 1,705.88 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 940.0 ns 2.70 ns 2.52 ns -
Decrypt · SM4-CBC (BouncyCastle) 128B 1,442.6 ns 4.82 ns 4.51 ns 40 B
Encrypt · SM4-CBC (CryptoHives-Scalar) 128B 1,048.0 ns 4.11 ns 3.85 ns -
Encrypt · SM4-CBC (BouncyCastle) 128B 1,523.2 ns 6.63 ns 6.20 ns 40 B
Decrypt · SM4-CBC (CryptoHives-Scalar) 1KB 6,658.6 ns 16.00 ns 14.97 ns -
Decrypt · SM4-CBC (BouncyCastle) 1KB 9,012.6 ns 36.88 ns 32.69 ns 40 B
Encrypt · SM4-CBC (CryptoHives-Scalar) 1KB 7,576.7 ns 15.81 ns 14.02 ns -
Encrypt · SM4-CBC (BouncyCastle) 1KB 9,841.0 ns 48.90 ns 45.74 ns 40 B
Decrypt · SM4-CBC (CryptoHives-Scalar) 8KB 52,524.8 ns 125.83 ns 117.70 ns -
Decrypt · SM4-CBC (BouncyCastle) 8KB 69,288.6 ns 248.85 ns 232.78 ns 40 B
Encrypt · SM4-CBC (CryptoHives-Scalar) 8KB 59,850.8 ns 145.59 ns 136.18 ns -
Encrypt · SM4-CBC (BouncyCastle) 8KB 76,415.4 ns 321.87 ns 301.07 ns 40 B
Decrypt · SM4-CBC (CryptoHives-Scalar) 128KB 838,849.9 ns 2,472.28 ns 2,312.57 ns -
Decrypt · SM4-CBC (BouncyCastle) 128KB 1,110,861.3 ns 14,963.84 ns 13,265.06 ns 40 B
Encrypt · SM4-CBC (CryptoHives-Scalar) 128KB 956,054.3 ns 2,355.72 ns 2,203.54 ns -
Encrypt · SM4-CBC (BouncyCastle) 128KB 1,218,526.6 ns 4,521.53 ns 4,229.44 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 Allocated
Decrypt · ARIA-128-CBC (CryptoHives-Scalar) 128B 958.3 ns 0.49 ns 0.46 ns -
Decrypt · ARIA-128-CBC (BouncyCastle) 128B 2,318.5 ns 3.77 ns 3.52 ns 1288 B
Encrypt · ARIA-128-CBC (CryptoHives-Scalar) 128B 946.6 ns 0.77 ns 0.72 ns -
Encrypt · ARIA-128-CBC (BouncyCastle) 128B 2,288.5 ns 2.53 ns 2.37 ns 1288 B
Decrypt · ARIA-128-CBC (CryptoHives-Scalar) 1KB 6,826.1 ns 2.07 ns 1.94 ns -
Decrypt · ARIA-128-CBC (BouncyCastle) 1KB 14,379.9 ns 12.43 ns 11.62 ns 3528 B
Encrypt · ARIA-128-CBC (CryptoHives-Scalar) 1KB 6,725.6 ns 5.58 ns 4.95 ns -
Encrypt · ARIA-128-CBC (BouncyCastle) 1KB 14,226.7 ns 16.83 ns 14.92 ns 3528 B
Decrypt · ARIA-128-CBC (CryptoHives-Scalar) 8KB 53,723.8 ns 29.76 ns 26.38 ns -
Decrypt · ARIA-128-CBC (BouncyCastle) 8KB 109,051.1 ns 97.10 ns 90.83 ns 21448 B
Encrypt · ARIA-128-CBC (CryptoHives-Scalar) 8KB 52,950.2 ns 49.63 ns 46.43 ns -
Encrypt · ARIA-128-CBC (BouncyCastle) 8KB 107,770.1 ns 83.51 ns 74.03 ns 21448 B
Decrypt · ARIA-128-CBC (CryptoHives-Scalar) 128KB 858,530.5 ns 632.22 ns 560.44 ns -
Decrypt · ARIA-128-CBC (BouncyCastle) 128KB 1,737,366.2 ns 1,931.29 ns 1,806.53 ns 328648 B
Encrypt · ARIA-128-CBC (CryptoHives-Scalar) 128KB 846,237.7 ns 659.66 ns 584.77 ns -
Encrypt · ARIA-128-CBC (BouncyCastle) 128KB 1,711,333.4 ns 1,698.98 ns 1,589.23 ns 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.234 μs 0.0006 μs 0.0006 μs -
Decrypt · ARIA-256-CBC (BouncyCastle) 128B 2.966 μs 0.0028 μs 0.0024 μs 1496 B
Encrypt · ARIA-256-CBC (CryptoHives-Scalar) 128B 1.221 μs 0.0008 μs 0.0007 μs -
Encrypt · ARIA-256-CBC (BouncyCastle) 128B 2.915 μs 0.0034 μs 0.0032 μs 1496 B
Decrypt · ARIA-256-CBC (CryptoHives-Scalar) 1KB 8.818 μs 0.0019 μs 0.0017 μs -
Decrypt · ARIA-256-CBC (BouncyCastle) 1KB 18.559 μs 0.0307 μs 0.0287 μs 3736 B
Encrypt · ARIA-256-CBC (CryptoHives-Scalar) 1KB 8.704 μs 0.0054 μs 0.0051 μs -
Encrypt · ARIA-256-CBC (BouncyCastle) 1KB 18.522 μs 0.0221 μs 0.0207 μs 3736 B
Decrypt · ARIA-256-CBC (CryptoHives-Scalar) 8KB 69.497 μs 0.0247 μs 0.0219 μs -
Decrypt · ARIA-256-CBC (BouncyCastle) 8KB 141.442 μs 0.1346 μs 0.1193 μs 21656 B
Encrypt · ARIA-256-CBC (CryptoHives-Scalar) 8KB 68.550 μs 0.0193 μs 0.0171 μs -
Encrypt · ARIA-256-CBC (BouncyCastle) 8KB 141.413 μs 0.1987 μs 0.1858 μs 21656 B
Decrypt · ARIA-256-CBC (CryptoHives-Scalar) 128KB 1,111.162 μs 0.8023 μs 0.7505 μs -
Decrypt · ARIA-256-CBC (BouncyCastle) 128KB 2,264.531 μs 2.8306 μs 2.6477 μs 328856 B
Encrypt · ARIA-256-CBC (CryptoHives-Scalar) 128KB 1,095.734 μs 0.7846 μs 0.7339 μs -
Encrypt · ARIA-256-CBC (BouncyCastle) 128KB 2,245.190 μs 2.6259 μs 2.3278 μ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 598.5 ns 1.47 ns 1.38 ns -
Decrypt · Camellia-128-CBC (BouncyCastle) 128B 906.8 ns 1.01 ns 0.89 ns 576 B
Encrypt · Camellia-128-CBC (CryptoHives-Scalar) 128B 673.3 ns 2.23 ns 2.09 ns -
Encrypt · Camellia-128-CBC (BouncyCastle) 128B 904.5 ns 0.51 ns 0.45 ns 576 B
Decrypt · Camellia-128-CBC (CryptoHives-Scalar) 1KB 4,200.5 ns 10.74 ns 10.05 ns -
Decrypt · Camellia-128-CBC (BouncyCastle) 1KB 5,836.6 ns 8.20 ns 7.67 ns 2816 B
Encrypt · Camellia-128-CBC (CryptoHives-Scalar) 1KB 4,857.5 ns 19.59 ns 18.32 ns -
Encrypt · Camellia-128-CBC (BouncyCastle) 1KB 5,963.2 ns 5.24 ns 4.90 ns 2816 B
Decrypt · Camellia-128-CBC (CryptoHives-Scalar) 8KB 32,856.6 ns 74.97 ns 70.13 ns -
Decrypt · Camellia-128-CBC (BouncyCastle) 8KB 45,646.8 ns 89.82 ns 84.02 ns 20736 B
Encrypt · Camellia-128-CBC (CryptoHives-Scalar) 8KB 38,335.1 ns 147.68 ns 138.14 ns -
Encrypt · Camellia-128-CBC (BouncyCastle) 8KB 46,472.3 ns 38.64 ns 34.26 ns 20736 B
Decrypt · Camellia-128-CBC (CryptoHives-Scalar) 128KB 532,346.2 ns 1,223.48 ns 1,084.58 ns -
Decrypt · Camellia-128-CBC (BouncyCastle) 128KB 717,414.6 ns 1,660.09 ns 1,552.85 ns 327936 B
Encrypt · Camellia-128-CBC (CryptoHives-Scalar) 128KB 613,741.2 ns 2,961.91 ns 2,770.57 ns -
Encrypt · Camellia-128-CBC (BouncyCastle) 128KB 726,129.0 ns 1,504.58 ns 1,333.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 833.3 ns 2.83 ns 2.65 ns -
Decrypt · Camellia-256-CBC (BouncyCastle) 128B 1,188.1 ns 2.76 ns 2.58 ns 592 B
Encrypt · Camellia-256-CBC (CryptoHives-Scalar) 128B 903.6 ns 2.55 ns 2.38 ns -
Encrypt · Camellia-256-CBC (BouncyCastle) 128B 1,158.2 ns 2.28 ns 2.13 ns 592 B
Decrypt · Camellia-256-CBC (CryptoHives-Scalar) 1KB 5,905.3 ns 22.22 ns 20.79 ns -
Decrypt · Camellia-256-CBC (BouncyCastle) 1KB 7,601.3 ns 9.86 ns 9.22 ns 2832 B
Encrypt · Camellia-256-CBC (CryptoHives-Scalar) 1KB 6,545.6 ns 14.52 ns 13.58 ns -
Encrypt · Camellia-256-CBC (BouncyCastle) 1KB 7,915.2 ns 23.18 ns 20.55 ns 2832 B
Decrypt · Camellia-256-CBC (CryptoHives-Scalar) 8KB 46,525.0 ns 200.57 ns 187.61 ns -
Decrypt · Camellia-256-CBC (BouncyCastle) 8KB 58,538.1 ns 85.47 ns 79.94 ns 20752 B
Encrypt · Camellia-256-CBC (CryptoHives-Scalar) 8KB 51,691.6 ns 136.98 ns 128.13 ns -
Encrypt · Camellia-256-CBC (BouncyCastle) 8KB 59,110.0 ns 75.57 ns 70.69 ns 20752 B
Decrypt · Camellia-256-CBC (CryptoHives-Scalar) 128KB 746,317.2 ns 2,124.71 ns 1,883.50 ns -
Decrypt · Camellia-256-CBC (BouncyCastle) 128KB 960,280.5 ns 1,479.53 ns 1,383.95 ns 327952 B
Encrypt · Camellia-256-CBC (CryptoHives-Scalar) 128KB 827,393.4 ns 2,260.21 ns 2,114.20 ns -
Encrypt · Camellia-256-CBC (BouncyCastle) 128KB 938,050.4 ns 3,219.61 ns 3,011.63 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 325.2 μs 6.47 μs 11.99 μs -
Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) 128B 381.8 μs 7.44 μs 11.58 μs -
Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) 1KB 3,204.8 μs 24.14 μs 21.40 μs -
Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) 1KB 3,136.9 μs 22.64 μs 21.17 μs -
Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) 8KB 25,896.8 μs 89.61 μs 83.82 μs -
Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) 8KB 25,993.1 μs 70.82 μs 66.25 μs -
Decrypt · Kuznyechik-CBC (CryptoHives-Scalar) 128KB 416,576.6 μs 1,492.71 μs 1,396.29 μs -
Encrypt · Kuznyechik-CBC (CryptoHives-Scalar) 128KB 403,828.9 μs 1,330.86 μs 1,111.33 μ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 798.3 ns 0.52 ns 0.48 ns -
Decrypt · Kalyna-128-CBC (BouncyCastle) 128B 2,414.8 ns 1.11 ns 1.04 ns 872 B
Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) 128B 403.8 ns 0.36 ns 0.34 ns -
Encrypt · Kalyna-128-CBC (BouncyCastle) 128B 1,266.2 ns 0.48 ns 0.42 ns 872 B
Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) 1KB 5,658.3 ns 4.04 ns 3.78 ns -
Decrypt · Kalyna-128-CBC (BouncyCastle) 1KB 15,384.8 ns 7.81 ns 6.92 ns 872 B
Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) 1KB 2,914.6 ns 7.31 ns 6.83 ns -
Encrypt · Kalyna-128-CBC (BouncyCastle) 1KB 7,175.8 ns 4.62 ns 4.32 ns 872 B
Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) 8KB 44,498.4 ns 21.83 ns 20.42 ns -
Decrypt · Kalyna-128-CBC (BouncyCastle) 8KB 118,897.6 ns 40.72 ns 36.10 ns 872 B
Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) 8KB 23,048.0 ns 35.53 ns 33.23 ns -
Encrypt · Kalyna-128-CBC (BouncyCastle) 8KB 54,157.0 ns 54.87 ns 51.32 ns 872 B
Decrypt · Kalyna-128-CBC (CryptoHives-Scalar) 128KB 710,804.9 ns 326.17 ns 305.10 ns -
Decrypt · Kalyna-128-CBC (BouncyCastle) 128KB 1,895,526.2 ns 429.38 ns 401.64 ns 872 B
Encrypt · Kalyna-128-CBC (CryptoHives-Scalar) 128KB 368,934.4 ns 219.40 ns 205.23 ns -
Encrypt · Kalyna-128-CBC (BouncyCastle) 128KB 862,475.7 ns 813.47 ns 760.92 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,122.2 ns 0.99 ns 0.92 ns -
Decrypt · Kalyna-256-CBC (BouncyCastle) 128B 3,289.0 ns 2.17 ns 2.03 ns 1112 B
Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) 128B 553.4 ns 0.38 ns 0.33 ns -
Encrypt · Kalyna-256-CBC (BouncyCastle) 128B 1,705.0 ns 1.20 ns 1.13 ns 1112 B
Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) 1KB 8,010.9 ns 12.45 ns 11.03 ns -
Decrypt · Kalyna-256-CBC (BouncyCastle) 1KB 21,136.2 ns 9.85 ns 9.22 ns 1112 B
Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) 1KB 4,011.0 ns 1.64 ns 1.54 ns -
Encrypt · Kalyna-256-CBC (BouncyCastle) 1KB 9,741.5 ns 17.28 ns 16.17 ns 1112 B
Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) 8KB 63,107.0 ns 117.43 ns 91.68 ns -
Decrypt · Kalyna-256-CBC (BouncyCastle) 8KB 164,039.3 ns 387.62 ns 323.68 ns 1112 B
Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) 8KB 31,626.4 ns 26.42 ns 24.71 ns -
Encrypt · Kalyna-256-CBC (BouncyCastle) 8KB 73,843.6 ns 159.31 ns 141.23 ns 1112 B
Decrypt · Kalyna-256-CBC (CryptoHives-Scalar) 128KB 1,011,116.8 ns 914.14 ns 810.36 ns -
Decrypt · Kalyna-256-CBC (BouncyCastle) 128KB 2,619,103.8 ns 1,515.69 ns 1,265.67 ns 1112 B
Encrypt · Kalyna-256-CBC (CryptoHives-Scalar) 128KB 505,551.8 ns 206.42 ns 182.98 ns -
Encrypt · Kalyna-256-CBC (BouncyCastle) 128KB 1,177,154.1 ns 4,032.05 ns 3,771.58 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.351 μs 0.0022 μs 0.0021 μs -
Decrypt · SEED-CBC (BouncyCastle) 128B 1.429 μs 0.0042 μs 0.0039 μs 152 B
Encrypt · SEED-CBC (CryptoHives-Scalar) 128B 1.396 μs 0.0040 μs 0.0037 μs -
Encrypt · SEED-CBC (BouncyCastle) 128B 1.462 μs 0.0046 μs 0.0043 μs 152 B
Decrypt · SEED-CBC (CryptoHives-Scalar) 1KB 9.615 μs 0.0341 μs 0.0319 μs -
Decrypt · SEED-CBC (BouncyCastle) 1KB 9.828 μs 0.0226 μs 0.0201 μs 152 B
Encrypt · SEED-CBC (CryptoHives-Scalar) 1KB 10.059 μs 0.0292 μs 0.0273 μs -
Encrypt · SEED-CBC (BouncyCastle) 1KB 10.188 μs 0.0437 μs 0.0408 μs 152 B
Decrypt · SEED-CBC (CryptoHives-Scalar) 8KB 75.615 μs 0.1927 μs 0.1803 μs -
Decrypt · SEED-CBC (BouncyCastle) 8KB 76.879 μs 0.2183 μs 0.2042 μs 152 B
Encrypt · SEED-CBC (CryptoHives-Scalar) 8KB 79.385 μs 0.2414 μs 0.2258 μs -
Encrypt · SEED-CBC (BouncyCastle) 8KB 80.066 μs 0.3611 μs 0.3378 μs 152 B
Decrypt · SEED-CBC (CryptoHives-Scalar) 128KB 1,208.888 μs 3.6126 μs 3.3792 μs -
Decrypt · SEED-CBC (BouncyCastle) 128KB 1,228.906 μs 5.4685 μs 5.1153 μs 152 B
Encrypt · SEED-CBC (CryptoHives-Scalar) 128KB 1,268.079 μs 4.5537 μs 4.2596 μs -
Encrypt · SEED-CBC (BouncyCastle) 128KB 1,276.503 μs 3.3576 μs 3.1407 μ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, ArmAes, ArmAes+ArmPmull, Neon) are zero-allocation at all payload sizes
OS (.NET) — GCM / ChaCha20-Poly1305 0 B OS AEAD implementations are zero-allocation
OS (.NET) — CBC 72 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,520–1,744 B Fixed per-call allocation (1,520 B for AES-128 encrypt, 1,744 B for AES-256 decrypt)
BouncyCastle — CCM 2,424–2,848 B Fixed per-call allocation (2,424 B for AES-128 decrypt, 2,848 B for AES-256 encrypt)
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