MetaMUI Security Training Guide

Side-channel claim limit. Nothing on this page claims constant-time behaviour or side-channel resistance for any target: the side-channel harness covers nothing (finding A48) and no measurement exists. The Rust and C cores are designed for constant time and unmeasured; managed runtimes (JIT, GC, bounds checks) make no timing claim. Where this page names constant-time or side-channel techniques, in prose or in code, they are design intent or recommendations, not measured properties.

Module 1: Cryptographic Fundamentals

1.1 Understanding Cryptographic Security

What Makes Cryptography Secure?

  1. Mathematical Hardness: Based on problems that are computationally infeasible to solve
  2. Key Secrecy: Security depends only on the key, not the algorithm (Kerckhoffs’s principle)
  3. Proper Implementation: Even strong algorithms can be broken by poor implementation

Common Cryptographic Failures

// ❌ Example 1: Predictable "Random" Values
fn bad_generate_nonce() -> [u8; 12] {
    let mut nonce = [0u8; 12];
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    nonce[..8].copy_from_slice(&timestamp.to_le_bytes());
    nonce // Predictable!
}

// ✅ Correct Implementation
fn good_generate_nonce() -> [u8; 12] {
    let mut nonce = [0u8; 12];
    OsRng.fill_bytes(&mut nonce);
    nonce // Cryptographically random
}

// ❌ Example 2: Timing Attack Vulnerability
fn bad_verify_password(input: &str, stored_hash: &str) -> bool {
    input == stored_hash // Returns false as soon as mismatch found
}

// ✅ Correct Implementation
fn good_verify_password(input: &str, stored_hash: &str) -> bool {
    use subtle::ConstantTimeEq;
    input.as_bytes().ct_eq(stored_hash.as_bytes()).unwrap_u8() == 1
}

1.2 Post-Quantum Cryptography

Why Post-Quantum?

Quantum computers can break:

Post-Quantum Safe Algorithms

// Classical (Quantum-Vulnerable)
let keypair = ed25519::generate_keypair(); // Broken by quantum computers

// Post-Quantum Safe
let keypair = ml_kem_768::generate_keypair(); // Quantum-resistant
let signing_key = dilithium::generate_keypair(); // Quantum-resistant signatures

Module 2: Secure Coding Practices

2.1 Memory Safety

Understanding Memory Vulnerabilities

// ❌ Unsafe: Buffer Overflow Risk
unsafe fn bad_copy(dest: *mut u8, src: *const u8, len: usize) {
    std::ptr::copy_nonoverlapping(src, dest, len); // No bounds checking!
}

// ✅ Safe: Rust's Built-in Protection
fn good_copy(dest: &mut [u8], src: &[u8]) -> Result<(), Error> {
    if dest.len() < src.len() {
        return Err(Error::BufferTooSmall);
    }
    dest[..src.len()].copy_from_slice(src);
    Ok(())
}

Secure Memory Handling

use zeroize::{Zeroize, ZeroizeOnDrop};

// Automatically clears memory when dropped
#[derive(ZeroizeOnDrop)]
struct SecretKey {
    key_material: Vec<u8>,
}

// Manual clearing for complex scenarios
fn process_secret(secret: Vec<u8>) -> Result<(), Error> {
    let mut working_copy = secret;
    
    // Use the secret
    let result = perform_operation(&working_copy)?;
    
    // Clear from memory
    working_copy.zeroize();
    
    // Prevent compiler optimizations
    std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst);
    
    Ok(result)
}

2.2 Side-Channel Resistance

Types of Side Channels

  1. Timing Attacks: Information leaked through execution time
  2. Power Analysis: Information from power consumption
  3. Cache Attacks: Information from CPU cache behavior
  4. Electromagnetic: Information from EM emissions

Protecting Against Timing Attacks

// ❌ Vulnerable to Timing Attack
fn bad_check_signature(message: &[u8], signature: &[u8], key: &PublicKey) -> bool {
    let computed = compute_signature(message, key);
    for i in 0..signature.len() {
        if computed[i] != signature[i] {
            return false; // Early return leaks information
        }
    }
    true
}

// ✅ Constant-Time Implementation
fn good_check_signature(message: &[u8], signature: &[u8], key: &PublicKey) -> bool {
    let computed = compute_signature(message, key);
    let mut result = 0u8;
    
    // Always check all bytes
    for i in 0..signature.len() {
        result |= computed[i] ^ signature[i];
    }
    
    // Constant-time comparison to zero
    result.ct_eq(&0).unwrap_u8() == 1
}

Module 3: Key Management

3.1 Key Lifecycle

Secure Key Generation

pub struct KeyGenerator {
    rng: DrbgRng,
}

impl KeyGenerator {
    pub fn generate_master_key(&mut self) -> Result<MasterKey, Error> {
        // 1. Verify RNG health
        self.rng.health_check()?;
        
        // 2. Generate with proper entropy
        let mut key_material = [0u8; 32];
        self.rng.fill_bytes(&mut key_material)?;
        
        // 3. Derive with domain separation
        let master_key = hkdf_sha256(
            &key_material,
            b"metamui-master-key-v1",
            32
        )?;
        
        // 4. Clear intermediate material
        key_material.zeroize();
        
        // 5. Audit log
        audit_log(Event::MasterKeyGenerated)?;
        
        Ok(MasterKey::new(master_key))
    }
}

Key Rotation Strategy

pub async fn rotate_encryption_key(
    old_key_id: KeyId,
) -> Result<KeyId, RotationError> {
    // 1. Generate new key
    let new_key = generate_key().await?;
    let new_key_id = new_key.id();
    
    // 2. Begin transaction
    let mut txn = begin_transaction().await?;
    
    // 3. Re-encrypt data
    for data_id in find_data_encrypted_with(old_key_id).await? {
        let plaintext = decrypt_with_key(data_id, old_key_id).await?;
        encrypt_with_key(data_id, new_key_id, plaintext).await?;
    }
    
    // 4. Update key metadata
    mark_key_as_rotated(old_key_id, new_key_id).await?;
    
    // 5. Commit transaction
    txn.commit().await?;
    
    // 6. Schedule old key destruction
    schedule_key_destruction(old_key_id, Duration::from_days(30)).await?;
    
    Ok(new_key_id)
}

3.2 Key Storage Security

Hardware Security Module Integration

pub trait KeyStorage: Send + Sync {
    async fn store_key(&self, key: &SecretKey) -> Result<KeyId, Error>;
    async fn retrieve_key(&self, id: KeyId) -> Result<SecretKey, Error>;
    async fn delete_key(&self, id: KeyId) -> Result<(), Error>;
}

pub struct HsmKeyStorage {
    hsm: HsmClient,
}

impl KeyStorage for HsmKeyStorage {
    async fn store_key(&self, key: &SecretKey) -> Result<KeyId, Error> {
        // Use HSM for secure storage
        let key_handle = self.hsm
            .import_key(key.algorithm(), key.material())
            .await?;
            
        Ok(KeyId::from(key_handle))
    }
}

Module 4: Common Vulnerabilities

4.1 Cryptographic Vulnerabilities

Nonce Reuse

// ❌ Vulnerable: Static Nonce
fn bad_encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
    let nonce = [0u8; 12]; // Same nonce every time!
    chacha20_poly1305_encrypt(key, &nonce, plaintext)
}

// ✅ Secure: Unique Nonce
fn good_encrypt(
    key: &[u8; 32], 
    plaintext: &[u8],
    nonce_mgr: &NonceManager,
) -> Result<(Vec<u8>, [u8; 12]), Error> {
    let nonce = nonce_mgr.generate_nonce(key)?;
    let ciphertext = chacha20_poly1305_encrypt(key, &nonce, plaintext)?;
    Ok((ciphertext, nonce))
}

Weak Random Number Generation

// ❌ Vulnerable: Predictable RNG
use rand::rngs::StdRng;
use rand::SeedableRng;

fn bad_generate_key() -> [u8; 32] {
    let seed = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    let mut rng = StdRng::seed_from_u64(seed); // Predictable seed!
    let mut key = [0u8; 32];
    rng.fill_bytes(&mut key);
    key
}

// ✅ Secure: Cryptographic RNG
fn good_generate_key() -> Result<[u8; 32], Error> {
    let mut key = [0u8; 32];
    OsRng.fill_bytes(&mut key);
    Ok(key)
}

4.2 Implementation Vulnerabilities

Integer Overflow

// ❌ Vulnerable: Integer Overflow
fn bad_allocate_buffer(count: usize, size: usize) -> Vec<u8> {
    let total = count * size; // Can overflow!
    vec![0u8; total]
}

// ✅ Secure: Checked Arithmetic
fn good_allocate_buffer(count: usize, size: usize) -> Result<Vec<u8>, Error> {
    let total = count
        .checked_mul(size)
        .ok_or(Error::IntegerOverflow)?;
        
    if total > MAX_BUFFER_SIZE {
        return Err(Error::BufferTooLarge);
    }
    
    Ok(vec![0u8; total])
}

Module 5: Security Testing

5.1 Writing Security Tests

Testing Constant-Time Operations

#[test]
fn test_constant_time_comparison() {
    use std::time::Instant;
    
    let iterations = 10_000;
    let mut timings_match = Vec::new();
    let mut timings_mismatch = Vec::new();
    
    // Test matching values
    for _ in 0..iterations {
        let a = [0xAA; 32];
        let b = [0xAA; 32];
        
        let start = Instant::now();
        let _ = constant_time_eq(&a, &b);
        timings_match.push(start.elapsed());
    }
    
    // Test mismatching values
    for i in 0..iterations {
        let a = [0xAA; 32];
        let mut b = [0xAA; 32];
        b[i % 32] = 0xBB; // Different byte at various positions
        
        let start = Instant::now();
        let _ = constant_time_eq(&a, &b);
        timings_mismatch.push(start.elapsed());
    }
    
    // Statistical analysis
    let match_avg = average(&timings_match);
    let mismatch_avg = average(&timings_mismatch);
    
    // Timing should be similar (within 5%)
    assert!((match_avg - mismatch_avg).abs() < match_avg * 0.05);
}

5.2 Fuzzing Cryptographic Code

Setting Up Fuzzing

// fuzz/fuzz_targets/crypto_fuzz.rs
#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    // Skip inputs that are too small
    if data.len() < 32 {
        return;
    }
    
    // Extract key and message
    let (key_bytes, message) = data.split_at(32);
    let key = key_bytes.try_into().unwrap();
    
    // Test encryption/decryption roundtrip
    if let Ok(encrypted) = encrypt(&key, message) {
        let decrypted = decrypt(&key, &encrypted).unwrap();
        assert_eq!(message, &decrypted[..]);
    }
});

Module 6: Incident Response

6.1 Recognizing Security Incidents

Key Compromise Indicators

pub struct SecurityMonitor {
    anomaly_detector: AnomalyDetector,
}

impl SecurityMonitor {
    pub async fn check_for_compromise(&self) -> Vec<SecurityAlert> {
        let mut alerts = Vec::new();
        
        // Check for unusual key usage patterns
        if let Some(anomaly) = self.check_key_usage_anomaly().await {
            alerts.push(SecurityAlert::PossibleKeyCompromise(anomaly));
        }
        
        // Check for timing anomalies
        if let Some(timing) = self.check_timing_anomaly().await {
            alerts.push(SecurityAlert::PossibleSideChannel(timing));
        }
        
        // Check for failed authentication spikes
        if self.failed_auth_rate().await > THRESHOLD {
            alerts.push(SecurityAlert::PossibleBruteForce);
        }
        
        alerts
    }
}

6.2 Incident Response Steps

Immediate Response Checklist

  1. Assess - Determine scope and severity
  2. Contain - Limit damage spread
  3. Investigate - Find root cause
  4. Remediate - Fix vulnerabilities
  5. Document - Record lessons learned
pub async fn handle_key_compromise(
    compromised_key_id: KeyId,
) -> Result<IncidentReport, Error> {
    let mut report = IncidentReport::new();
    
    // 1. Immediate containment
    revoke_key(compromised_key_id).await?;
    report.add_action("Key revoked");
    
    // 2. Identify affected data
    let affected_data = find_data_encrypted_with(compromised_key_id).await?;
    report.add_finding(format!("{} items affected", affected_data.len()));
    
    // 3. Rotate to new key
    let new_key_id = emergency_key_rotation(compromised_key_id).await?;
    report.add_action("Emergency key rotation completed");
    
    // 4. Re-encrypt affected data
    for data_id in affected_data {
        reencrypt_data(data_id, new_key_id).await?;
    }
    report.add_action("Data re-encrypted");
    
    // 5. Notify stakeholders
    notify_security_team(&report).await?;
    
    Ok(report)
}

Module 7: Best Practices Summary

Security Checklist for Every PR

Red Flags in Code Review

🚩 Direct string comparison of secrets

if password == stored_password { // BAD!

🚩 Unwrap in production code

let key = generate_key().unwrap(); // BAD!

🚩 Missing input validation

fn process(data: &[u8]) -> Vec<u8> {
    encrypt(data) // No validation! BAD!
}

🚩 Secrets in logs

println!("Key: {:?}", secret_key); // BAD!

Certification Path

Level 1: Security Awareness

Level 2: Cryptographic Developer

Level 3: Security Champion

Resources for Continued Learning

Books

Online Courses

Practice Platforms

Community


Remember: Security is everyone’s responsibility. When in doubt, ask for help!