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 NEONvshl/vsri(shift-and-insert) andvtbl(byte-table permute) instructions for the four rotation widths (16-bit, 12-bit, 8-bit, 7-bit). Diagonal rounds useAdvSimd.ExtractVector128to rotate rows by one element. Yields ~750 MB/s throughput at 128 KiB; ~1.24× faster than BouncyCastle. - Managed: Scalar
uintquarter-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/AESIMCinstructions. Decrypt uses 8-block interleaving — 8 ciphertext blocks are loaded and decrypted simultaneously via parallelAESDdispatch. Each block decrypts independently, requiring only the preceding ciphertext block as an XOR mask (10 rounds × 8 blocks = 80AESDinstructions in flight). Encrypt remains serial because each plaintext block must be XORed with the previous ciphertext before the nextAESEcan 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/AESEfor counter-mode encryption andPMULL/PMULL2for GHASH polynomial multiplication.PMULLoperates on 64-bit polynomial operands to produce 128-bit products;PMULL2reads 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-styleMODREDUCE. 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/AESEinstructions 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 (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 usingMath.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 |