# KMS Performance Comparison

**Versions**: `v5.25.0`  
**Generated**: 2026-07-10

---

## Benchmark Environment

| Field | Value |
|---|---|
| Date | 2026-07-10 16:46:07 UTC |
| Build | release / non-fips |
| Database | SQLite (temporary, single benchmark run) |
| CPU | AMD EPYC 7R13 Processor @ 3,593 MHz |
| CPU cores | 2 physical / 4 logical (HT) |
| RAM | 7.0 GB |
| OS | Ubuntu 24.04.4 LTS |
| Kernel | 6.17.0-1019-aws |

### Load test parameters

| Parameter | Value |
|---|---|
| Mode | all |
| Protocols | all |
| Measurement window | 20 s per concurrency level |
| Concurrency levels | 1,2,4,8,16 |
| Warm-up | 5 s |
| Cooldown between levels | 2 s |

### CPU detail (`lscpu`)

```text
Architecture:                            x86_64
CPU op-mode(s):                          32-bit, 64-bit
Address sizes:                           48 bits physical, 48 bits virtual
Byte Order:                              Little Endian
CPU(s):                                  4
On-line CPU(s) list:                     0-3
Vendor ID:                               AuthenticAMD
Model name:                              AMD EPYC 7R13 Processor
CPU family:                              25
Model:                                   1
Thread(s) per core:                      2
Core(s) per socket:                      2
Socket(s):                               1
Stepping:                                1
BogoMIPS:                                5300.00
Flags:                                   fpu vme de pse tsc msr pae mce cx8 apic sep pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 clzero xsaveerptr wbnoinvd arat npt nrip_save vaes vpclmulqdq rdpid
Hypervisor vendor:                       KVM
Virtualization type:                     full
L1d cache:                               64 KiB (2 instances)
L1i cache:                               64 KiB (2 instances)
L2 cache:                                1 MiB (2 instances)
L3 cache:                                8 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-3
Vulnerability Gather data sampling:      Not affected
Vulnerability Ghostwrite:                Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Old microcode:             Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Mitigation; Safe RET
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; Retpolines; IBPB conditional; IBRS_FW; STIBP always-on; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Mitigation; Clear CPU buffers
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
```


---

## Protocols

The KMS server was exercised over three distinct wire protocols.
Each benchmark column is labelled with the protocol name it used.

| Protocol | Transport | Encoding | Endpoint | Description |
|---|---|---|---|---|
| **ttlv-json** | HTTP/1.1 | KMIP 2.1 JSON-TTLV | `POST /kmip/2_1` | Primary interoperability protocol — any KMIP 2.1 compliant client can use it |
| **ttlv-bytes** | HTTP/1.1 | KMIP 2.1 binary TTLV | `POST /kmip` | Binary wire format; eliminates JSON parsing overhead — typically 10–30 % faster |
| **jose** | HTTP/1.1 | JWE / JWS (JOSE) | `POST /v1/crypto/` | REST API for OAuth2/OIDC workloads that prefer JWA algorithm identifiers over KMIP |

**KMIP TTLV** (Tag-Type-Length-Value) is the native encoding of the KMIP 2.1 standard (OASIS KMIP Spec v2.1, §9.1). The **JSON** variant wraps every field in a `{"tag": …, "type": …, "value": …}` JSON object and base64-encodes binary values. The **binary** variant uses a compact 8-byte fixed header (3-byte tag, 1-byte type, 4-byte length) per value, removing JSON tokenisation, base64, and UTF-8 overhead entirely.

**JOSE** (JSON Object Signing and Encryption, RFC 7516 / RFC 7515) exposes KMS key material through `/v1/crypto/` REST endpoints. It is used by cloud integrations (Google CSE, Microsoft DKE, Azure EKM) and any workload that speaks JWA algorithm identifiers (A256GCM, RS256, ES384 …) rather than KMIP semantics.


---

## Benchmark Methodology

### Plaintext / payload sizes

All encrypt/decrypt benchmarks use a **fixed-size random payload**. Sizes represent a realistic key-wrapping or small-message encryption workload without introducing significant data-transfer overhead on a loopback connection.

| Algorithm / category | Plaintext size | Notes |
|---|---|---|
| AES-GCM (128 / 192 / 256-bit key) | 64 bytes | FIPS 140-3 |
| AES-GCM-SIV (128 / 256-bit key) | 64 bytes | Non-FIPS |
| AES-XTS (128 / 256-bit AES = 256 / 512-bit key) | 64 bytes | FIPS 140-3; requires 16-byte IV |
| ChaCha20-Poly1305 (256-bit key) | 64 bytes | Non-FIPS |
| ECIES — P-256 / P-384 / P-521 | 64 bytes | Non-FIPS; EC public-key encryption |
| Salsa Sealed Box (X25519) | 64 bytes | Non-FIPS |
| Covercrypt (attribute-based encryption) | 64 bytes | Non-FIPS |
| JOSE JWE — `dir` + AES-GCM (A128GCM / A192GCM / A256GCM) | 64 bytes | Symmetric (direct key agreement) |
| JOSE JWE — RSA-OAEP + AES-GCM (2048 / 4096-bit) | 64 bytes | Asymmetric (RSA-OAEP CEK wrapping) |
| RSA-OAEP (2048 / 3072 / 4096-bit) | 32 bytes | Limited by RSA block size |
| RSA-PKCS#1 v1.5 (2048 / 3072 / 4096-bit) | 32 bytes | Non-FIPS |
| RSA-AES Key Wrap — KWP (2048 / 3072 / 4096-bit) | 32 bytes | FIPS 140-3 |
| Sign / Verify — all algorithms | 32 bytes | Message is hashed internally |
| JOSE JWS / MAC | 32 bytes | |

### Load test (`ckms bench --load`)

The load test sweeps a configurable list of concurrency levels. At each level *N* concurrent async tasks send pre-serialised requests in tight loops for a fixed **measurement window** (default: 20 s), preceded by a **warm-up phase** (default: 5 s) that is excluded from measurements. Pre-serialisation happens once at setup time and the same bytes are reused on every iteration, isolating server-side KMS latency from client-side encoding overhead.
Recorded metrics per *(protocol, operation, concurrency)* triple:

- **Throughput** — requests per second (req/s)
- **p50 / p95 / p99** — round-trip latency percentiles (ms)

### Criterion micro-benchmarks (`ckms bench`)

Criterion (Rust, v0.5) measures the **round-trip latency of a single request** from the ckms client library through the KMS server and back over a loopback TCP connection. The server is started once and kept alive across all benchmarks in the suite.
The reported value is the **mean ± 95 % confidence interval** over a configurable number of samples (preset `quick`: 3 s warm-up + 5 s measurement per benchmark).

> **Infrastructure note:** Both test types use a **local SQLite** backend (temporary, discarded after the run). This isolates pure cryptographic and KMIP serialisation overhead from database I/O. Throughput figures will differ on a production deployment backed by PostgreSQL or Redis-Findex.


---

## Load Tests

### encrypt/aes-gcm

| Concurrency | ttlv-json (req/s) | ttlv-bytes (req/s) | jose (req/s) |
|---|---|---|---|
| 1 | 1,000 | 1,158 | 1,524 |
| 2 | 1,920 | 2,199 | 2,872 |
| 4 | 4,973 | 7,019 | 12,637 |
| 8 | 4,875 | 6,797 | 11,898 |
| 16 | 4,866 | 6,858 | 12,236 |

![Throughput — encrypt/aes-gcm](load/encrypt_aes-gcm.svg)

---

### sign-verify/ecdsa-p256

| Concurrency | ttlv-json (req/s) | ttlv-bytes (req/s) | jose (req/s) |
|---|---|---|---|
| 1 | 603 | 602 | 622 |
| 2 | 1,206 | 1,206 | 1,244 |
| 4 | 2,437 | 2,435 | 2,543 |
| 8 | 2,431 | 2,417 | 2,548 |
| 16 | 2,439 | 2,404 | 2,543 |

![Throughput — sign-verify/ecdsa-p256](load/sign-verify_ecdsa-p256.svg)

---

### key-creation/aes-sym

| Concurrency | ttlv-json (req/s) |
|---|---|
| 1 | 483 |
| 2 | 815 |
| 4 | 1,071 |
| 8 | 1,024 |
| 16 | 1,011 |

![Throughput — key-creation/aes-sym](load/key-creation_aes-sym.svg)

---

### batch/aes-gcm-10

| Concurrency | ttlv-json (req/s) |
|---|---|
| 1 | 269 |
| 2 | 504 |
| 4 | 742 |
| 8 | 735 |
| 16 | 741 |

![Throughput — batch/aes-gcm-10](load/batch_aes-gcm-10.svg)

---

## Criterion Benchmarks

### Symmetric Encryption

| Benchmark | ttlv-json | ttlv-bytes |
|---|---|---|
| aes-gcm-siv/decrypt - 128 | 1.27 ms | 1.35 ms |
| aes-gcm-siv/decrypt - 256 | 1.31 ms | 1.26 ms |
| aes-gcm-siv/encrypt - 128 | 1.30 ms | 1.33 ms |
| aes-gcm-siv/encrypt - 256 | 1.30 ms | 1.27 ms |
| aes-gcm/decrypt - 128 | 1.41 ms | 1.26 ms |
| aes-gcm/decrypt - 192 | 1.30 ms | 1.33 ms |
| aes-gcm/encrypt - 128 | 1.31 ms | 1.29 ms |
| aes-gcm/encrypt - 192 | 1.29 ms | 1.28 ms |
| aes-gcm/encrypt - 256 | 1.29 ms | 1.31 ms |
| aes-xts/decrypt - 128 | 1.27 ms | 1.28 ms |
| aes-xts/decrypt - 256 | 1.24 ms | 1.25 ms |
| aes-xts/encrypt - 128 | 1.31 ms | 1.28 ms |
| aes-xts/encrypt - 256 | 1.40 ms | 1.30 ms |
| chacha20-poly1305/decrypt/256 | 1.33 ms | 1.28 ms |
| chacha20-poly1305/encrypt/256 | 1.26 ms | 1.27 ms |
| salsa-sealed-box/decrypt | 1.53 ms | 1.50 ms |
| salsa-sealed-box/encrypt | 393.03 ms | 538.84 ms |


---

### Asymmetric Encryption

| Benchmark | ttlv-json | ttlv-bytes | jose |
|---|---|---|---|
| covercrypt/decrypt | 29.49 ms | 30.37 ms | — |
| covercrypt/encrypt | 402.87 ms | 583.35 ms | — |
| decrypt - A128GCM | — | — | 1.19 ms |
| decrypt - A192GCM | — | — | 1.22 ms |
| decrypt - A256GCM | — | — | 1.19 ms |
| ecies/decrypt - P-256 | 1.50 ms | 1.50 ms | — |
| ecies/decrypt - P-384 | 3.73 ms | 3.62 ms | — |
| ecies/encrypt - P-256 | 388.40 ms | 542.50 ms | — |
| ecies/encrypt - P-384 | 387.18 ms | 524.14 ms | — |
| encrypt - A128GCM | — | — | 1.27 ms |
| encrypt - A192GCM | — | — | 1.20 ms |
| encrypt - A256GCM | — | — | 1.22 ms |
| rsa-aes-kwp/decrypt - 4096 | 353.17 ms | 344.29 ms | — |
| rsa-aes-kwp/encrypt - 4096 | 387.64 ms | 530.80 ms | — |
| rsa-oaep/decrypt - 2048 | — | — | 49.53 ms |
| rsa-oaep/decrypt - 4096 | 343.33 ms | 345.75 ms | 332.23 ms |
| rsa-oaep/encrypt - 2048 | — | — | 1.47 ms |
| rsa-oaep/encrypt - 4096 | 393.59 ms | 558.35 ms | 1.63 ms |
| rsa-pkcs1v15/decrypt - 4096 | 350.42 ms | 339.49 ms | — |
| rsa-pkcs1v15/encrypt - 4096 | 384.22 ms | 531.11 ms | — |


---

### Key Encapsulation (KEM)

| Benchmark | ttlv-json | ttlv-bytes |
|---|---|---|
| configurable/decapsulate - ML-KEM-512 | 1.37 ms | 1.40 ms |
| configurable/decapsulate - ML-KEM-768 | 1.35 ms | — |
| configurable/encapsulate - ML-KEM-512 | 386.71 ms | 568.38 ms |
| configurable/encapsulate - ML-KEM-768 | 390.13 ms | 524.19 ms |
| pqc/decapsulate - ML-KEM-512 | 1.54 ms | 1.43 ms |
| pqc/decapsulate - ML-KEM-768 | 1.50 ms | 1.48 ms |
| pqc/encapsulate - ML-KEM-512 | 386.43 ms | 532.20 ms |
| pqc/encapsulate - ML-KEM-768 | 387.73 ms | 512.29 ms |


---

### Key Creation

| Benchmark | ttlv-json |
|---|---|
| EC - ES256 | — |
| EC - ES384 | — |
| RSA - 2048 | — |
| covercrypt/master-keypair | 53.40 ms |
| ec/ed25519 | 2.71 ms |
| ec/ed448 | 3.23 ms |
| ec/p256 | 2.78 ms |
| ec/p384 | 4.21 ms |
| ec/p521 | 5.63 ms |
| kem/ML-KEM-512 | 3.27 ms |
| kem/ML-KEM-512/P-256 | 3.23 ms |
| kem/ML-KEM-512/X25519 | 7.18 ms |
| kem/ML-KEM-768 | 3.32 ms |
| kem/ML-KEM-768/P-256 | 3.81 ms |
| oct - A128GCM | — |
| oct - A256GCM | — |
| pqc/ML-KEM-1024 | 3.36 ms |
| pqc/ML-KEM-512 | 3.05 ms |
| pqc/ML-KEM-768 | 3.37 ms |
| pqc/X25519MLKEM768 | 3.08 ms |
| pqc/X448MLKEM1024 | 3.47 ms |
| rsa/rsa-4096 | 662.48 ms |
| symmetric/aes-128 | 2.94 ms |
| symmetric/aes-192 | 2.66 ms |
| symmetric/aes-256 | 2.62 ms |
| symmetric/chacha20-256 | 2.68 ms |


---

### Sign / Verify

| Benchmark | ttlv-json | ttlv-bytes | jose |
|---|---|---|---|
| ecdsa-p256/sign | 2.27 ms | 2.21 ms | 2.22 ms |
| ecdsa-p256/verify | 631.61 ms | 714.44 ms | 698.75 ms |
| ecdsa-p384/sign | 3.78 ms | 3.80 ms | 3.61 ms |
| ecdsa-p384/verify | 558.80 ms | 698.33 ms | 722.23 ms |
| ecdsa-p521/sign | 6.70 ms | 6.71 ms | — |
| ecdsa-p521/verify | 568.28 ms | 698.13 ms | — |
| ecdsa-secp256k1/sign | 2.14 ms | 2.18 ms | — |
| ecdsa-secp256k1/verify | 565.62 ms | 693.00 ms | — |
| eddsa-ed25519/sign | 1.44 ms | 1.41 ms | 1.40 ms |
| eddsa-ed25519/verify | 558.78 ms | 680.07 ms | 717.83 ms |
| eddsa-ed448/sign | 1.96 ms | 1.91 ms | — |
| eddsa-ed448/verify | 567.43 ms | 675.48 ms | — |
| ml-dsa/sign - 44 | 2.50 ms | 2.44 ms | — |
| ml-dsa/sign - 65 | 3.11 ms | 3.15 ms | — |
| ml-dsa/verify - 44 | 559.47 ms | 689.24 ms | — |
| ml-dsa/verify - 65 | 553.29 ms | 690.25 ms | — |
| rsa-pkcs1v15/sign | — | — | 49.91 ms |
| rsa-pkcs1v15/verify | — | — | 728.14 ms |
| rsa-pss/sign | — | — | 52.58 ms |
| rsa-pss/sign - 4096 | 337.92 ms | 349.34 ms | — |
| rsa-pss/verify | — | — | 725.28 ms |
| rsa-pss/verify - 4096 | 566.81 ms | 684.86 ms | — |
| slh-dsa/sign - SHA2-128f | 19.47 ms | 18.73 ms | — |
| slh-dsa/sign - SHA2-256f | 68.98 ms | 65.80 ms | — |
| slh-dsa/verify - SHA2-128f | 562.36 ms | 706.49 ms | — |
| slh-dsa/verify - SHA2-256f | 567.51 ms | 695.74 ms | — |


---

