Skip to content

ANKASecure Composite Streaming Re-Encryption Micro-Benchmark

Overview

This document describes the methodology, scope, and results of the SecureCore Composite Streaming Re-Encryption Micro-Benchmark, a performance test suite designed to evaluate the cryptographic efficiency of COMPOSITE_KEM_COMBINE composite key re-encryption operations in streaming mode within the AnkaSecure system.

This benchmark systematically measures composite re-encryption performance for hybrid composite keys that combine classical and post-quantum key encapsulation mechanisms (KEMs) across multiple large payload sizes using streaming I/O. The re-encryption operation decrypts an existing JWE General JSON encrypted payload and re-encrypts it with different composite keys using streaming, providing empirical evidence of the platform's ability to deliver quantum-resistant key rotation with memory-efficient processing for large files.


Objectives

The goals of this benchmark are to:

  • Validate the efficiency and scalability of SecureCore's composite streaming re-encryption operations for quantum-resistant key rotation on large files.

  • Compare classical and post-quantum KEM combinations in streaming re-encryption workflows.

  • Quantify the performance overhead of dual-KEM decryption and re-encryption in streaming mode.

  • Provide externally auditable evidence of the platform's enterprise-grade composite streaming re-encryption capabilities.


Scope

  • Operations:

    • Dual decryption of existing JWE General JSON encrypted token using streaming I/O
    • Dual encryption with new composite key producing a new JWE General JSON encrypted token using streaming I/O
  • Composite Mode: COMPOSITE_KEM_COMBINE

    • Combines classical KEM with post-quantum KEM
    • Uses dual-layer key encapsulation (both KEMs must decrypt successfully)
    • Security level difference constraint: ≤ 2 steps
    • Only RECOMMENDED algorithms with allowedInComposite=true
  • Algorithms Tested: 20 valid combinations discovered dynamically from the algorithm catalog:

    • Classical KEMs: P-256, P-384, P-521, X25519, X448
    • PQC KEMs: ML-KEM-768, ML-KEM-1024, HQC-128, HQC-192, HQC-256
  • Payload Sizes: 2 input sizes (limited for re-encryption workflows):

    • 5 MiB, 10 MiB
  • Iteration Strategy:

    • Warm-up iterations: 5 (configurable via sc.perf.warmup)
    • Measurement iterations: 10 (configurable via sc.perf.measurements)
  • Total Measurements: 40 (20 combinations × 2 payload sizes)


Algorithm Taxonomy

Classical Key Encapsulation Mechanisms (5 algorithms)

Elliptic Curve Diffie-Hellman (ECDH) - NIST curves:

  • P-256 (NIST P-256/secp256r1, security level 1)
  • P-384 (NIST P-384/secp384r1, security level 3)
  • P-521 (NIST P-521/secp521r1, security level 5)

Elliptic Curve Diffie-Hellman (ECDH) - Montgomery curves:

  • X25519 (Curve25519, security level 1)
  • X448 (Curve448, security level 3)

Post-Quantum Key Encapsulation Mechanisms (5 algorithms)

ML-KEM (NIST FIPS 203 - Module-Lattice-Based Key Encapsulation Mechanism, formerly Kyber):

  • ML-KEM-768 (security level 3)
  • ML-KEM-1024 (security level 5)

HQC (Hamming Quasi-Cyclic):

  • HQC-128 (security level 1)
  • HQC-192 (security level 3)
  • HQC-256 (security level 5)

Valid Combinations (20 total)

The benchmark dynamically discovers valid combinations using:

  • Security level difference ≤ 2 (e.g., P-256 L1 + HQC-128 L1 ✅, P-256 L1 + ML-KEM-1024 L5 ❌)
  • RECOMMENDED status only
  • Catalog flag: allowedInComposite=true

Example combinations:

  • P-256 + HQC-128 (L1 + L1 = Δ0)
  • P-256 + HQC-192 (L1 + L3 = Δ2)
  • P-256 + ML-KEM-768 (L1 + L3 = Δ2)
  • P-384 + HQC-128 (L3 + L1 = Δ2)
  • P-384 + HQC-192 (L3 + L3 = Δ0)
  • P-384 + HQC-256 (L3 + L5 = Δ2)
  • P-384 + ML-KEM-768 (L3 + L3 = Δ0)
  • P-384 + ML-KEM-1024 (L3 + L5 = Δ2)
  • P-521 + HQC-192 (L5 + L3 = Δ2)
  • P-521 + HQC-256 (L5 + L5 = Δ0)
  • P-521 + ML-KEM-768 (L5 + L3 = Δ2)
  • P-521 + ML-KEM-1024 (L5 + L5 = Δ0)
  • X25519 + HQC-128 (L1 + L1 = Δ0)
  • X25519 + HQC-192 (L1 + L3 = Δ2)
  • X25519 + ML-KEM-768 (L1 + L3 = Δ2)
  • X448 + HQC-128 (L3 + L1 = Δ2)
  • X448 + HQC-192 (L3 + L3 = Δ0)
  • X448 + HQC-256 (L3 + L5 = Δ2)
  • X448 + ML-KEM-768 (L3 + L3 = Δ0)
  • X448 + ML-KEM-1024 (L3 + L5 = Δ2)

Measured on the earlier composite construction

The timings on this page were recorded on 2026-01-18, on the composite construction that preceded the current key combiner: one random content key was wrapped under each component. The steps under How It Works describe the current construction (two real KEMs and the NIST SP 800-227 key combiner), which moves the per-operation cost and the size of each encrypted_key. On that build an HQC-192 or HQC-256 key also carried HQC-128 material, so the HQC-192 and HQC-256 rows measure the HQC-128 parameter set. Re-run the benchmark before quoting a composite figure.

How It Works

🔁 Iteration Process

  1. Source Composite Key Generation: A source composite key is generated with:

    • Mode: COMPOSITE_KEM_COMBINE
    • Decryption Policy: ALL (both KEMs must decrypt successfully)
    • Components: classical KEM (role="classical") + PQC KEM (role="pqc")
    • Standard test parameters: 100K max usage, 365-day expiry
  2. Target Composite Key Generation: A new target composite key is generated (different key material, same algorithm combination)

  3. Initial Encryption: Create an initial JWE General JSON encrypted payload with the source composite key using streaming I/O

  4. Warm-up Loop: The system runs several streaming re-encryption operations to stabilize JIT compilation and memory allocation

  5. Measurement Loop: The following metrics are collected per iteration:

    • Wall-clock time for streaming re-encryption (milliseconds)
    • Thread-level CPU time for streaming re-encryption (milliseconds)
    • Heap memory delta during streaming re-encryption (KiB)
  6. Validation:

    • The new encrypted payload must decrypt successfully with the target composite key using streaming I/O
    • The benchmark fails the iteration if decryption returns null or mismatched data

🔐 Composite Streaming Re-Encryption Process

Streaming re-encryption operation (dual decryption + dual encryption):

  1. Parse existing JWE General JSON structure
  2. Extract source classical KEM ciphertext: ct_classical_old = header1.encrypted_key
  3. Extract source PQC KEM ciphertext: ct_pqc_old = header2.encrypted_key
  4. Decapsulate source classical shared secret: ss_classical_old = P-256.decapsulate(ct_classical_old, sk_classical_old)
  5. Decapsulate source PQC shared secret: ss_pqc_old = ML_KEM.decapsulate(ct_pqc_old, sk_pqc_old)
  6. Derive source CEK as the combiner's output: cek_old = KeyCombine(ss_classical_old, ss_pqc_old, ct_classical_old, ct_pqc_old, pk_classical_old, pk_pqc_old, domain)
  7. Initialize AES-GCM stream decipher: decipher = AES-256-GCM.initDecrypt(cek_old)
  8. Read ciphertext incrementally (chunked streaming):
    • For each chunk: plaintext_chunk = decipher.update(chunk)
  9. Verify authentication tag and finalize: final_chunk = decipher.doFinal(auth_tag)
  10. Generate a new ephemeral classical key pair for the target (the PQC encapsulation needs none)
  11. Encapsulate target classical shared secret: (ct_classical_new, ss_classical_new) = P-256.encapsulate(pk_classical_target)
  12. Encapsulate target PQC shared secret: (ct_pqc_new, ss_pqc_new) = ML_KEM.encapsulate(pk_pqc_target)
  13. Derive target CEK as the combiner's output: cek_new = KeyCombine(ss_classical_new, ss_pqc_new, ct_classical_new, ct_pqc_new, pk_classical_new, pk_pqc_new, domain)
  14. Initialize AES-GCM stream cipher: cipher = AES-256-GCM.initEncrypt(cek_new)
  15. Re-encrypt plaintext incrementally:
    • For each chunk: ciphertext_chunk_new = cipher.update(plaintext_chunk)
  16. Finalize encryption: (final_chunk_new, auth_tag_new) = cipher.doFinal()
  17. Construct new JWE General JSON with two new KEK layers
  18. Return new JWE General JSON Serialization string

🧠 Deterministic RNG

A fixed seed is used in the random number generator (0xC0FFEE_BABEFACE) to ensure reproducible test runs.

📈 Metrics Aggregation

For each metric, the median value across all measurement iterations is recorded, providing robust resistance to outliers.


Metrics Collected

For each combination of (classical_kem, pqc_kem, payload size), the following metrics are measured for streaming re-encryption:

Metric Description Units
CLASSICAL Classical KEM name (P-256, P-384, X25519, etc.) String
PQC Post-quantum KEM name (ML-KEM-768, HQC-128, etc.) String
BYTES Payload size in bytes Integer
REENC Median wall-clock time for streaming re-encryption Milliseconds
CPU-R Median thread CPU time for streaming re-encryption Milliseconds
MEM-R Median heap delta for streaming re-encryption Kibibytes

Each metric is calculated as the median across the measurement iterations to reduce the influence of transient spikes or system noise.


Execution Notes

  • Composite keys use JWE General JSON Serialization with streaming encryption for memory efficiency

  • The benchmark is implemented using JUnit 5 with @ParameterizedTest

  • All runs are sequential to avoid interference from thread scheduling (enforced via @Execution(SAME_THREAD))

  • Thread CPU-time measurement is required; the test is skipped if unavailable on the system

  • A deterministic RNG (fixed seed) ensures repeatability

  • Results are exported as a CSV file: benchmark_composite_stream_reenc_20260118_222354.csv

Streaming overhead notes: Streaming operations process data incrementally without loading entire payloads into memory, providing constant memory footprint regardless of file size. The reported heap delta reflects this memory-efficient design.

Scope of the heap delta. The figure above is a heap measurement and says nothing about disk. The disk-free property — no uploaded part written to a temporary file — is measured separately (512 MiB through -Xmx256m, zero temporary files observed in flight); see Memory & Performance*.

Payload size limitation: Re-encryption benchmarks are limited to smaller payloads (5-10 MiB) due to the computational overhead of dual decryption + dual encryption in a single operation.


Complete Results

CLASSICAL | PQC         |      BYTES |    REENC |    CPU-R |   MEM-R
----------+-------------+------------+----------+----------+---------
P-256     | HQC-128     |  5.242.880 |      213 |      203 | 169.344
P-256     | HQC-128     | 10.485.760 |      368 |      359 | 120.899
P-256     | HQC-192     |  5.242.880 |      236 |      234 | 169.344
P-256     | HQC-192     | 10.485.760 |      400 |      390 | 233.152
P-256     | ML-KEM-768  |  5.242.880 |      206 |      195 |  54.817
P-256     | ML-KEM-768  | 10.485.760 |      363 |      343 | 175.232
P-384     | HQC-128     |  5.242.880 |      259 |      250 | 169.344
P-384     | HQC-128     | 10.485.760 |      496 |      468 | 154.590
P-384     | HQC-192     |  5.242.880 |      260 |      250 | 169.344
P-384     | HQC-192     | 10.485.760 |      469 |      453 | 347.136
P-384     | HQC-256     |  5.242.880 |      259 |      250 | 169.344
P-384     | HQC-256     | 10.485.760 |      320 |      320 | 347.136
P-384     | ML-KEM-1024 |  5.242.880 |      220 |      218 | 169.344
P-384     | ML-KEM-1024 | 10.485.760 |      468 |      453 | 347.136
P-384     | ML-KEM-768  |  5.242.880 |      221 |      218 | 169.344
P-384     | ML-KEM-768  | 10.485.760 |      421 |      390 | 120.643
P-521     | HQC-192     |  5.242.880 |      234 |      218 | 169.344
P-521     | HQC-192     | 10.485.760 |      408 |      406 | 347.136
P-521     | HQC-256     |  5.242.880 |      231 |      218 | 169.344
P-521     | HQC-256     | 10.485.760 |      294 |      288 | 347.136
P-521     | ML-KEM-1024 |  5.242.880 |      215 |      203 | 169.344
P-521     | ML-KEM-1024 | 10.485.760 |      422 |      421 | 347.136
P-521     | ML-KEM-768  |  5.242.880 |      230 |      218 | 169.344
P-521     | ML-KEM-768  | 10.485.760 |      390 |      382 | 347.136
X25519    | HQC-128     |  5.242.880 |      192 |      187 | 161.152
X25519    | HQC-128     | 10.485.760 |      417 |      413 | 338.944
X25519    | HQC-192     |  5.242.880 |      232 |      218 | 161.152
X25519    | HQC-192     | 10.485.760 |      407 |      390 | 338.944
X25519    | ML-KEM-768  |  5.242.880 |      153 |      156 | 161.152
X25519    | ML-KEM-768  | 10.485.760 |      284 |      281 | 338.944
X448      | HQC-128     |  5.242.880 |      209 |      203 | 161.152
X448      | HQC-128     | 10.485.760 |      397 |      390 | 338.944
X448      | HQC-192     |  5.242.880 |      209 |      203 | 161.152
X448      | HQC-192     | 10.485.760 |      373 |      359 | 338.944
X448      | HQC-256     |  5.242.880 |      206 |      195 | 161.152
X448      | HQC-256     | 10.485.760 |      365 |      343 | 338.944
X448      | ML-KEM-1024 |  5.242.880 |      220 |      218 | 161.152
X448      | ML-KEM-1024 | 10.485.760 |      404 |      390 | 338.944
X448      | ML-KEM-768  |  5.242.880 |      247 |      234 | 161.152
X448      | ML-KEM-768  | 10.485.760 |      422 |      406 | 338.944
----------+-------------+------------+----------+----------+---------

Summary Statistics:

  • Total combinations tested: 20 (5 classical × 5 PQC KEMs, filtered by security level constraints)
  • Total measurements: 40 (20 combinations × 2 payload sizes)
  • Total bytes processed: 314,572,800 bytes (~315 MB)
  • Total re-encryption time: 12.340 ms (cumulative across all measurements)
  • Median streaming re-encryption time: 258 ms (across all measurements)

Performance Observations

Based on benchmark results with default settings (5 warm-up, 10 measurement iterations):

✅ Memory-Efficient Composite Key Rotation

Composite streaming re-encryption operations demonstrate exceptional memory efficiency for large files:

  • 5 MiB payloads: Consistent heap delta (~54-170 KiB) across all combinations
  • 10 MiB payloads: Predictable heap delta (~120-350 KiB) regardless of KEM type
  • Memory safety: Constant memory footprint enables key rotation on arbitrarily large files

🔍 Algorithm Characteristics

Fastest streaming re-encryption combinations:

  • X25519 + ML-KEM-768: ~153-284ms (5-10 MiB payloads)
  • X25519 + HQC-128: ~192-417ms (5-10 MiB payloads)
  • P-256 + ML-KEM-768: ~206-363ms (5-10 MiB payloads)

Performance by KEM family:

  • Montgomery curves (X25519, X448): Consistently fastest with minimal heap overhead
  • NIST curves (P-256, P-384, P-521): Balanced performance across all payload sizes
  • ML-KEM combinations: Excellent scalability with moderate memory usage
  • HQC combinations: Competitive performance with larger payloads

📊 Scalability

  • Near-linear scaling with payload size (dominated by dual streaming decryption + dual streaming encryption)
  • Memory efficiency: Heap deltas remain sub-linear with payload growth
  • Optimal for large files: Composite streaming re-encryption maintains acceptable performance for 10+ MiB payloads

🚀 Production Readiness

Composite streaming re-encryption operations are production-ready for quantum-resistant key rotation on large files:

  • Key lifecycle management: Acceptable latency for rotating composite keys on large documents
  • Certificate renewal: Suitable for dual-KEM certificate re-issuance on large files
  • Quantum migration: Practical performance for transitioning between composite key pairs with large payloads
  • Defense-in-depth: Provides quantum resistance with minimal streaming overhead

Comparison to Compact Mode Composite Re-Encryption

Operation Compact Mode (P-256 + ML-KEM-768, 1 MiB) Streaming Mode (P-256 + ML-KEM-768, 5 MiB) Performance
Re-encryption ~67ms ~206ms ~5× larger payload, ~3.1× time (sub-linear!)
Memory 16.384 KiB 54.817 KiB ~3.3× more (still efficient)

Key insight: Streaming mode provides better scalability for large payloads with acceptable memory overhead.


Comparison to Single-KEM Streaming Re-Encryption

Operation Single KEM (X25519) Composite (X25519 + ML-KEM-768) Overhead
5 MiB re-encryption ~98ms ~153ms ~1.6×
10 MiB re-encryption ~187ms ~284ms ~1.5×

Key insight: Composite streaming re-encryption overhead is modest (~1.5-1.6×) compared to single-KEM operations, providing quantum resistance with acceptable performance cost.


Test Execution

Running the Benchmark

Default settings (5 warm-up, 10 measurement iterations):

cd ankasecure-core-api
mvn test -Dtest=SCPerformanceEnhancedStreamingCompositeReencryptionTest

Custom iteration counts:

mvn test -Dtest=SCPerformanceEnhancedStreamingCompositeReencryptionTest \
  -Dsc.perf.warmup=10 \
  -Dsc.perf.measurements=20

Expected runtime: ~7-10 minutes with default settings

Output Location

CSV file exported to:

/tmp/sc_bench_<random>/benchmark_composite_stream_reenc_YYYYMMDD_HHMMSS.csv

Console output shows ASCII table with all measurements sorted by (CLASSICAL, PQC, BYTES).


CSV Data Format

The exported CSV file contains the following columns:

CLASSICAL,PQC,BYTES,REENC_MS,CPU_REENC_MS,REENC_MEM_KIB
P-256,HQC-128,5242880,213,203,169344
P-256,HQC-128,10485760,368,359,120899
...

Use cases:

  • Import into spreadsheet tools (Excel, Google Sheets) for analysis
  • Generate charts and visualizations
  • Statistical analysis (percentiles, distributions)
  • Regression testing (compare across versions)


Implementation Details

Test class: SCPerformanceEnhancedStreamingCompositeReencryptionTest.java

Location: ankasecure-core-api/src/test/java/co/ankatech/ankasecure/core/controller/

Key dependencies:

  • SecureCoreTestHelper.getValidKemCombinations() - Dynamic combination discovery
  • SecureCoreTestHelper.generateCompositeKey() - Composite key generation
  • SecureCoreController.reencryptCompositeDataStreamJwe() - Composite JWE streaming re-encryption operation

Thread safety: Single-threaded execution (@Execution(SAME_THREAD))

Lifecycle: Per-class instance (@TestInstance(Lifecycle.PER_CLASS))


Security Considerations

✅ Defense-in-Depth

Composite streaming re-encryption maintains dual-layer security throughout key rotation on large files:

  • Classical KEM validation protects against current threats
  • PQC KEM validation protects against future quantum threats
  • Dual decryption requirement ensures both KEMs must succeed before re-encryption

✅ Algorithm Diversity

Combining different algorithm families (ECDH + lattice-based/code-based) reduces risk during key rotation:

  • X25519/X448/P-curves: Discrete logarithm problem (DLP) hardness
  • ML-KEM: Module-LWE (Learning With Errors) hardness
  • HQC: Syndrome decoding hardness

✅ Memory Safety

Streaming operations ensure constant or sub-linear memory usage regardless of file size, preventing memory exhaustion attacks during key rotation.


Conclusion

This benchmark provides strong, reproducible evidence that SecureCore's composite streaming re-encryption operations:

  • Efficiently support quantum-resistant key rotation on large files with minimal memory footprint across a wide variety of hybrid classical+PQC KEM combinations.

  • Perform reliably and predictably across payload sizes from 5 MiB to 10 MiB, with linear or sub-linear performance scaling.

  • Offer exceptional memory efficiency critical for key rotation in cloud, enterprise, and archival environments.

  • Demonstrate that composite key rotation is production-ready for large-scale streaming scenarios with performance overhead of only ~1.5-1.6× compared to single-KEM operations.

These results demonstrate SecureCore's readiness for quantum-safe key rotation on large files, regulatory compliance, and future-proof cryptographic agility in enterprise key management scenarios.


Changelog

Date Change Author
2026-01-18 Created composite streaming re-encryption performance benchmark ANKASecure Performance Team
2026-01-18 Validated 20 COMPOSITE_KEM_COMBINE combinations across 40 streaming measurements ANKASecure Performance Team
* restricted content — see higher-tier documentation