Cypheron Core

IMPORTANT DEVELOPMENT STATUS NOTICE

This library is currently in ACTIVE DEVELOPMENT (v0.1.0) and is EXPERIMENTAL.

This is a Rust wrapper around official NIST reference implementations - not custom cryptography. The core algorithms are NIST-certified, but the Rust integration layer has NOT undergone:

  • Independent security audits of FFI bindings
  • Formal verification of memory safety wrappers
  • Production environment validation

DO NOT USE IN PRODUCTION without comprehensive integration review and testing.

Risk areas: FFI safety, memory management, build system - NOT the underlying NIST algorithms.

Post-quantum cryptography library implementing NIST-standardized quantum-resistant algorithms

Cypheron Core is a Rust library implementing NIST-standardized quantum-resistant algorithms designed to protect against both classical and quantum computer attacks. The library provides high-performance implementations with strong security guarantees.

Quick Start

Add to your Cargo.toml:

[dependencies]
cypheron-core = "0.1.0"

Basic usage:

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

// Generate keypair
let (public_key, secret_key) = MlKem768::keypair()?;

// Encapsulate shared secret  
let (ciphertext, shared_secret) = MlKem768::encapsulate(&public_key)?;

// Decapsulate shared secret
let decapsulated_secret = MlKem768::decapsulate(&ciphertext, &secret_key)?;
assert_eq!(shared_secret.expose_secret(), decapsulated_secret.expose_secret());
}

Algorithms Supported

Key Encapsulation Mechanisms (KEM)

ML-KEM-512
Security Level 1
ML-KEM-768
Security Level 3
ML-KEM-1024
Security Level 5

Digital Signatures

ML-DSA-44
Security Level 2
ML-DSA-65
Security Level 3
ML-DSA-87
Security Level 5
Falcon-512
Security Level 1
Falcon-1024
Security Level 5
SPHINCS+
Multiple variants available

Hybrid Cryptography

  • ECC + ML-DSA: Classical elliptic curve + post-quantum signatures
  • Hybrid KEM: Combined classical and post-quantum key agreement

Performance

AlgorithmKey GenSign/EncapsVerify/Decaps
ML-KEM-768~50μs~60μs~80μs
ML-DSA-65~120μs~250μs~110μs

Security Features

  • Side-channel resistance: Constant-time implementations
  • Memory safety: Secure key zeroization
  • NIST compliance: Implements FIPS 203, 204, 205 standards
  • Production hardened: Extensive testing and validation

Documentation Sections

Error Handling

When you encounter errors, they include direct links to relevant documentation:

#![allow(unused)]
fn main() {
match MlKem768::keypair() {
    Ok((pk, sk)) => { /* use keys */ },
    Err(e) => {
        // Error includes link: ERROR-KEM-001
        // See: https://docs.rs/cypheron-core/troubleshooting/errors.html#error-kem-001
        eprintln!("Key generation failed: {}", e);
    }
}
}

Local Development

Run the documentation locally:

# Install mdBook
cargo install mdbook

# Serve documentation with hot reload
cd docs
mdbook serve

# Open http://localhost:3000 in your browser

License

Licensed under the Apache License 2.0. See LICENSE for details.


Development Status: This library (v0.1.0) contains experimental implementations and has not been audited. DO NOT USE IN PRODUCTION without thorough security review. Built with C vendor code + Rust FFI requiring careful validation. See Security Model for details.

Installation

System Requirements

  • Rust: 1.80 or higher
  • Operating System: Linux, macOS, or Windows
  • Architecture: x86_64, aarch64

Cargo Installation

Add Cypheron Core to your Cargo.toml:

[dependencies]
cypheron-core = "0.1.0"

Then run:

cargo build

Feature Flags

Cypheron Core supports optional features:

[dependencies]
cypheron-core = { version = "0.1.0", features = ["std", "alloc"] }

Available features:

  • std (default): Standard library support
  • alloc: Allocation support for no_std environments
  • hybrid: Hybrid cryptography algorithms
  • serialize: Serde serialization support

No-std Support

For embedded and constrained environments:

[dependencies]
cypheron-core = { version = "0.1.0", default-features = false, features = ["alloc"] }

Development Dependencies

For testing and benchmarking:

[dev-dependencies]
cypheron-core = { version = "0.1.0", features = ["test-utils"] }
criterion = "0.5"

Platform-Specific Notes

Linux

No additional dependencies required.

macOS

Ensure Xcode command line tools are installed:

xcode-select --install

Windows

Requires Visual Studio Build Tools or MSVC.

Verification

Verify your installation:

use cypheron_core::kem::{MlKem768, Kem};

fn main() {
    match MlKem768::keypair() {
        Ok(_) => println!("Installation successful!"),
        Err(e) => eprintln!("Installation issue: {}", e),
    }
}

Next Steps

Quick Start Guide

Get up and running with Cypheron Core in minutes.

Installation

Add cypheron-core to your Cargo.toml:

[dependencies]
cypheron-core = "0.1.0"

Basic KEM Example

Key Encapsulation Mechanisms (KEMs) are used for secure key exchange:

use cypheron_core::kem::{MlKem768, Kem};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Generate a keypair
    let (public_key, secret_key) = MlKem768::keypair()?;
    
    // Alice encapsulates a shared secret using Bob's public key
    let (ciphertext, shared_secret_alice) = MlKem768::encapsulate(&public_key)?;
    
    // Bob decapsulates the shared secret using his secret key
    let shared_secret_bob = MlKem768::decapsulate(&ciphertext, &secret_key)?;
    
    // Both parties now have the same shared secret
    assert_eq!(shared_secret_alice.expose_secret(), shared_secret_bob.expose_secret());
    
    println!("Key exchange successful!");
    Ok(())
}

Basic Signature Example

Digital signatures provide authentication and non-repudiation:

use cypheron_core::sig::{MlDsa65, SignatureEngine};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let message = b"Hello, post-quantum world!";
    
    // Generate signing keypair
    let (public_key, secret_key) = MlDsa65::keypair()?;
    
    // Sign the message
    let signature = MlDsa65::sign(message, &secret_key)?;
    
    // Verify the signature
    let is_valid = MlDsa65::verify(message, &signature, &public_key);
    
    assert!(is_valid);
    println!("Signature verification successful!");
    Ok(())
}

Hybrid Example

Combine classical and post-quantum security:

use cypheron_core::hybrid::{EccDilithium, HybridEngine};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let message = b"Hybrid security message";
    
    // Generate hybrid keypair (ECC + ML-DSA)
    let (public_key, secret_key) = EccDilithium::keypair()?;
    
    // Create hybrid signature
    let signature = EccDilithium::sign(message, &secret_key)?;
    
    // Verify with different policies
    use cypheron_core::hybrid::VerificationPolicy;
    
    // Require both classical and post-quantum signatures to be valid
    let strict_valid = EccDilithium::verify_with_policy(
        message, 
        &signature, 
        &public_key, 
        VerificationPolicy::BothRequired
    );
    
    // Accept if either classical OR post-quantum signature is valid
    let relaxed_valid = EccDilithium::verify_with_policy(
        message, 
        &signature, 
        &public_key, 
        VerificationPolicy::EitherValid
    );
    
    println!("Strict policy: {}", strict_valid);
    println!("Relaxed policy: {}", relaxed_valid);
    
    Ok(())
}

Error Handling

Cypheron Core uses structured error types with helpful messages:

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

match MlKem768::keypair() {
    Ok((pk, sk)) => {
        println!("Keypair generated successfully");
        // Use the keys...
    },
    Err(e) => {
        eprintln!("Key generation failed: {}", e);
        // Error codes like ERROR-KEM-001 link to documentation
        // See troubleshooting/errors.md for complete error reference
    }
}
}

Memory Safety

All sensitive data is automatically zeroized when dropped:

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

{
    let (public_key, secret_key) = MlKem768::keypair().unwrap();
    // Use keys...
} // secret_key is automatically zeroized when it goes out of scope
}

Next Steps

Production Checklist

Before using in production:

  1. Read the Security Model
  2. Review Compliance Requirements
  3. Set up Monitoring
  4. Test your Error Handling
  5. Performance test with Benchmarking Guide

Basic Examples

Complete working examples to get you started with Cypheron Core.

Key Encapsulation (KEM) Example

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};
use cypheron_core::SecretBox;

fn kem_example() -> Result<(), Box<dyn std::error::Error>> {
    // Alice generates a keypair
    let (alice_pk, alice_sk) = MlKem768::keypair()?;
    
    // Bob wants to send a secret to Alice
    // He encapsulates using Alice's public key
    let (ciphertext, shared_secret_bob) = MlKem768::encapsulate(&alice_pk)?;
    
    // Alice decapsulates using her secret key
    let shared_secret_alice = MlKem768::decapsulate(&ciphertext, &alice_sk)?;
    
    // Both parties now have the same shared secret
    assert_eq!(
        shared_secret_alice.expose_secret(),
        shared_secret_bob.expose_secret()
    );
    
    println!("Shared secret exchange successful!");
    Ok(())
}
}

Digital Signature Example

#![allow(unused)]
fn main() {
use cypheron_core::sig::{MlDsa65, SignatureEngine};

fn signature_example() -> Result<(), Box<dyn std::error::Error>> {
    let document = b"Important contract terms...";
    
    // Alice generates signing keys
    let (verify_key, signing_key) = MlDsa65::keypair()?;
    
    // Alice signs the document
    let signature = MlDsa65::sign(document, &signing_key)?;
    
    // Bob verifies Alice's signature
    let is_valid = MlDsa65::verify(document, &signature, &verify_key);
    
    if is_valid {
        println!("Signature is valid - document authenticated!");
    } else {
        println!("Invalid signature - document may be tampered!");
    }
    
    Ok(())
}
}

Hybrid Signature Example

#![allow(unused)]
fn main() {
use cypheron_core::hybrid::{EccDilithium, HybridEngine, VerificationPolicy};

fn hybrid_example() -> Result<(), Box<dyn std::error::Error>> {
    let message = b"Quantum-safe hybrid message";
    
    // Generate hybrid keypair (ECC + ML-DSA)
    let (public_key, secret_key) = EccDilithium::keypair()?;
    
    // Create hybrid signature
    let signature = EccDilithium::sign(message, &secret_key)?;
    
    // Verify with strict policy (both signatures must be valid)
    let strict_valid = EccDilithium::verify_with_policy(
        message,
        &signature,
        &public_key,
        VerificationPolicy::BothRequired
    );
    
    // Verify with relaxed policy (either signature valid)
    let relaxed_valid = EccDilithium::verify_with_policy(
        message,
        &signature,
        &public_key,
        VerificationPolicy::EitherValid
    );
    
    println!("Strict policy result: {}", strict_valid);
    println!("Relaxed policy result: {}", relaxed_valid);
    
    Ok(())
}
}

Error Handling Example

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem, MlKemError};

fn error_handling_example() {
    match MlKem768::keypair() {
        Ok((pk, sk)) => {
            println!("Keys generated successfully");
            
            // Try to encapsulate
            match MlKem768::encapsulate(&pk) {
                Ok((ct, ss)) => {
                    println!("Encapsulation successful");
                    
                    // Try to decapsulate
                    match MlKem768::decapsulate(&ct, &sk) {
                        Ok(decrypted_ss) => {
                            println!("Decapsulation successful");
                        },
                        Err(e) => {
                            eprintln!("Decapsulation failed: {}", e);
                            // Error includes helpful documentation links
                        }
                    }
                },
                Err(e) => eprintln!("Encapsulation failed: {}", e),
            }
        },
        Err(e) => {
            eprintln!("Key generation failed: {}", e);
            // Errors include ERROR-KEM-XXX codes linking to docs
        }
    }
}
}

Memory Safety Example

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};
use cypheron_core::SecretBox;

fn memory_safety_example() -> Result<(), Box<dyn std::error::Error>> {
    let shared_secret = {
        let (pk, sk) = MlKem768::keypair()?;
        let (ct, ss) = MlKem768::encapsulate(&pk)?;
        
        // Secret key `sk` is automatically zeroized when it goes out of scope
        ss
    }; // Keys are now securely zeroized
    
    // Shared secret is still valid and secure
    println!("Shared secret length: {}", shared_secret.expose_secret().len());
    
    // When shared_secret goes out of scope, it will be zeroized
    Ok(())
}
}

Complete Application Example

use cypheron_core::kem::{MlKem768, Kem};
use cypheron_core::sig::{MlDsa65, SignatureEngine};

struct SecureMessage {
    encrypted_data: Vec<u8>,
    signature: Vec<u8>,
}

fn secure_messaging_example() -> Result<(), Box<dyn std::error::Error>> {
    // Alice's keys for encryption
    let (alice_kem_pk, alice_kem_sk) = MlKem768::keypair()?;
    
    // Bob's keys for signing  
    let (bob_sig_pk, bob_sig_sk) = MlDsa65::keypair()?;
    
    let plaintext = b"Confidential message from Bob to Alice";
    
    // Bob encrypts message for Alice
    let (ciphertext, shared_secret) = MlKem768::encapsulate(&alice_kem_pk)?;
    
    // Use shared secret to encrypt data (simplified - in practice use AES-GCM)
    let mut encrypted_data = plaintext.to_vec();
    for (i, byte) in encrypted_data.iter_mut().enumerate() {
        *byte ^= shared_secret.expose_secret()[i % 32];
    }
    
    // Bob signs the encrypted message
    let signature = MlDsa65::sign(&encrypted_data, &bob_sig_sk)?;
    
    let secure_msg = SecureMessage {
        encrypted_data,
        signature,
    };
    
    // Alice receives and verifies the message
    // First verify Bob's signature
    let signature_valid = MlDsa65::verify(
        &secure_msg.encrypted_data,
        &secure_msg.signature,
        &bob_sig_pk
    );
    
    if !signature_valid {
        return Err("Invalid signature!".into());
    }
    
    // Then decrypt using her private key
    let decrypted_secret = MlKem768::decapsulate(&ciphertext, &alice_kem_sk)?;
    
    // Decrypt the message
    let mut decrypted_data = secure_msg.encrypted_data.clone();
    for (i, byte) in decrypted_data.iter_mut().enumerate() {
        *byte ^= decrypted_secret.expose_secret()[i % 32];
    }
    
    println!("Decrypted message: {}", String::from_utf8_lossy(&decrypted_data));
    
    Ok(())
}

fn main() {
    if let Err(e) = secure_messaging_example() {
        eprintln!("Secure messaging failed: {}", e);
    }
}

Next Steps

ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism)

ML-KEM is the NIST-standardized quantum-resistant key encapsulation mechanism, formerly known as Kyber. It enables secure key exchange that is resistant to both classical and quantum computer attacks.

Overview

ML-KEM is based on the Module Learning With Errors (M-LWE) problem, which is believed to be hard even for quantum computers. The algorithm provides:

  • Key Encapsulation: Secure key exchange between parties
  • Quantum Resistance: Security against Shor’s algorithm
  • Performance: Efficient operations suitable for real-world use
  • Standardization: NIST FIPS 203 compliance

Security Levels

Cypheron Core implements all three ML-KEM variants:

VariantSecurity LevelClassical SecurityQuantum SecurityKey Sizes
ML-KEM-5121~128-bit~64-bitPK: 800B, SK: 1632B
ML-KEM-7683~192-bit~96-bitPK: 1184B, SK: 2400B
ML-KEM-10245~256-bit~128-bitPK: 1568B, SK: 3168B

Basic Usage

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

// Generate keypair
let (public_key, secret_key) = MlKem768::keypair()?;

// Alice encapsulates a shared secret
let (ciphertext, shared_secret_alice) = MlKem768::encapsulate(&public_key)?;

// Bob decapsulates the shared secret
let shared_secret_bob = MlKem768::decapsulate(&ciphertext, &secret_key)?;

// Both parties have the same 32-byte shared secret
assert_eq!(shared_secret_alice.expose_secret(), shared_secret_bob.expose_secret());
}

Algorithm Details

Key Generation

  1. Generate matrix A from public randomness
  2. Generate secret vectors s and e from centered binomial distribution
  3. Compute t = A·s + e
  4. Public key: (ρ, t), Secret key: s

Encapsulation

  1. Generate ephemeral secret r and error vectors e1, e2
  2. Compute u = A^T·r + e1
  3. Compute v = t^T·r + e2 + Encode(m)
  4. Return ciphertext (u, v) and shared secret KDF(m)

Decapsulation

  1. Compute m’ = Decode(v - s^T·u)
  2. Re-encapsulate with m’ to get (u’, v’)
  3. If (u’, v’) = (u, v), return KDF(m’), else return KDF(z)

Performance Characteristics

ML-KEM operations are highly efficient:

#![allow(unused)]
fn main() {
use std::time::Instant;
use cypheron_core::kem::{MlKem768, Kem};

fn benchmark_ml_kem() -> Result<(), Box<dyn std::error::Error>> {
    // Key generation
    let start = Instant::now();
    let (pk, sk) = MlKem768::keypair()?;
    println!("Keygen: {:?}", start.elapsed());
    
    // Encapsulation  
    let start = Instant::now();
    let (ct, ss1) = MlKem768::encapsulate(&pk)?;
    println!("Encaps: {:?}", start.elapsed());
    
    // Decapsulation
    let start = Instant::now();
    let ss2 = MlKem768::decapsulate(&ct, &sk)?;
    println!("Decaps: {:?}", start.elapsed());
    
    Ok(())
}
}

Security Considerations

Proper Usage

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

// Correct: Use each key pair only once
let (pk, sk) = MlKem768::keypair()?;
let (ct, ss) = MlKem768::encapsulate(&pk)?;

// Correct: Validate ciphertext before decapsulation
if ct.len() == 1088 { // ML-KEM-768 ciphertext size
    let ss2 = MlKem768::decapsulate(&ct, &sk)?;
}

// Incorrect: Reusing the same keypair multiple times
// This could leak information about the secret key
}

Side-Channel Protection

All operations use constant-time implementations:

  • Constant-time sampling: Secret values don’t affect execution time
  • Constant-time arithmetic: Operations always take the same time
  • Memory access patterns: No secret-dependent memory accesses

Migration from Kyber

Cypheron Core provides compatibility aliases for smooth migration:

#![allow(unused)]
fn main() {
// Old Kyber code
use cypheron_core::kem::{Kyber768, KyberError}; // Deprecated

// New ML-KEM code  
use cypheron_core::kem::{MlKem768, MlKemError}; // Recommended

// Both interfaces are identical
let (pk, sk) = MlKem768::keypair()?;
}

Test Vectors

Validation against NIST test vectors:

#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_nist_vectors() {
        // Test against official NIST ML-KEM test vectors
        // See tests/kat/ directory for complete vectors
        let (pk, sk) = MlKem768::keypair().unwrap(); 
        let (ct, ss1) = MlKem768::encapsulate(&pk).unwrap();
        let ss2 = MlKem768::decapsulate(&ct, &sk).unwrap();
        assert_eq!(ss1.expose_secret(), ss2.expose_secret());
    }
}
}

Variants

See Also

Hybrid Cryptography Overview

Hybrid cryptography combines classical and post-quantum algorithms to provide defense against both current and future cryptographic attacks.

Why Hybrid?

Hybrid schemes provide multiple layers of security:

  1. Classical Security: Protection against traditional computing threats
  2. Quantum Resistance: Protection against quantum computer attacks
  3. Migration Safety: Smooth transition from classical to post-quantum
  4. Defense in Depth: Multiple independent security assumptions

Hybrid Strategies

Composite Signatures

Combine classical and post-quantum signature schemes:

#![allow(unused)]
fn main() {
use cypheron_core::hybrid::{EccDilithium, HybridEngine};

// Generate hybrid keypair (ECC + ML-DSA)
let (public_key, secret_key) = EccDilithium::keypair()?;

// Create composite signature  
let message = b"Hybrid signed message";
let signature = EccDilithium::sign(message, &secret_key)?;

// Verification can use different policies
let is_valid = EccDilithium::verify(message, &signature, &public_key);
}

Verification Policies

Different policies for signature verification:

#![allow(unused)]
fn main() {
use cypheron_core::hybrid::VerificationPolicy;

// Strict: Both signatures must be valid
let strict_valid = EccDilithium::verify_with_policy(
    message,
    &signature, 
    &public_key,
    VerificationPolicy::BothRequired
);

// Relaxed: Either signature can be valid
let relaxed_valid = EccDilithium::verify_with_policy(
    message,
    &signature,
    &public_key, 
    VerificationPolicy::EitherValid
);

// Migration: Prefer post-quantum but accept classical
let migration_valid = EccDilithium::verify_with_policy(
    message,
    &signature,
    &public_key,
    VerificationPolicy::PostQuantumPreferred
);
}

Security Analysis

Combined Security Level

The security of hybrid schemes depends on verification policy:

PolicySecurity LevelDescription
BothRequiredmin(classical, pq)Weakest component determines security
EitherValidmax(classical, pq)Strongest component determines security
PostQuantumPreferredpost-quantumPrioritizes quantum resistance

Attack Scenarios

Quantum Computer Attack:

  • Classical component: Broken
  • Post-quantum component: Secure
  • Result with EitherValid: Secure

Classical Cryptanalysis:

  • Classical component: Potentially broken
  • Post-quantum component: Secure
  • Result with EitherValid: Secure

Post-Quantum Cryptanalysis:

  • Classical component: Secure
  • Post-quantum component: Potentially broken
  • Result with EitherValid: Secure

Performance Considerations

Signature Size

Hybrid signatures combine both signature types:

#![allow(unused)]
fn main() {
// Individual signature sizes (approximate)
// ECDSA P-256: ~64 bytes
// ML-DSA-65: ~3300 bytes  
// Combined: ~3364 bytes

let (pk, sk) = EccDilithium::keypair()?;
let signature = EccDilithium::sign(b"message", &sk)?;

println!("Hybrid signature size: {} bytes", signature.len());
// Output: Hybrid signature size: 3364 bytes
}

Verification Time

Verification involves both algorithms:

#![allow(unused)]
fn main() {
use std::time::Instant;

let start = Instant::now();
let valid = EccDilithium::verify(message, &signature, &public_key);
let duration = start.elapsed();

println!("Hybrid verification: {:?}", duration);
// Typical: ~0.5ms (classical) + ~0.1ms (post-quantum) = ~0.6ms
}

Migration Strategies

Phase 1: Introduction

Start with relaxed verification policy:

#![allow(unused)]
fn main() {
// Accept either classical or post-quantum signatures
let valid = EccDilithium::verify_with_policy(
    message,
    &signature,
    &public_key,
    VerificationPolicy::EitherValid
);
}

Phase 2: Transition

Require both signatures but log failures:

#![allow(unused)]
fn main() {
let strict_valid = EccDilithium::verify_with_policy(
    message,
    &signature,
    &public_key,
    VerificationPolicy::BothRequired
);

if !strict_valid {
    // Log for monitoring but continue processing
    log::warn!("Hybrid signature verification failed");
    
    // Fallback to relaxed policy during transition
    let relaxed_valid = EccDilithium::verify_with_policy(
        message,
        &signature,
        &public_key,
        VerificationPolicy::EitherValid
    );
    
    return relaxed_valid;
}
}

Phase 3: Post-Quantum Only

Eventually migrate to pure post-quantum:

#![allow(unused)]
fn main() {
use cypheron_core::sig::{MlDsa65, SignatureEngine};

// Pure post-quantum signatures
let (pk, sk) = MlDsa65::keypair()?;
let signature = MlDsa65::sign(message, &sk)?;
let valid = MlDsa65::verify(message, &signature, &pk);
}

Configuration Management

Policy Configuration

#![allow(unused)]
fn main() {
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct HybridConfig {
    pub verification_policy: VerificationPolicy,
    pub signature_format: SignatureFormat,
    pub key_rotation_interval: u64, // days
}

impl Default for HybridConfig {
    fn default() -> Self {
        Self {
            verification_policy: VerificationPolicy::EitherValid,
            signature_format: SignatureFormat::Concatenated,
            key_rotation_interval: 90,
        }
    }
}
}

Environment-Based Configuration

#![allow(unused)]
fn main() {
use std::env;

fn get_verification_policy() -> VerificationPolicy {
    match env::var("CYPHERON_VERIFICATION_POLICY").as_deref() {
        Ok("strict") => VerificationPolicy::BothRequired,
        Ok("relaxed") => VerificationPolicy::EitherValid,
        Ok("pq-preferred") => VerificationPolicy::PostQuantumPreferred,
        _ => VerificationPolicy::EitherValid, // Default
    }
}
}

Interoperability

Wire Format

Hybrid signatures can use different encoding formats:

#![allow(unused)]
fn main() {
// Concatenated format: [classical_sig][pq_sig]
// Tagged format: [tag][len][classical_sig][tag][len][pq_sig]
// ASN.1 format: Structured encoding with OIDs
}

Protocol Integration

Example integration with TLS:

#![allow(unused)]
fn main() {
// Custom signature scheme identifier
const HYBRID_ECC_MLDSA: u16 = 0xFE00;

impl SignatureScheme for EccDilithium {
    fn scheme_id(&self) -> u16 {
        HYBRID_ECC_MLDSA
    }
    
    fn sign(&self, message: &[u8], key: &PrivateKey) -> Vec<u8> {
        // Convert from TLS types to Cypheron types
        let sk = HybridSecretKey::from_tls(key);
        EccDilithium::sign(message, &sk).unwrap()
    }
}
}

See Also

Core Types

This section documents the core types and data structures used throughout Cypheron Core.

Key Types

Public Keys

All public key types are Clone and can be safely shared:

#![allow(unused)]
fn main() {
use cypheron_core::kem::MlKemPublicKey;
use cypheron_core::sig::MlDsaPublicKey;

// ML-KEM public keys
let pk: MlKemPublicKey = // ... from keypair generation
let pk_clone = pk.clone(); // Safe to clone

// ML-DSA public keys  
let verify_key: MlDsaPublicKey = // ... from keypair generation
}

Secret Keys

Secret keys are wrapped in SecretBox for memory safety:

#![allow(unused)]
fn main() {
use cypheron_core::kem::MlKemSecretKey;
use cypheron_core::sig::MlDsaSecretKey;
use secrecy::ExposeSecret;

// Secret keys are automatically zeroized when dropped
let sk: MlKemSecretKey = // ... from keypair generation

// Access secret data only when needed
let secret_bytes = sk.0.expose_secret();
// sk is automatically zeroized when it goes out of scope
}

Shared Secrets

Shared secrets from KEM operations are securely managed:

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};
use secrecy::ExposeSecret;

let (pk, sk) = MlKem768::keypair()?;
let (ct, shared_secret) = MlKem768::encapsulate(&pk)?;

// Access shared secret data
let secret_data = shared_secret.expose_secret(); // &[u8; 32]

// shared_secret is zeroized when dropped
}

Error Types

KEM Errors

#![allow(unused)]
fn main() {
use cypheron_core::kem::MlKemError;

pub enum MlKemError {
    KeyGenerationEntropyFailure,
    KeyGenerationInternalError,
    EncapsulationInvalidKey,
    EncapsulationInternalError,
    DecapsulationInvalidCiphertext,
    DecapsulationInternalError,
    InvalidCiphertextLength { expected: usize, actual: usize },
    InvalidPublicKeyLength { expected: usize, actual: usize },
    InvalidSecretKeyLength { expected: usize, actual: usize },
    CLibraryError { code: i32 },
}
}

Signature Errors

#![allow(unused)]
fn main() {
use cypheron_core::sig::MlDsaError;

pub enum MlDsaError {
    KeyGenerationFailed,
    SignatureFailed,
    VerificationFailed,
    InvalidSignatureLength { expected: usize, actual: usize },
    InvalidPublicKeyLength { expected: usize, actual: usize },
    InvalidSecretKeyLength { expected: usize, actual: usize },
    CLibraryError { code: i32 },
}
}

Trait Definitions

KEM Trait

#![allow(unused)]
fn main() {
pub trait Kem {
    type PublicKey;
    type SecretKey;
    type Ciphertext;
    type SharedSecret;
    type Error;

    fn keypair() -> Result<(Self::PublicKey, Self::SecretKey), Self::Error>;
    fn encapsulate(pk: &Self::PublicKey) -> Result<(Self::Ciphertext, Self::SharedSecret), Self::Error>;
    fn decapsulate(ct: &Self::Ciphertext, sk: &Self::SecretKey) -> Result<Self::SharedSecret, Self::Error>;
}
}

SignatureEngine Trait

#![allow(unused)]
fn main() {
pub trait SignatureEngine {
    type PublicKey;
    type SecretKey;
    type Signature;
    type Error;

    fn keypair() -> Result<(Self::PublicKey, Self::SecretKey), Self::Error>;
    fn sign(message: &[u8], sk: &Self::SecretKey) -> Result<Self::Signature, Self::Error>;
    fn verify(message: &[u8], signature: &Self::Signature, pk: &Self::PublicKey) -> bool;
}
}

Size Constants

All algorithm parameters are available as constants:

#![allow(unused)]
fn main() {
use cypheron_core::kem::sizes;
use cypheron_core::sig::sizes as sig_sizes;

// ML-KEM sizes
const ML_KEM_768_PUBLIC: usize = sizes::ML_KEM_768_PUBLIC;     // 1184
const ML_KEM_768_SECRET: usize = sizes::ML_KEM_768_SECRET;     // 2400  
const ML_KEM_768_CIPHERTEXT: usize = sizes::ML_KEM_768_CIPHERTEXT; // 1088
const ML_KEM_768_SHARED: usize = sizes::ML_KEM_768_SHARED;     // 32

// ML-DSA sizes
const ML_DSA_65_PUBLIC: usize = sig_sizes::ML_DSA_65_PUBLIC;   // 1952
const ML_DSA_65_SECRET: usize = sig_sizes::ML_DSA_65_SECRET;   // 4032
}

Memory Safety Guarantees

Automatic Zeroization

#![allow(unused)]
fn main() {
use zeroize::Zeroize;

// All secret types implement Zeroize
fn example() {
    let (pk, sk) = MlKem768::keypair().unwrap();
    
    // Use secret key...
    
} // sk is automatically zeroized here when dropped
}

SecretBox Protection

#![allow(unused)]
fn main() {
use secrecy::{SecretBox, ExposeSecret};

// Secret data is protected until explicitly exposed
let secret = SecretBox::new([1, 2, 3, 4]);

// Only expose when absolutely necessary
let data = secret.expose_secret(); // &[u8]

// secret is zeroized when dropped
}

Serialization Support

With the serialize feature enabled:

#![allow(unused)]
fn main() {
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct KeyPair {
    public_key: MlKemPublicKey,
    // Note: Secret keys should NOT be serialized in most cases
}

// Serialize public key safely
let json = serde_json::to_string(&public_key)?;

// Deserialize public key  
let pk: MlKemPublicKey = serde_json::from_str(&json)?;
}

Thread Safety

All public key types are Send and Sync:

#![allow(unused)]
fn main() {
use std::sync::Arc;
use std::thread;

let (pk, _sk) = MlKem768::keypair().unwrap();
let shared_pk = Arc::new(pk);

// Public keys can be shared across threads
let handles: Vec<_> = (0..4).map(|_| {
    let pk = shared_pk.clone();
    thread::spawn(move || {
        // Use pk in thread...
        MlKem768::encapsulate(&pk)
    })
}).collect();
}

See Also

Security Model

DEVELOPMENT STATUS WARNING

This security model describes the INTENDED security properties of Cypheron Core v0.1.0.

CRITICAL: This is a Rust wrapper around official NIST reference implementations - not custom cryptography. The core algorithms are NIST-certified, but the Rust integration layer is experimental and has NOT been:

  • Independently audited for FFI safety
  • Formally verified for memory management
  • Validated in production environments

Integration layer uses C vendor code with Rust FFI bindings requiring security evaluation.

Cypheron Core’s security model describes intended cryptographic foundations and defensive programming practices.

Threat Model

Adversarial Capabilities

We protect against adversaries with the following capabilities:

  1. Classical Computers: Unlimited classical computational power
  2. Quantum Computers: Large-scale fault-tolerant quantum computers
  3. Side-Channel Attacks: Timing, power, and electromagnetic analysis
  4. Memory Attacks: Cold boot attacks, memory dumps, swap file analysis

Security Goals

  • Confidentiality: Encrypted data remains secret
  • Authenticity: Signatures prove message origin
  • Integrity: Tampering is detectable
  • Forward Secrecy: Past communications remain secure if keys are compromised

Cryptographic Security

Post-Quantum Resistance

All algorithms are designed to resist quantum computer attacks:

  • ML-KEM: Based on Module Learning With Errors (M-LWE)
  • ML-DSA: Based on Module Short Integer Solution (M-SIS)
  • Falcon: Based on NTRU lattices and Gaussian sampling
  • SPHINCS+: Based on hash functions and one-time signatures

Security Levels

LevelClassical SecurityQuantum SecurityReal-World Equivalent
1128-bit64-bitAES-128
2128-bit64-bitSHA-256
3192-bit96-bitAES-192
4192-bit96-bitSHA-256
5256-bit128-bitAES-256

Implementation Security

Constant-Time Operations

All cryptographic operations execute in constant time:

#![allow(unused)]
fn main() {
// Example: Constant-time secret key usage
let (pk, sk) = MlKem768::keypair()?;
let (ct, ss) = MlKem768::encapsulate(&pk)?;

// Decapsulation time is independent of:
// - Secret key content
// - Ciphertext validity  
// - Previous operations
let result = MlKem768::decapsulate(&ct, &sk)?;
}

Memory Protection

Sensitive data is automatically protected:

#![allow(unused)]
fn main() {
use secrecy::ExposeSecret;

{
    let (pk, sk) = MlKem768::keypair()?;
    
    // Secret key is in protected memory
    let secret_data = sk.0.expose_secret();
    
    // Use secret_data...
    
} // Secret key memory is zeroized automatically
}

Randomness Requirements

Cryptographic operations require high-quality randomness:

  • Entropy Sources: Hardware RNG, OS entropy pools
  • Seeding: Proper CSPRNG initialization
  • Reseeding: Regular entropy pool updates
#![allow(unused)]
fn main() {
// Entropy failure is handled gracefully
match MlKem768::keypair() {
    Ok((pk, sk)) => { /* success */ },
    Err(MlKemError::KeyGenerationEntropyFailure) => {
        // Handle insufficient entropy
        std::thread::sleep(std::time::Duration::from_millis(100));
        // Retry...
    },
    Err(e) => return Err(e),
}
}

Side-Channel Protection

Timing Attacks

All operations use constant-time algorithms:

  • No secret-dependent branches: Control flow is independent of secrets
  • No secret-dependent memory access: Memory patterns are predictable
  • No secret-dependent loop bounds: Iteration counts are fixed

Power Analysis

Operations are designed to minimize power analysis vulnerabilities:

  • Uniform operations: Similar power consumption patterns
  • Masked arithmetic: Secret values are never used directly
  • Randomized execution: Some operations include deliberate randomness

Fault Injection

Critical operations include integrity checks:

#![allow(unused)]
fn main() {
// Example: Built-in integrity verification
let (pk, sk) = MlKem768::keypair()?;
let (ct, ss1) = MlKem768::encapsulate(&pk)?;

// Decapsulation includes implicit ciphertext validation
match MlKem768::decapsulate(&ct, &sk) {
    Ok(ss2) => {
        // ss1 and ss2 are identical if no faults occurred
        assert_eq!(ss1.expose_secret(), ss2.expose_secret());
    },
    Err(MlKemError::DecapsulationInvalidCiphertext) => {
        // Ciphertext was corrupted or maliciously modified
    },
}
}

Key Management

Key Lifecycle

  1. Generation: High-entropy key creation
  2. Storage: Encrypted at rest when possible
  3. Usage: Minimal exposure time
  4. Destruction: Cryptographic erasure
#![allow(unused)]
fn main() {
// Proper key lifecycle management
fn secure_key_usage() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Generation
    let (pk, sk) = MlKem768::keypair()?;
    
    // 2. Usage (minimize exposure time)
    let (ct, ss) = MlKem768::encapsulate(&pk)?;
    
    // 3. Destruction is automatic when variables go out of scope
    Ok(())
} // Keys are zeroized here
}

Key Rotation

Regular key rotation is recommended:

#![allow(unused)]
fn main() {
use std::time::{Duration, Instant};

struct KeyManager {
    current_keys: (MlKemPublicKey, MlKemSecretKey),
    created_at: Instant,
    rotation_interval: Duration,
}

impl KeyManager {
    fn should_rotate(&self) -> bool {
        self.created_at.elapsed() > self.rotation_interval
    }
    
    fn rotate(&mut self) -> Result<(), MlKemError> {
        if self.should_rotate() {
            self.current_keys = MlKem768::keypair()?;
            self.created_at = Instant::now();
        }
        Ok(())
    }
}
}

Compliance and Standards

NIST Standardization

All algorithms implement NIST-standardized specifications:

  • FIPS 203: ML-KEM standard
  • FIPS 204: ML-DSA standard
  • FIPS 205: SPHINCS+ standard

Security Validations

  • Known Answer Tests (KAT): Validation against NIST test vectors
  • Monte Carlo Testing: Statistical randomness validation
  • Side-Channel Testing: Timing and power analysis resistance

Limitations and Assumptions

Trust Assumptions

  • Implementation Correctness: No bugs in cryptographic implementations
  • Hardware Security: CPU and memory provide basic security guarantees
  • Random Number Generation: OS provides cryptographically secure randomness

Known Limitations

  • No Perfect Forward Secrecy: KEM schemes don’t provide PFS by default
  • Post-Quantum Assumptions: Security relies on unproven mathematical assumptions
  • Implementation Attacks: Hardware vulnerabilities could compromise security

Best Practices

Application Security

#![allow(unused)]
fn main() {
// ✅ Good: Validate all inputs
if ciphertext.len() != EXPECTED_CIPHERTEXT_SIZE {
    return Err("Invalid ciphertext size");
}

// ✅ Good: Handle errors appropriately  
match MlKem768::decapsulate(&ct, &sk) {
    Ok(ss) => use_shared_secret(ss),
    Err(e) => log_security_event(e),
}

// ❌ Bad: Ignoring security-critical errors
let ss = MlKem768::decapsulate(&ct, &sk).unwrap(); // Don't do this!
}

Operational Security

  1. Monitor Entropy: Check system entropy levels
  2. Log Security Events: Record cryptographic failures
  3. Update Regularly: Keep libraries up to date
  4. Test Thoroughly: Validate all error paths

See Also

Error Codes Reference

Complete reference for all error codes in Cypheron Core.

KEM Errors

ERROR-KEM-001

Key Generation Entropy Failure

Cause: Insufficient entropy available for key generation.

Solution:

#![allow(unused)]
fn main() {
// Ensure your system has adequate entropy
// On Linux: check /proc/sys/kernel/random/entropy_avail
// Consider using hardware RNG if available

use cypheron_core::kem::{MlKem768, Kem};

// Retry with backoff
for attempt in 1..=3 {
    match MlKem768::keypair() {
        Ok(keys) => return Ok(keys),
        Err(e) if attempt < 3 => {
            std::thread::sleep(std::time::Duration::from_millis(100 * attempt));
            continue;
        },
        Err(e) => return Err(e),
    }
}
}

ERROR-KEM-002

Decapsulation Invalid Ciphertext

Cause: Ciphertext was corrupted or not generated with the corresponding public key.

Solution:

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

let (pk, sk) = MlKem768::keypair().unwrap();
let (ct, ss1) = MlKem768::encapsulate(&pk).unwrap();

// Verify ciphertext length before decapsulation
if ct.len() != 1088 { // ML-KEM-768 ciphertext size
    return Err("Invalid ciphertext size");
}

match MlKem768::decapsulate(&ct, &sk) {
    Ok(shared_secret) => { /* success */ },
    Err(e) => {
        // Check if ciphertext is corrupted
        // Verify it was generated with correct public key
        eprintln!("Decapsulation failed: {}", e);
    }
}
}

ERROR-KEM-003

Encapsulation Invalid Public Key

Cause: Public key format is invalid or corrupted.

Solution:

#![allow(unused)]
fn main() {
// Validate public key before use
use cypheron_core::kem::{MlKem768, Kem};

fn validate_public_key(pk_bytes: &[u8]) -> Result<(), &'static str> {
    if pk_bytes.len() != 1184 { // ML-KEM-768 public key size
        return Err("Invalid public key size");
    }
    // Additional validation logic...
    Ok(())
}

// Use validated public key
if let Err(e) = validate_public_key(&pk_bytes) {
    return Err(format!("Public key validation failed: {}", e));
}
}

Signature Errors

ERROR-SIG-001

Signature Generation Failed

Cause: Internal error during signature generation, possibly due to entropy issues.

Solution:

#![allow(unused)]
fn main() {
use cypheron_core::sig::{MlDsa65, SignatureEngine};

let message = b"message to sign";
let (pk, sk) = MlDsa65::keypair().unwrap();

match MlDsa65::sign(message, &sk) {
    Ok(signature) => { /* success */ },
    Err(e) => {
        // Check message size (ML-DSA has no message size limit)
        // Verify secret key integrity
        // Ensure adequate system entropy
        eprintln!("Signature generation failed: {}", e);
    }
}
}

ERROR-SIG-002

Signature Verification Failed

Cause: Signature is invalid, message was modified, or wrong public key used.

Solution:

#![allow(unused)]
fn main() {
use cypheron_core::sig::{MlDsa65, SignatureEngine};

// Ensure exact message match
let original_message = b"Hello, world!";
let modified_message = b"Hello, world?"; // Note the different punctuation

let (pk, sk) = MlDsa65::keypair().unwrap();
let signature = MlDsa65::sign(original_message, &sk).unwrap();

// This will fail
let valid = MlDsa65::verify(modified_message, &signature, &pk);
assert!(!valid); // Verification fails due to message modification

// This will succeed  
let valid = MlDsa65::verify(original_message, &signature, &pk);
assert!(valid);
}

Hybrid Errors

ERROR-HYBRID-001

Composite Key Generation Failed

Cause: Failure in either classical or post-quantum key generation.

Solution:

#![allow(unused)]
fn main() {
use cypheron_core::hybrid::{EccDilithium, HybridEngine};

// Retry hybrid key generation with error isolation
match EccDilithium::keypair() {
    Ok(keys) => { /* success */ },
    Err(e) => {
        // Error could be from ECC or ML-DSA component
        // Check system entropy and crypto library status
        eprintln!("Hybrid key generation failed: {}", e);
        
        // Consider fallback to individual algorithms for debugging
        use cypheron_core::sig::{MlDsa44, SignatureEngine};
        let pq_test = MlDsa44::keypair();
        match pq_test {
            Ok(_) => println!("Post-quantum component working"),
            Err(e) => println!("Post-quantum issue: {}", e),
        }
    }
}
}

Platform-Specific Errors

ERROR-PLATFORM-001

Windows Entropy Source Unavailable

Cause: Windows CryptoAPI is not accessible.

Solution:

#![allow(unused)]
fn main() {
// Ensure Windows CryptoAPI is available
// This is rare but can happen in restricted environments

#[cfg(target_os = "windows")]
fn check_windows_crypto() -> Result<(), Box<dyn std::error::Error>> {
    // The library will automatically fallback to other entropy sources
    // but you can manually check availability
    
    use cypheron_core::platform::secure_random_bytes;
    let mut buffer = vec![0u8; 32];
    secure_random_bytes(&mut buffer)?;
    Ok(())
}
}

Memory Errors

ERROR-MEM-001

Secure Memory Allocation Failed

Cause: System cannot allocate secure memory for sensitive operations.

Solution:

#![allow(unused)]
fn main() {
// Reduce memory pressure or increase available memory
// Check system memory limits and available RAM

use cypheron_core::kem::{MlKem512, Kem}; // Use smaller variant if needed

// Consider using smaller security parameters temporarily
let (pk, sk) = MlKem512::keypair()?; // Instead of MlKem1024
}

FFI Errors

ERROR-FFI-001

C Library Binding Failed

Cause: Underlying C library call failed.

Solution:

#![allow(unused)]
fn main() {
// This indicates an issue with the vendor C implementations
// Usually due to memory corruption or invalid parameters

// Enable debug logging to get more details
std::env::set_var("RUST_LOG", "debug");
env_logger::init();

// The error will include more detailed information in debug mode
}

Debugging Tips

Enable Detailed Logging

// Add to your Cargo.toml
[dependencies]
env_logger = "0.10"

// In your code
fn main() {
    env_logger::init();
    // Your code here - errors will include more details
}

Validate Input Data

#![allow(unused)]
fn main() {
use cypheron_core::kem::{MlKem768, Kem};

fn safe_decapsulate(ct: &[u8], sk: &SecretKey) -> Result<SharedSecret, String> {
    // Validate ciphertext size
    if ct.len() != 1088 {
        return Err(format!("Invalid ciphertext size: expected 1088, got {}", ct.len()));
    }
    
    // Additional validation...
    
    MlKem768::decapsulate(ct, sk)
        .map_err(|e| format!("Decapsulation failed: {}", e))
}
}

Test with Known Good Data

#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_with_known_vectors() {
        // Use NIST test vectors for validation
        // See tests/kat/ directory for examples
        let (pk, sk) = MlKem768::keypair().unwrap();
        let (ct, ss1) = MlKem768::encapsulate(&pk).unwrap();
        let ss2 = MlKem768::decapsulate(&ct, &sk).unwrap();
        assert_eq!(ss1.expose_secret(), ss2.expose_secret());
    }
}
}

Getting Help

If you encounter an error not covered here:

  1. Check the FAQ for common solutions
  2. Enable debug logging to get more details
  3. Search GitHub Issues
  4. Create a minimal reproduction case
  5. File a new issue with full error details

See Also