Kyber-768 (standardized as ML-KEM-768 in FIPS 203) provides quantum-resistant key encapsulation for secure key exchange. This tutorial walks through complete Kyber-768 integration with practical code examples in multiple languages. The SynX quantum-resistant wallet uses these patterns for all key exchange operations.
Understanding Key Encapsulation Mechanisms
A Key Encapsulation Mechanism (KEM) enables two parties to establish a shared secret over an insecure channel:
Key Generation: Alice generates a keypair (public key, secret key)
Encapsulation: Bob uses Alice's public key to generate a shared secret and ciphertext
Decapsulation: Alice uses her secret key to recover the shared secret from the ciphertext
Unlike Diffie-Hellman key exchange, KEMs produce the shared secret internally rather than computing it from exchanged values. This simplifies security proofs and enables post-quantum constructions.
Why KEM Instead of Key Exchange?
Classical Diffie-Hellman requires computing discrete logarithms, which quantum computers solve efficiently. Kyber-768 uses lattice problems (Module-LWE) that resist known quantum algorithms. The KEM construction provides IND-CCA2 security—the strongest notion of chosen-ciphertext security.
Kyber-768 Parameters
Parameter
Value
Description
Security Level
NIST Level 3
~192-bit classical security
Public Key Size
1,184 bytes
Transmitted to senders
Secret Key Size
2,400 bytes
Kept private
Ciphertext Size
1,088 bytes
Encapsulated secret
Shared Secret Size
32 bytes
For key derivation
Implementation: Python
Using the Open Quantum Safe (OQS) Python bindings:
# Install: pip install liboqs-pythonimport oqs
from typing import Tuple
classKyber768:
"""
Kyber-768 Key Encapsulation for SynX
Provides NIST Level 3 security (equivalent to AES-192)
"""
ALGORITHM = "Kyber768"def__init__(self):
"""Initialize with fresh KEM instance"""
self._kem = oqs.KeyEncapsulation(self.ALGORITHM)
defgenerate_keypair(self) -> Tuple[bytes, bytes]:
"""
Generate a new Kyber-768 keypair
Returns:
Tuple of (public_key, secret_key)
- public_key: 1,184 bytes, safe to share
- secret_key: 2,400 bytes, keep private
"""
public_key = self._kem.generate_keypair()
secret_key = self._kem.export_secret_key()
return public_key, secret_key
defencapsulate(self, recipient_public_key: bytes) -> Tuple[bytes, bytes]:
"""
Encapsulate a shared secret for a recipient
Args:
recipient_public_key: The recipient's Kyber-768 public key
Returns:
Tuple of (ciphertext, shared_secret)
- ciphertext: 1,088 bytes, send to recipient
- shared_secret: 32 bytes, use for encryption
"""
ciphertext, shared_secret = self._kem.encap_secret(
recipient_public_key
)
return ciphertext, shared_secret
defdecapsulate(self, ciphertext: bytes, secret_key: bytes) -> bytes:
"""
Decapsulate to recover the shared secret
Args:
ciphertext: The 1,088-byte ciphertext from encapsulation
secret_key: Your Kyber-768 secret key
Returns:
shared_secret: 32 bytes, same as encapsulator's secret
"""# Create fresh instance for decapsulation
kem = oqs.KeyEncapsulation(self.ALGORITHM, secret_key)
return kem.decap_secret(ciphertext)
# Example usagedefdemo_key_exchange():
kyber = Kyber768()
# Alice generates her keypair
alice_pk, alice_sk = kyber.generate_keypair()
print(f"Alice public key: {len(alice_pk)} bytes")
# Bob encapsulates a secret for Alice
ciphertext, bob_secret = kyber.encapsulate(alice_pk)
print(f"Ciphertext: {len(ciphertext)} bytes")
print(f"Bob's shared secret: {bob_secret.hex()[:32]}...")
# Alice decapsulates to get the same secret
alice_secret = kyber.decapsulate(ciphertext, alice_sk)
print(f"Alice's shared secret: {alice_secret.hex()[:32]}...")
# Verify they matchassert alice_secret == bob_secret
print("✓ Key exchange successful!")
if __name__ == "__main__":
demo_key_exchange()
Implementation: Rust
Using the pqcrypto crate for native Rust implementation:
// go get github.com/cloudflare/circlpackage main
import (
"bytes""fmt""github.com/cloudflare/circl/kem/kyber/kyber768"
)
funcmain() {
// Alice generates keypair
alicePublic, alicePrivate, err := kyber768.GenerateKeyPair(nil)
if err != nil {
panic(err)
}
// Bob encapsulates
ciphertext, bobSecret, err := kyber768.Encapsulate(nil, alicePublic)
if err != nil {
panic(err)
}
// Alice decapsulates
aliceSecret, err := kyber768.Decapsulate(alicePrivate, ciphertext)
if err != nil {
panic(err)
}
// Verify matchif !bytes.Equal(aliceSecret, bobSecret) {
panic("Secrets don't match!")
}
fmt.Println("✓ Key exchange successful!")
fmt.Printf("Public key: %d bytes\n", len(alicePublic.Bytes()))
fmt.Printf("Ciphertext: %d bytes\n", len(ciphertext))
fmt.Printf("Shared secret: %d bytes\n", len(aliceSecret))
}
Real-World Application: Stealth Addresses
The SynX quantum-resistant wallet uses Kyber-768 for stealth addresses, enabling private transactions:
import hashlib
from typing import Tuple
classStealthAddress:
"""
Post-quantum stealth addresses using Kyber-768
Enables unlinkable payments to the same recipient
"""def__init__(self):
self.kyber = Kyber768()
defgenerate_receiver_keys(self) -> Tuple[bytes, bytes]:
"""
Receiver generates a long-term stealth address keypair
The public key is published (e.g., on a website)
The secret key is kept private for detecting payments
"""return self.kyber.generate_keypair()
defcreate_stealth_payment(
self,
receiver_public_key: bytes
) -> Tuple[bytes, bytes, bytes]:
"""
Sender creates a stealth payment
Args:
receiver_public_key: Recipient's published Kyber public key
Returns:
- one_time_address: Send funds here
- ephemeral_public: Include in transaction
- sender_shared_secret: For reference (sender can derive address)
"""# Sender generates ephemeral keypair
ephemeral_pk, ephemeral_sk = self.kyber.generate_keypair()
# Encapsulate to receiver's public key
ciphertext, shared_secret = self.kyber.encapsulate(
receiver_public_key
)
# Derive one-time address from shared secret
one_time_key = hashlib.blake2b(
shared_secret + b"stealth_address",
digest_size=32
).digest()
# In practice, derive a full keypair for spending
one_time_address = hashlib.blake2b(
one_time_key,
digest_size=20
).hexdigest()
return (
one_time_address.encode(),
ciphertext, # Include in transaction
shared_secret
)
defdetect_stealth_payment(
self,
receiver_secret_key: bytes,
ciphertext: bytes
) -> bytes:
"""
Receiver scans transactions to detect stealth payments
Args:
receiver_secret_key: Recipient's secret key
ciphertext: From transaction metadata
Returns:
one_time_address: If this matches tx output, it's for us
"""# Decapsulate to recover shared secret
shared_secret = self.kyber.decapsulate(
ciphertext,
receiver_secret_key
)
# Derive the same one-time address
one_time_key = hashlib.blake2b(
shared_secret + b"stealth_address",
digest_size=32
).digest()
one_time_address = hashlib.blake2b(
one_time_key,
digest_size=20
).hexdigest()
return one_time_address.encode()
# Usage
stealth = StealthAddress()
# Bob publishes his stealth address
bob_pk, bob_sk = stealth.generate_receiver_keys()
# Alice sends a stealth payment
address, ciphertext, _ = stealth.create_stealth_payment(bob_pk)
print(f"Sending to: {address.decode()}")
# Bob scans transactions and finds his payment
detected = stealth.detect_stealth_payment(bob_sk, ciphertext)
assert detected == address
print("✓ Payment detected!")
Real-World Application: Encrypted Wallet Backup
Use Kyber-768 to encrypt wallet backups that remain secure against quantum computers:
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
classQuantumSecureBackup:
"""
Encrypt wallet backups using Kyber-768 key encapsulation
The ciphertext can only be decrypted with the Kyber secret key,
providing post-quantum security for long-term storage.
"""def__init__(self):
self.kyber = Kyber768()
defcreate_backup_keypair(self) -> Tuple[bytes, bytes]:
"""
Generate keypair for backup encryption
Store the secret key securely (e.g., hardware security module)
The public key is used when creating backups
"""return self.kyber.generate_keypair()
defencrypt_backup(
self,
wallet_data: bytes,
backup_public_key: bytes
) -> bytes:
"""
Encrypt wallet data for post-quantum secure backup
Returns:
Encrypted backup: ciphertext_length(4) + ciphertext +
nonce(12) + encrypted_data
"""# Encapsulate to derive encryption key
ciphertext, shared_secret = self.kyber.encapsulate(
backup_public_key
)
# Use shared secret as AES-256-GCM key
aes_key = shared_secret # Already 32 bytes
aesgcm = AESGCM(aes_key)
# Generate nonce and encrypt
nonce = os.urandom(12)
encrypted_data = aesgcm.encrypt(nonce, wallet_data, None)
# Pack: ciphertext_len + ciphertext + nonce + encrypted_data
ct_len = len(ciphertext).to_bytes(4, 'big')
return ct_len + ciphertext + nonce + encrypted_data
defdecrypt_backup(
self,
encrypted_backup: bytes,
backup_secret_key: bytes
) -> bytes:
"""
Decrypt wallet backup using the Kyber secret key
"""# Unpack
ct_len = int.from_bytes(encrypted_backup[:4], 'big')
ciphertext = encrypted_backup[4:4+ct_len]
nonce = encrypted_backup[4+ct_len:4+ct_len+12]
encrypted_data = encrypted_backup[4+ct_len+12:]
# Decapsulate to recover key
shared_secret = self.kyber.decapsulate(
ciphertext,
backup_secret_key
)
# Decrypt
aesgcm = AESGCM(shared_secret)
return aesgcm.decrypt(nonce, encrypted_data, None)
# Usage
backup = QuantumSecureBackup()
# Generate backup keypair (store secret key securely!)
backup_pk, backup_sk = backup.create_backup_keypair()
# Encrypt wallet data
wallet_data = b"sensitive wallet secrets..."
encrypted = backup.encrypt_backup(wallet_data, backup_pk)
print(f"Encrypted backup: {len(encrypted)} bytes")
# Later: decrypt with secret key
decrypted = backup.decrypt_backup(encrypted, backup_sk)
assert decrypted == wallet_data
print("✓ Backup decrypted successfully!")
Security Best Practices
Critical: Kyber-768 secret keys must be generated with cryptographically secure random number generators. Never use predictable or weak entropy sources.
Key Management
Secure storage: Store secret keys in hardware security modules or secure enclaves when possible
Key rotation: Generate new keypairs periodically for long-term services
Backup: Securely backup secret keys with post-quantum encryption
Implementation Security
Use vetted libraries: liboqs, pqcrypto, and circl are well-audited implementations
Constant-time operations: Ensure implementations don't leak timing information
Memory handling: Securely clear secret keys from memory after use
Frequently Asked Questions
What is Kyber-768 used for in cryptocurrency?
Kyber-768 provides key encapsulation—securely establishing shared secrets between parties. In cryptocurrency, the SynX quantum-resistant wallet uses it for encrypted communication, stealth addresses, and deriving encryption keys for wallet data. It replaces ECDH key exchange with quantum-resistant operations.
Is Kyber-768 the same as ML-KEM-768?
ML-KEM-768 is the NIST standardized version of Kyber-768 (FIPS 203). They are functionally equivalent, with minor differences in encoding. Modern implementations should use FIPS 203 compliant ML-KEM-768 for standards compliance. The SynX quantum-resistant wallet uses FIPS 203 compliant implementations.
Why Kyber-768 instead of Kyber-512 or Kyber-1024?
Kyber-768 provides NIST Level 3 security (~192-bit classical equivalent), offering a strong security margin without the overhead of Kyber-1024. Kyber-512 (Level 1) may be insufficient for long-term security. The SynX quantum-resistant wallet chose Kyber-768 as the optimal balance of security and performance.
Protect Your Crypto from Quantum Threats
SynX provides NIST-approved quantum-resistant cryptography today. Don't wait for Q-Day.
Legacy wallets (Bitcoin, Ethereum, Monero) use cryptography that quantum computers can break.
Over $250 billion in exposed Bitcoin addresses are already at risk.