Security Best Practices for MetaMUI Crypto Primitives
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.
Overview
This document describes common practices against timing attacks, other side-channel attacks and memory-based vulnerabilities, for anyone writing or reviewing code that handles secrets. It does not say which of them each MetaMUI target applies. Constant-time behaviour and side-channel resistance are not claimed for any MetaMUI target: none has been measured (finding A48).
Constant-Time Operations
Principle
All cryptographic operations must execute in constant time regardless of input values to prevent timing attacks.
Implementation Guidelines
- Conditional Operations
- Never use data-dependent branches in cryptographic code
- Use constant-time selection functions instead of if/else statements
- Example (Rust): ```rust // BAD: Timing leak if secret_bit == 1 { result = a; } else { result = b; }
// BETTER: no branch on the secret (measure timing on your target) use subtle::ConditionallySelectable; result = u32::conditional_select(&a, &b, secret_bit.into()); ```
- Comparisons
- Never use standard equality operators for secret data
- Use constant-time comparison functions
- Example (Python):
```python
BAD: Timing leak
if secret_key == expected_key: return True
BETTER: the stdlib’s comparison for secrets (timing not measured here)
import hmac return hmac.compare_digest(secret_key, expected_key) ```
- Array Access
- Avoid secret-dependent array indexing
- Use masking or conditional selection for lookups
- Example (TypeScript): ```typescript // BAD: Cache timing leak result = lookup_table[secret_index];
// BETTER: linear scan, no secret-dependent index // (a JIT may still introduce timing differences; measure on your target) let result = 0; for (let i = 0; i < table.length; i++) { const mask = constantTimeEq(i, secret_index) ? 0xFF : 0x00; result |= table[i] & mask; } ```
Memory Security
Secure Memory Handling
- Zeroing Sensitive Data
- Always clear sensitive data from memory after use
- Use secure zeroing functions that won’t be optimized away
- Examples: ```rust // Rust use zeroize::Zeroize; secret_key.zeroize();
// Python import ctypes ctypes.memset(ctypes.addressof(ctypes.c_char.from_buffer(secret)), 0, len(secret))
// TypeScript crypto.getRandomValues(secret); // Overwrite with random data secret.fill(0); ```
- Memory Allocation
- Use secure allocators when available
- Lock memory pages to prevent swapping (platform-specific)
- Minimize copies of sensitive data
- Stack Cleaning
- Clear local variables containing secrets
- Be aware of compiler optimizations that might leave copies
Input Validation
Comprehensive Validation
- Size Validation
pub fn validate_key(key: &[u8], expected_size: usize) -> Result<()> { if key.len() != expected_size { return Err(SecurityError::InvalidKeySize { expected: expected_size, actual: key.len(), }); } Ok(()) } - Range Validation
- Check all inputs are within valid ranges
- Validate polynomial coefficients in lattice-based crypto
- Ensure modular arithmetic inputs are reduced
- Format Validation
- Verify data structures are well-formed
- Check for canonical representations
- Validate encoding formats (base64, hex, etc.)
Side-Channel Protection
Generic countermeasures, listed as advice. This page does not state that any MetaMUI target implements them, and none has been measured (A48).
Power Analysis Protection
- Masking
- Split sensitive values into random shares
- Process shares independently
- Recombine only when necessary
- Blinding
- Add random factors to computations
- Remove factors at the end
- Particularly important for RSA and ECC
- Dummy Operations
- Add noise to power traces
- Execute dummy operations randomly
- Balance Hamming weights
Cache Attack Protection
- Cache-Oblivious Algorithms
- Avoid secret-dependent memory access patterns
- Use linear scans instead of indexed lookups
- Prefetch data to normalize cache behavior
- Cache Flushing
- Clear caches after sensitive operations
- Use memory barriers appropriately
- Consider cache-line alignment
Implementation-Specific Guidelines
Rust
- Use
subtlecrate for constant-time operations - Enable
zeroizefor automatic memory clearing - Use
#[inline(never)]to prevent optimization issues - Compile with appropriate flags to disable certain optimizations
Python
- Use
hmac.compare_digest()for comparisons - Implement custom constant-time functions where needed
- Use
ctypesfor memory operations - Be cautious with Python’s reference counting
TypeScript/JavaScript
- Implement all constant-time operations manually
- Use
crypto.timingSafeEqual()when available (Node.js) - Clear typed arrays explicitly
- Be aware of JIT optimization effects
Swift
- Use
Data.withUnsafeBytesfor secure operations - Implement constant-time primitives
- Clear memory with
memset_swhen available - Use
@inline(never)to control optimization
Kotlin
- Implement constant-time operations using bitwise logic
- Use
Arrays.fill()for clearing arrays - Be cautious with JVM optimizations
- Consider using
sun.misc.Cleanerfor direct ByteBuffers
Testing Security Properties
Timing Analysis
- Measure execution time with different inputs
- Statistical analysis to detect variations
- Use tools like
dudectfor timing leak detection
Memory Analysis
- Use memory sanitizers (ASan, MSan)
- Check for uninitialized memory reads
- Verify proper cleanup with debugging tools
Fuzzing
- Use coverage-guided fuzzing
- Target edge cases and error paths
- Include differential fuzzing between implementations
Security Checklist
Before releasing any cryptographic code (for MetaMUI the side-channel and timing items are open: no target has been measured, A48):
- All comparisons use constant-time functions
- No secret-dependent branches
- All sensitive memory is properly zeroed
- Input validation is comprehensive
- Side-channel protections are implemented
- Code has been reviewed by security experts
- Timing tests show no statistical variations
- Memory sanitizers report no issues
- Fuzzing has achieved good coverage
- Documentation clearly marks security-critical sections