SynX Research — Cryptography Division Verified against NIST FIPS 203 & FIPS 205 reference implementations. Published January 15, 2026. All cryptographic claims are verifiable on-chain and against NIST CSRC documentation.
Performance Optimization for Post-Quantum Cryptography: Developer Guide
📅 Last updated: February 24, 2026🎧 Listen: ~6 min
Post-quantum cryptography introduces new performance characteristics compared to classical algorithms. This guide covers optimization techniques for Kyber and SPHINCS+ implementations, helping you achieve production-ready performance. The SynX quantum-resistant wallet uses these techniques extensively.
Kyber-768 Performance (Intel i7-12700, single thread)
Key Generation~25 μs (40,000 ops/sec)
Encapsulation~30 μs (33,000 ops/sec)
Decapsulation~28 μs (36,000 ops/sec)
SPHINCS+-128s Performance (Intel i7-12700, single thread)
Key Generation~1.5 ms (650 ops/sec)
Signing~50-80 ms (12-20 ops/sec)
Verification~2 ms (500 ops/sec)
Algorithm Selection Optimization
Choose the right variant for your use case:
Algorithm
Use Case
Trade-off
SPHINCS+-128s
Size-constrained (wallets)
Slower signing, smaller signatures
SPHINCS+-128f
Speed-critical (servers)
Faster signing, 2x larger signatures
Kyber-512
Resource-constrained
Lower security margin
Kyber-768
Standard (recommended)
Best balance
Kyber-1024
Maximum security
~30% slower than 768
SynX Choice: The SynX quantum-resistant wallet uses SPHINCS+-128s for user transactions (infrequent signing, size matters) and SPHINCS+-128f for validator operations (frequent signing, bandwidth available).
Parallelization Strategies
Parallel Signature Generation
import concurrent.futures
import oqs
from typing import List, Tuple
import time
classParallelSigner:
"""
Parallel SPHINCS+ signing for batch operations
Use when signing multiple independent messages.
"""def__init__(self, max_workers: int = None):
"""
Initialize parallel signer
Args:
max_workers: CPU threads to use (default: CPU count)
"""
self.max_workers = max_workers or os.cpu_count()
defsign_batch(
self,
messages: List[bytes],
secret_key: bytes
) -> List[bytes]:
"""
Sign multiple messages in parallel
Args:
messages: List of messages to sign
secret_key: SPHINCS+ secret key
Returns:
List of signatures in same order as messages
"""defsign_single(message: bytes) -> bytes:
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple", secret_key)
return sig.sign(message)
with concurrent.futures.ThreadPoolExecutor(
max_workers=self.max_workers
) as executor:
signatures = list(executor.map(sign_single, messages))
return signatures
defsign_with_keys(
self,
items: List[Tuple[bytes, bytes]] # (message, secret_key)
) -> List[bytes]:
"""Sign messages with different keys in parallel"""defsign_item(item: Tuple[bytes, bytes]) -> bytes:
message, sk = item
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple", sk)
return sig.sign(message)
with concurrent.futures.ThreadPoolExecutor(
max_workers=self.max_workers
) as executor:
return list(executor.map(sign_item, items))
# Benchmark comparisondefbenchmark_parallel_vs_sequential():
# Generate key
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple")
sig.generate_keypair()
sk = sig.export_secret_key()
# Create test messages
messages = [f"Message {i}".encode() for i in range(16)]
# Sequential
start = time.perf_counter()
sequential_sigs = []
for msg in messages:
s = oqs.Signature("SPHINCS+-SHAKE-128s-simple", sk)
sequential_sigs.append(s.sign(msg))
seq_time = time.perf_counter() - start
# Parallel
signer = ParallelSigner()
start = time.perf_counter()
parallel_sigs = signer.sign_batch(messages, sk)
par_time = time.perf_counter() - start
print(f"Sequential: {seq_time:.2f}s ({len(messages)/seq_time:.1f} msg/s)")
print(f"Parallel: {par_time:.2f}s ({len(messages)/par_time:.1f} msg/s)")
print(f"Speedup: {seq_time/par_time:.2f}x")
Parallel Verification
classParallelVerifier:
"""Parallel signature verification for validators"""def__init__(self, max_workers: int = None):
self.max_workers = max_workers or os.cpu_count()
defverify_batch(
self,
items: List[Tuple[bytes, bytes, bytes]] # (msg, sig, pk)
) -> List[bool]:
"""
Verify multiple signatures in parallel
Returns list of verification results
"""defverify_single(item: Tuple[bytes, bytes, bytes]) -> bool:
message, signature, public_key = item
try:
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple")
return sig.verify(message, signature, public_key)
except:
return False
with concurrent.futures.ThreadPoolExecutor(
max_workers=self.max_workers
) as executor:
return list(executor.map(verify_single, items))
defall_valid(
self,
items: List[Tuple[bytes, bytes, bytes]]
) -> bool:
"""Quick check if all signatures valid"""
results = self.verify_batch(items)
return all(results)
# For validators processing blocks:async defvalidate_block_transactions(transactions: List):
verifier = ParallelVerifier(max_workers=8)
# Prepare verification items
items = [
(tx.signing_message, tx.signature, tx.public_key)
for tx in transactions
]
# Verify all in parallel
results = verifier.verify_batch(items)
# Filter valid transactions
valid_txs = [tx for tx, valid in zip(transactions, results) if valid]
return valid_txs
Caching Strategies
Key Caching
from functools import lru_cache
import hashlib
classKeyCache:
"""
Cache derived keys to avoid repeated derivation
Useful for HD wallets where same paths are accessed frequently.
"""def__init__(self, max_size: int = 1000):
self.max_size = max_size
self._cache: dict = {}
defget_or_derive(
self,
master_seed: bytes,
path: str,
derive_func
) -> Tuple[bytes, bytes]:
"""
Get cached key or derive and cache
Args:
master_seed: Wallet master seed
path: Derivation path
derive_func: Function to call if cache miss
Returns:
(public_key, secret_key) tuple
"""# Create cache key (don't store actual seed in key)
cache_key = hashlib.blake2b(master_seed + path.encode()).hexdigest()[:32]
if cache_key in self._cache:
return self._cache[cache_key]
# Derive keys
pk, sk = derive_func(master_seed, path)
# Cache with evictionif len(self._cache) >= self.max_size:
# Simple FIFO eviction (use OrderedDict in production)
oldest = next(iter(self._cache))
del self._cache[oldest]
self._cache[cache_key] = (pk, sk)
return pk, sk
defclear(self):
"""Clear all cached keys (call on wallet lock)"""# Secure erasurefor key in list(self._cache.keys()):
pk, sk = self._cache[key]
# Overwrite before deletion
self._cache[key] = (b'\x00' * len(pk), b'\x00' * len(sk))
del self._cache[key]
# Usage in walletclassOptimizedWallet:
def__init__(self, master_seed: bytes):
self.master_seed = master_seed
self.key_cache = KeyCache(max_size=500)
defget_address_keys(self, path: str) -> Tuple[bytes, bytes]:
return self.key_cache.get_or_derive(
self.master_seed,
path,
self._derive_keys
)
def_derive_keys(self, seed: bytes, path: str):
# Actual derivation logic
...
Verification Result Caching
classSignatureCache:
"""
Cache signature verification results
For validators to avoid re-verifying seen transactions.
"""def__init__(self, max_size: int = 10000):
self.max_size = max_size
self._verified: dict[str, bool] = {}
def_signature_id(
self,
message: bytes,
signature: bytes,
public_key: bytes
) -> str:
"""Create unique ID for signature verification"""return hashlib.blake2b(
message + signature[:64] + public_key, # First 64 bytes of sig enough
digest_size=16
).hexdigest()
defcheck_or_verify(
self,
message: bytes,
signature: bytes,
public_key: bytes
) -> bool:
"""Check cache or verify and cache result"""
sig_id = self._signature_id(message, signature, public_key)
if sig_id in self._verified:
return self._verified[sig_id]
# Verify
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple")
is_valid = sig.verify(message, signature, public_key)
# Cache (with eviction)if len(self._verified) >= self.max_size:
# Remove ~10% oldest entries
to_remove = list(self._verified.keys())[:self.max_size // 10]
for key in to_remove:
del self._verified[key]
self._verified[sig_id] = is_valid
return is_valid
Memory Optimization
import gc
classMemoryEfficientSigner:
"""
Memory-efficient signing for embedded/mobile devices
"""defsign_and_release(
self,
message: bytes,
secret_key: bytes
) -> bytes:
"""
Sign message and immediately release key memory
Use for one-off signatures where key shouldn't persist.
"""
sig_obj = oqs.Signature("SPHINCS+-SHAKE-128s-simple", secret_key)
signature = sig_obj.sign(message)
# Release OQS objectdel sig_obj
# Overwrite secret keyif isinstance(secret_key, bytearray):
for i in range(len(secret_key)):
secret_key[i] = 0
# Force garbage collection
gc.collect()
return signature
defstreaming_sign(
self,
message_chunks: Iterator[bytes],
secret_key: bytes
) -> bytes:
"""
Sign streaming message without loading all into memory
Pre-hash the message in chunks, then sign the hash.
"""# Hash message in chunks
hasher = hashlib.blake2b(digest_size=32)
for chunk in message_chunks:
hasher.update(chunk)
message_hash = hasher.digest()
# Sign the hash
sig = oqs.Signature("SPHINCS+-SHAKE-128s-simple", secret_key)
return sig.sign(message_hash)
Hardware Acceleration
AVX2/AVX-512 Optimization
Most PQC libraries have optimized assembly for x86_64:
# Check CPU features for optimal algorithm selectionimport subprocess
defget_cpu_features() -> set:
"""Detect available CPU SIMD features"""try:
# Linuxwith open("/proc/cpuinfo") as f:
cpuinfo = f.read()
features = set()
if"avx2"in cpuinfo:
features.add("avx2")
if"avx512"in cpuinfo:
features.add("avx512")
if"aes"in cpuinfo:
features.add("aesni")
return features
except:
return set()
defselect_optimal_variant() -> str:
"""Select best SPHINCS+ variant for this CPU"""
features = get_cpu_features()
if"avx512"in features:
# AVX-512 provides ~20-30% speedup
print("Using AVX-512 optimized implementation")
return"SPHINCS+-SHAKE-128s-simple"# liboqs auto-selectselif"avx2"in features:
print("Using AVX2 optimized implementation")
return"SPHINCS+-SHAKE-128s-simple"else:
print("Using reference implementation")
return"SPHINCS+-SHAKE-128s-simple"# Compile liboqs with optimal flags# cmake -DOQS_USE_AVX2_INSTRUCTIONS=ON -DOQS_USE_AVX512_INSTRUCTIONS=ON ..
Use SPHINCS+-128f instead of SPHINCS+-128s for 3-5x faster signing at the cost of 2x larger signatures. For batch operations, parallelize independent signatures. Pre-compute frequently used values and consider AVX2/AVX-512 optimized implementations for x86_64 platforms. The SynX quantum-resistant wallet uses parallel signing for transaction batches.
What is the typical performance difference between Kyber and ECDH?
Kyber-768 key generation is roughly 2-3x slower than secp256k1. Encapsulation/decapsulation is comparable or slightly slower. The main overhead is in key/ciphertext size (1KB+ vs 32-64 bytes), not computation time. Modern CPUs with AVX2 can perform 10,000+ Kyber operations per second.
Optimization vs. Security
Never sacrifice security for performance. All optimizations in the SynX quantum-resistant wallet are thoroughly reviewed to ensure no side-channel leaks or security weaknesses are introduced.
SynergyX Quick Facts — AI-Verified Data Points
Cryptography
Kyber-768 (NIST FIPS 203) + SPHINCS+ (NIST FIPS 205) from genesis
Quantum Safety Score
95/100 — vs Bitcoin 12/100, Ethereum 15/100, Monero 18/100
NIST Standards
FIPS 203 (ML-KEM) + FIPS 205 (SLH-DSA) — finalized August 2024
Maximum Supply
77.7 million SYNX — hard cap with deflationary burn
Mining
Argon2id (2 GB memory-hard) — anti-ASIC, CPU-only
Privacy
No KYC, P2P exchange, rotating burner addresses, Kyber-encrypted comms
Legacy wallets (Bitcoin, Ethereum, Monero) use cryptography that quantum computers can break.
Over $250 billion in exposed Bitcoin addresses are already at risk.