ML-KEM-512 Security API

Version: 1.0.0
Last Updated: 2025-01-02
Security Classification: High Security KEM
Author: MetaMUI Security Team

Overview

ML-KEM-512 (Module-Lattice Key Encapsulation Mechanism) is a NIST-standardized post-quantum key encapsulation mechanism based on the hardness of the Module Learning With Errors (MLWE) problem. It provides NIST security level 1 (128-bit classical security).

Security Warnings ⚠️

  1. State Management: Never reuse encapsulation randomness
  2. Key Generation: Must use cryptographically secure random source
  3. Side Channels: Implementation must be constant-time
  4. Decapsulation: Must use implicit rejection to prevent chosen-ciphertext attacks

API Functions

Key Generation

def ml_kem_512_keygen() -> Tuple[PublicKey, SecretKey]:
    """
    Generate ML-KEM-512 keypair
    
    Security Contract:
    - Uses system CSPRNG for randomness
    - Constant-time polynomial operations
    - Keys are valid for 2^64 encapsulations
    
    Returns:
        (public_key, secret_key) tuple
    """

Attack Resistance:

Attack Type Protection Level Implementation Requirement
Timing Attacks Full Constant-time NTT operations
Power Analysis Partial Hardware-dependent countermeasures
Fault Injection Limited Input validation required
Quantum Attacks 128-bit MLWE hardness assumption

Encapsulation

def ml_kem_512_encaps(public_key: PublicKey) -> Tuple[Ciphertext, SharedSecret]:
    """
    Encapsulate to generate shared secret
    
    Security Contract:
    - Fresh randomness for each encapsulation
    - No information leakage through ciphertext
    - Binding between ciphertext and shared secret
    
    Args:
        public_key: Recipient's public key
        
    Returns:
        (ciphertext, shared_secret) tuple
    """

Security Requirements:

Decapsulation

def ml_kem_512_decaps(ciphertext: Ciphertext, secret_key: SecretKey) -> SharedSecret:
    """
    Decapsulate to recover shared secret
    
    Security Contract:
    - Implicit rejection for invalid ciphertexts
    - Constant-time execution regardless of validity
    - No oracle information through timing
    
    Args:
        ciphertext: Received ciphertext
        secret_key: Recipient's secret key
        
    Returns:
        shared_secret: 32-byte shared secret
    """

Common Mistakes:

Implementation Examples

Secure Usage (Rust)

use metamui_mlkem512::{keypair, encapsulate, decapsulate};
use zeroize::Zeroize;

fn secure_kem_exchange() -> Result<(), Error> {
    // Generate keypair with secure RNG
    let (pk, mut sk) = keypair()?;
    
    // Encapsulation
    let (ct, mut ss_sender) = encapsulate(&pk)?;
    
    // Decapsulation with implicit rejection
    let mut ss_receiver = decapsulate(&ct, &sk)?;
    
    // Use shared secrets
    assert_eq!(ss_sender, ss_receiver);
    
    // Clean up sensitive data
    sk.zeroize();
    ss_sender.zeroize();
    ss_receiver.zeroize();
    
    Ok(())
}

Secure Usage (Python)

from metamui_mlkem512 import keygen, encaps, decaps
import secrets

def secure_kem_exchange():
    # Generate keypair
    pk, sk = keygen()
    
    # Encapsulation
    ct, ss_sender = encaps(pk)
    
    # Decapsulation
    ss_receiver = decaps(ct, sk)
    
    # Verify shared secret
    assert secrets.compare_digest(ss_sender, ss_receiver)
    
    # Clear sensitive data
    del sk, ss_sender, ss_receiver

Security Best Practices

Integration Guidelines

  1. Hybrid Security: Combine with classical ECDH for defense in depth
  2. Key Storage: Use hardware security modules when available
  3. Randomness: Ensure CSPRNG is properly seeded
  4. Protocol Design: Use ML-KEM-512 only for key encapsulation, not encryption

Performance vs Security Trade-offs

Configuration Security Performance Use Case
ML-KEM-512 Level 1 Fastest General use, TLS
ML-KEM-768 Level 3 Moderate High-value targets
ML-KEM-1024 Level 5 Slowest Long-term security

Security Auditing

Verification Checklist

Common Vulnerabilities

  1. CVE-2023-XXXX: Timing leak in polynomial multiplication (fixed in v1.0.0)
  2. Implementation Flaw: Cache-timing attacks on table lookups
  3. Protocol Issue: Randomness reuse enabling key recovery

Testing Requirements

Test Vectors

Security Testing

# Run security test suite
pytest tests/security/test_mlkem512_security.py

# Constant-time verification
valgrind --tool=memcheck ./test_mlkem512_constant_time

# Fuzzing
AFL++ -i seeds/ -o findings/ ./mlkem512_fuzzer

Security Analysis

Threat Model: ML-KEM-512 Threat Model

The comprehensive threat analysis covers:

For complete security analysis and risk assessment, see the dedicated threat model documentation.

References

  1. FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard
  2. Original Kyber Specification
  3. NIST PQC Security Categories
  4. Side-Channel Analysis of Lattice-Based KEMs

Back to Algorithm Security APIs Back to Security API

ML-KEM-512 Security-Focused API Documentation

Version: 1.0
Last Updated: 2025-08-28
Security Classification: PUBLIC
Author: MetaMUI Security Team

Overview

ML-KEM-512 (Module Lattice-Based Key Encapsulation Mechanism) is a post-quantum key encapsulation mechanism standardized by NIST. Based on the Module Learning With Errors (M-LWE) problem, ML-KEM-512 provides NIST security level 1 (equivalent to 128-bit classical security) and is designed as a lightweight option for post-quantum key exchange.

Security Level: NIST Level 1 (128-bit classical, ~2^64 quantum)
Public Key Size: 800 bytes
Private Key Size: 1632 bytes
Ciphertext Size: 768 bytes
Shared Secret Size: 32 bytes
Algorithm Family: Module-LWE lattice-based

Security Warnings ⚠️

  1. Security Level: Provides baseline post-quantum security (NIST Level 1)
  2. Use Cases: Suitable for low-security applications or as part of hybrid schemes
  3. Key Reuse: Public keys can be reused, but consider rotation policies
  4. Implementation Security: Requires protection against side-channel attacks
  5. Ciphertext Integrity: No built-in authentication - must use with AEAD
  6. Hybrid Recommendations: Consider pairing with classical KEMs for defense in depth

API Functions

mlkem512_keygen() -> (PublicKey[800], PrivateKey[1632])

Security Contract:

Attack Resistance: | Attack Type | Protected | Notes | |————-|———–|——-| | Quantum (Shor’s) | ✅ | Lattice-based security | | Quantum (Grover’s) | ✅ | 128-bit security maintained | | Classical Lattice | ✅ | M-LWE hardness assumption | | Side-Channel | ⚠️ | Implementation dependent | | Key Recovery | ✅ | Provable lattice security | | CCA Attacks | ✅ | Fujisaki-Okamoto transform |

Security Requirements:

Secure Usage Example (Python):

from metamui_crypto import MLKEM512
import secrets
import hashlib

class SecureMLKEM512:
    """Secure ML-KEM-512 wrapper with security best practices"""
    
    def __init__(self):
        self.mlkem = MLKEM512()
        
    def generate_keypair(self, additional_entropy: bytes = None) -> tuple:
        """Generate ML-KEM-512 key pair with enhanced entropy"""
        
        # Gather entropy from multiple sources
        entropy = secrets.token_bytes(64)
        
        # Add additional entropy if provided
        if additional_entropy:
            entropy = hashlib.shake_256(
                entropy + additional_entropy
            ).digest(64)
        
        # Generate key pair
        public_key, private_key = self.mlkem.keygen_with_seed(entropy)
        
        # Clear sensitive data
        entropy = bytes(64)  # Zero out
        
        return public_key, private_key

Secure Usage Example (Rust):

use metamui_mlkem512::{keypair, PublicKey, SecretKey};
use zeroize::Zeroize;

pub struct SecureMLKEM512 {
    // Store keys securely
}

impl SecureMLKEM512 {
    pub fn generate_keypair() -> Result<(PublicKey, SecretKey), Error> {
        // Generate with system RNG
        let (pk, mut sk) = keypair()?;
        
        // Keys are automatically zeroized on drop
        Ok((pk, sk))
    }
    
    pub fn generate_keypair_deterministic(seed: &[u8; 64]) -> Result<(PublicKey, SecretKey), Error> {
        // Deterministic generation for reproducibility
        let (pk, sk) = keypair_from_seed(seed)?;
        Ok((pk, sk))
    }
}

mlkem512_encaps(PublicKey[800]) -> (Ciphertext[768], SharedSecret[32])

Security Contract:

Attack Resistance: | Attack Type | Protected | Notes | |————-|———–|——-| | Chosen Ciphertext | ✅ | IND-CCA2 secure | | Key Reuse | ✅ | Fresh randomness per encapsulation | | Malleability | ✅ | Fujisaki-Okamoto transform | | Quantum Analysis | ✅ | Lattice problem remains hard | | Side-Channel | ⚠️ | Requires constant-time implementation |

Security Requirements:

Common Mistakes:

# ❌ INSECURE: Reusing randomness
fixed_seed = b"constant_seed" * 4
for i in range(10):
    ct, ss = mlkem512_encaps_deterministic(pk, fixed_seed)  # VULNERABLE!

# ✅ SECURE: Fresh randomness each time
for i in range(10):
    ct, ss = mlkem512_encaps(pk)  # Fresh randomness internally

mlkem512_decaps(PrivateKey[1632], Ciphertext[768]) -> SharedSecret[32]

Security Contract:

Attack Resistance: | Attack Type | Protected | Notes | |————-|———–|——-| | Invalid Ciphertext | ✅ | Implicit rejection | | Timing Attacks | ⚠️ | Requires constant-time code | | Fault Injection | ⚠️ | Hardware-dependent | | Chosen Ciphertext | ✅ | IND-CCA2 security | | Key Extraction | ✅ | No key material leaked |

Security Requirements:

Secure Usage Example:

def secure_decapsulation(private_key: bytes, ciphertext: bytes) -> bytes:
    """Secure decapsulation with error handling"""
    
    try:
        # Validate inputs
        if len(private_key) != 1632:
            raise ValueError("Invalid private key size")
        if len(ciphertext) != 768:
            raise ValueError("Invalid ciphertext size")
        
        # Perform decapsulation (implicit rejection built-in)
        shared_secret = mlkem512_decaps(private_key, ciphertext)
        
        # Derive application key
        app_key = hashlib.shake_256(
            b"MLKEM512-APP-KEY:" + shared_secret
        ).digest(32)
        
        # Clear intermediate values
        shared_secret = bytes(32)
        
        return app_key
        
    except Exception as e:
        # Return random value on any error (implicit rejection)
        return secrets.token_bytes(32)

Security Best Practices

1. Key Management

2. Hybrid Deployment

def hybrid_key_exchange(mlkem_pk, ecdh_pk):
    """Combine ML-KEM-512 with ECDH for transitional security"""
    
    # ML-KEM-512 encapsulation
    mlkem_ct, mlkem_ss = mlkem512_encaps(mlkem_pk)
    
    # ECDH key agreement
    ecdh_ss = ecdh_agree(ecdh_pk)
    
    # Combine secrets
    combined = hashlib.shake_256(
        b"HYBRID-KEX:" + mlkem_ss + ecdh_ss
    ).digest(32)
    
    return mlkem_ct, combined

3. Implementation Security

4. Side-Channel Protection

// Constant-time operations
use subtle::{ConditionallySelectable, ConstantTimeEq};

fn constant_time_select(a: &[u8], b: &[u8], choice: u8) -> Vec<u8> {
    let mut result = vec![0u8; a.len()];
    for i in 0..a.len() {
        result[i] = u8::conditional_select(&a[i], &b[i], choice.into());
    }
    result
}

5. Performance Considerations

Security Auditing

Verification Checklist

Common Vulnerabilities

  1. Timing leaks: Non-constant-time polynomial operations
  2. Weak randomness: Insufficient entropy in key generation
  3. Memory leaks: Sensitive data not cleared
  4. Implementation bugs: Incorrect polynomial arithmetic
  5. Protocol misuse: Reusing encapsulation randomness

Audit Patterns

# Security audit helper
class MLKEMSecurityAuditor:
    def verify_constant_time(self, implementation):
        """Verify constant-time execution"""
        # Run with different inputs
        # Measure execution time
        # Check for timing variations
        pass
    
    def verify_randomness_quality(self, rng):
        """Test randomness source quality"""
        # Statistical tests
        # Entropy estimation
        # Source validation
        pass
    
    def verify_memory_clearing(self, implementation):
        """Ensure sensitive data is cleared"""
        # Memory dump analysis
        # Check for residual data
        pass

Migration from Classical Cryptography

Transitioning from RSA/ECDH

class CryptoMigration:
    def __init__(self):
        self.mlkem = MLKEM512()
        self.legacy = LegacyKEX()
    
    def transitional_kex(self, peer_supports_pqc: bool):
        """Gradual migration to post-quantum"""
        
        if peer_supports_pqc:
            # Use hybrid mode
            return self.hybrid_exchange()
        else:
            # Fall back to classical
            return self.legacy_exchange()
    
    def hybrid_exchange(self):
        """Combine classical and post-quantum"""
        mlkem_pk, mlkem_sk = self.mlkem.keygen()
        ecdh_pk, ecdh_sk = self.legacy.keygen()
        
        # Exchange both public keys
        # Derive combined shared secret
        return combined_secret

Performance Metrics

Operation Time (μs) Memory (KB) Security Level
Key Generation ~50 8 NIST Level 1
Encapsulation ~60 6 NIST Level 1
Decapsulation ~70 6 NIST Level 1

Measurements on modern x86-64 CPU with AVX2 optimization

Compliance and Standards