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?
- Mathematical Hardness: Based on problems that are computationally infeasible to solve
- Key Secrecy: Security depends only on the key, not the algorithm (Kerckhoffs’s principle)
- 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(×tamp.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:
- RSA (Shor’s algorithm)
- ECDSA/ECDH (Shor’s algorithm)
- Small symmetric keys (Grover’s algorithm)
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
- Timing Attacks: Information leaked through execution time
- Power Analysis: Information from power consumption
- Cache Attacks: Information from CPU cache behavior
- 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
- Assess - Determine scope and severity
- Contain - Limit damage spread
- Investigate - Find root cause
- Remediate - Fix vulnerabilities
- 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
- No hardcoded secrets - Use environment variables or key management
- Input validation - Check all inputs before use
- Error handling - Don’t leak sensitive information
- Memory safety - Clear secrets after use
- Constant time - Use for all secret comparisons
- Secure randomness - Use OsRng or approved RNG
- Tests included - Security-specific test cases
- Documentation - Security implications documented
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
- Complete this training guide
- Pass basic security quiz
- Demonstrate secure coding in PR
Level 2: Cryptographic Developer
- Implement a secure module
- Pass cryptographic concepts exam
- Complete side-channel workshop
Level 3: Security Champion
- Lead security review
- Mentor other developers
- Contribute to security tools
Resources for Continued Learning
Books
- “Cryptography Engineering” by Ferguson, Schneier, and Kohno
- “The Rust Programming Language” (Security chapters)
- “Serious Cryptography” by Jean-Philippe Aumasson
Online Courses
- Coursera: Cryptography I & II (Dan Boneh)
- Real World Cryptography (David Wong)
- Rust Security Workshop (RustConf)
Practice Platforms
- CryptoHack (https://cryptohack.org)
- Cryptopals Challenges (https://cryptopals.com)
- RustSec Advisory Database
Community
- RustCrypto Discord
- IACR Forums
- Local security meetups
Remember: Security is everyone’s responsibility. When in doubt, ask for help!