Skip to content

WebAssembly Security Runtimes: Deploying Rust Security Tools at the Edge

Published: at 09:00 AM

WebAssembly Security Runtimes: Deploying Rust Security Tools at the Edge

Introduction

The security perimeter has dissolved. With cloud-native architectures, remote workforces, and distributed applications, traditional centralized security models fail to protect modern infrastructure. Edge computing brings computation closer to users and data sources, but it also creates new attack surfaces that need protection.

WebAssembly (WASM) represents a paradigm shift for edge security: the ability to deploy high-performance, sandboxed security tools anywhere—from CDN nodes to IoT gateways to browser environments. This comprehensive guide demonstrates how to build production-grade security tools in Rust that compile to WebAssembly, achieving near-native performance in sandboxed environments while maintaining the memory safety guarantees that make Rust ideal for security applications.

WebAssembly for Security: The Perfect Match

WebAssembly provides unique advantages for security applications:

Security Benefits:

Performance Benefits:

Deployment Benefits:

Building the WASM Security Foundation

Let’s start by creating a comprehensive Rust-to-WASM security toolkit:

// Cargo.toml for WASM security runtime
[package]
name = "wasm-security-runtime"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
js-sys = "0.3"
web-sys = "0.3"
console_error_panic_hook = "0.1"
wee_alloc = "0.4"
getrandom = { version = "0.2", features = ["js"] }

# Cryptographic dependencies (WASM-compatible)
ring = "0.16"
sha2 = "0.10"
blake3 = "1.0"
hmac = "0.12"
aes-gcm = "0.10"
chacha20poly1305 = "0.10"

# Parsing and pattern matching
regex = { version = "1.0", default-features = false }
nom = "7.0"
aho-corasick = "1.0"

# Networking (where supported)
url = "2.0"
base64 = "0.21"

# Optional allocator for size optimization
[dependencies.wee_alloc]
version = "0.4.5"
optional = true

[features]
default = ["wee_alloc"]

# Profile optimizations for WASM
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"

[profile.release.package."*"]
opt-level = 3

Now let’s implement the core security runtime:

use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::RwLock;

// Global allocator optimization for WASM
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

// Enable better panic messages in debug mode
#[cfg(feature = "console_error_panic_hook")]
#[wasm_bindgen(start)]
pub fn main() {
    console_error_panic_hook::set_once();
}

/// Main security runtime for edge deployment
#[wasm_bindgen]
pub struct WasmSecurityRuntime {
    /// Threat detection engine
    threat_detector: ThreatDetector,
    /// Policy engine for access control
    policy_engine: PolicyEngine,
    /// Cryptographic services
    crypto_service: CryptoService,
    /// Configuration and rules
    config: SecurityConfig,
    /// Performance metrics
    metrics: SecurityMetrics,
}

#[wasm_bindgen]
impl WasmSecurityRuntime {
    /// Create new security runtime instance
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<WasmSecurityRuntime, JsValue> {
        Ok(WasmSecurityRuntime {
            threat_detector: ThreatDetector::new()?,
            policy_engine: PolicyEngine::new()?,
            crypto_service: CryptoService::new()?,
            config: SecurityConfig::default(),
            metrics: SecurityMetrics::new(),
        })
    }

    /// Initialize runtime with configuration
    #[wasm_bindgen]
    pub fn initialize(&mut self, config_json: &str) -> Result<(), JsValue> {
        let config: SecurityConfig = serde_json::from_str(config_json)
            .map_err(|e| JsValue::from_str(&format!("Config parse error: {}", e)))?;

        self.config = config;

        // Initialize sub-components with config
        self.threat_detector.configure(&self.config.threat_detection)?;
        self.policy_engine.configure(&self.config.access_policies)?;
        self.crypto_service.configure(&self.config.crypto_settings)?;

        Ok(())
    }

    /// Analyze HTTP request for security threats
    #[wasm_bindgen]
    pub fn analyze_http_request(&mut self, request_json: &str) -> Result<JsValue, JsValue> {
        let start_time = js_sys::Date::now();

        // Parse HTTP request
        let request: HttpRequest = serde_json::from_str(request_json)
            .map_err(|e| JsValue::from_str(&format!("Request parse error: {}", e)))?;

        // Perform comprehensive security analysis
        let mut analysis = SecurityAnalysis::new();

        // 1. Threat detection
        let threat_result = self.threat_detector.analyze_request(&request)?;
        analysis.add_threat_analysis(threat_result);

        // 2. Policy evaluation
        let policy_result = self.policy_engine.evaluate_request(&request)?;
        analysis.add_policy_evaluation(policy_result);

        // 3. Content security analysis
        let content_result = self.analyze_request_content(&request)?;
        analysis.add_content_analysis(content_result);

        // 4. Rate limiting and abuse detection
        let rate_limit_result = self.check_rate_limits(&request)?;
        analysis.add_rate_limit_analysis(rate_limit_result);

        // Calculate final security score
        let security_score = analysis.calculate_security_score();

        // Record performance metrics
        let processing_time = js_sys::Date::now() - start_time;
        self.metrics.record_request_analysis(processing_time, security_score);

        // Return analysis result
        let result = SecurityResult {
            allowed: security_score >= self.config.security_threshold,
            security_score,
            threat_detected: analysis.has_threats(),
            policy_violations: analysis.get_policy_violations(),
            processing_time_ms: processing_time,
            details: analysis,
        };

        Ok(serde_wasm_bindgen::to_value(&result)?)
    }

    /// Encrypt sensitive data using AES-GCM
    #[wasm_bindgen]
    pub fn encrypt_data(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>, JsValue> {
        self.crypto_service.encrypt_aes_gcm(data, key)
            .map_err(|e| JsValue::from_str(&format!("Encryption failed: {}", e)))
    }

    /// Decrypt data using AES-GCM
    #[wasm_bindgen]
    pub fn decrypt_data(&self, ciphertext: &[u8], key: &[u8]) -> Result<Vec<u8>, JsValue> {
        self.crypto_service.decrypt_aes_gcm(ciphertext, key)
            .map_err(|e| JsValue::from_str(&format!("Decryption failed: {}", e)))
    }

    /// Generate cryptographically secure random bytes
    #[wasm_bindgen]
    pub fn generate_random_bytes(&self, length: usize) -> Result<Vec<u8>, JsValue> {
        self.crypto_service.generate_random_bytes(length)
            .map_err(|e| JsValue::from_str(&format!("Random generation failed: {}", e)))
    }

    /// Hash data using BLAKE3
    #[wasm_bindgen]
    pub fn hash_data(&self, data: &[u8]) -> Vec<u8> {
        self.crypto_service.hash_blake3(data)
    }

    /// Verify HMAC signature
    #[wasm_bindgen]
    pub fn verify_hmac(&self, data: &[u8], signature: &[u8], key: &[u8]) -> bool {
        self.crypto_service.verify_hmac_sha256(data, signature, key)
    }

    /// Get performance metrics
    #[wasm_bindgen]
    pub fn get_metrics(&self) -> Result<JsValue, JsValue> {
        Ok(serde_wasm_bindgen::to_value(&self.metrics)?)
    }

    /// Update security rules dynamically
    #[wasm_bindgen]
    pub fn update_rules(&mut self, rules_json: &str) -> Result<(), JsValue> {
        let rules: SecurityRules = serde_json::from_str(rules_json)
            .map_err(|e| JsValue::from_str(&format!("Rules parse error: {}", e)))?;

        self.threat_detector.update_rules(&rules.threat_rules)?;
        self.policy_engine.update_policies(&rules.policies)?;

        Ok(())
    }

    /// Check if IP address is in threat intelligence database
    #[wasm_bindgen]
    pub fn is_malicious_ip(&self, ip: &str) -> Result<bool, JsValue> {
        self.threat_detector.is_malicious_ip(ip)
            .map_err(|e| JsValue::from_str(&format!("IP check failed: {}", e)))
    }

    /// Analyze JavaScript code for malicious patterns
    #[wasm_bindgen]
    pub fn analyze_javascript(&self, code: &str) -> Result<JsValue, JsValue> {
        let analysis = self.threat_detector.analyze_javascript(code)?;
        Ok(serde_wasm_bindgen::to_value(&analysis)?)
    }
}

Implementing High-Performance Threat Detection

Let’s build a comprehensive threat detection engine optimized for WASM:

use aho_corasick::AhoCorasick;
use regex::Regex;
use std::sync::OnceLock;

/// High-performance threat detection engine
pub struct ThreatDetector {
    /// SQL injection patterns
    sql_injection_detector: SqlInjectionDetector,
    /// XSS detection patterns
    xss_detector: XssDetector,
    /// Command injection detector
    command_injection_detector: CommandInjectionDetector,
    /// Path traversal detector
    path_traversal_detector: PathTraversalDetector,
    /// Malicious IP database
    threat_intel: ThreatIntelligence,
    /// Performance-optimized pattern matching
    pattern_matcher: AhoCorasick,
    /// Regular expression cache
    regex_cache: HashMap<String, Regex>,
}

impl ThreatDetector {
    pub fn new() -> Result<Self, String> {
        // Pre-compile threat patterns for maximum performance
        let threat_patterns = vec![
            // SQL injection patterns
            "union select", "drop table", "insert into", "delete from",
            "update set", "exec(", "execute(", "sp_executesql",

            // XSS patterns
            "<script", "javascript:", "onerror=", "onload=", "eval(",
            "alert(", "document.cookie", "window.location",

            // Command injection patterns
            "$(", "`", "|", "&", ";", "&&", "||", "../",
            "cmd.exe", "/bin/sh", "bash", "powershell",

            // Path traversal patterns
            "../", "..\\", "%2e%2e%2f", "%2e%2e%5c",
            "/etc/passwd", "/etc/shadow", "C:\\windows\\system32",
        ];

        let pattern_matcher = AhoCorasick::new(&threat_patterns)
            .map_err(|e| format!("Failed to create pattern matcher: {}", e))?;

        Ok(Self {
            sql_injection_detector: SqlInjectionDetector::new()?,
            xss_detector: XssDetector::new()?,
            command_injection_detector: CommandInjectionDetector::new()?,
            path_traversal_detector: PathTraversalDetector::new()?,
            threat_intel: ThreatIntelligence::new(),
            pattern_matcher,
            regex_cache: HashMap::new(),
        })
    }

    pub fn analyze_request(&mut self, request: &HttpRequest) -> Result<ThreatAnalysis, String> {
        let mut threats = Vec::new();
        let mut risk_score = 0.0;

        // Quick pattern matching scan first
        let suspicious_patterns = self.scan_for_patterns(request);
        if !suspicious_patterns.is_empty() {
            risk_score += 0.3;
            threats.extend(suspicious_patterns);
        }

        // Detailed SQL injection analysis
        if let Some(sql_threat) = self.sql_injection_detector.analyze(request)? {
            risk_score += sql_threat.severity;
            threats.push(sql_threat);
        }

        // XSS analysis
        if let Some(xss_threat) = self.xss_detector.analyze(request)? {
            risk_score += xss_threat.severity;
            threats.push(xss_threat);
        }

        // Command injection analysis
        if let Some(cmd_threat) = self.command_injection_detector.analyze(request)? {
            risk_score += cmd_threat.severity;
            threats.push(cmd_threat);
        }

        // Path traversal analysis
        if let Some(path_threat) = self.path_traversal_detector.analyze(request)? {
            risk_score += path_threat.severity;
            threats.push(path_threat);
        }

        // IP reputation check
        if let Some(ip) = &request.source_ip {
            if self.threat_intel.is_malicious_ip(ip)? {
                threats.push(Threat {
                    threat_type: ThreatType::MaliciousIp,
                    severity: 0.8,
                    description: format!("Request from known malicious IP: {}", ip),
                    evidence: vec![ip.clone()],
                });
                risk_score += 0.8;
            }
        }

        Ok(ThreatAnalysis {
            threats,
            risk_score: risk_score.min(1.0),
            scan_time_ms: 0.0, // Will be set by caller
        })
    }

    fn scan_for_patterns(&self, request: &HttpRequest) -> Vec<Threat> {
        let mut threats = Vec::new();

        // Combine all request data for scanning
        let mut scan_data = String::new();
        scan_data.push_str(&request.url);
        scan_data.push_str(&request.query_string.as_deref().unwrap_or(""));
        scan_data.push_str(&request.body.as_deref().unwrap_or(""));

        // Add headers
        for (key, value) in &request.headers {
            scan_data.push_str(key);
            scan_data.push_str(value);
        }

        // Case-insensitive scanning
        let scan_data_lower = scan_data.to_lowercase();

        for mat in self.pattern_matcher.find_iter(&scan_data_lower) {
            let pattern = &scan_data_lower[mat.start()..mat.end()];

            threats.push(Threat {
                threat_type: ThreatType::SuspiciousPattern,
                severity: 0.3,
                description: format!("Suspicious pattern detected: {}", pattern),
                evidence: vec![pattern.to_string()],
            });
        }

        threats
    }
}

/// Specialized SQL injection detector with context awareness
pub struct SqlInjectionDetector {
    /// SQL keyword patterns
    sql_keywords: AhoCorasick,
    /// SQL injection regex patterns
    injection_patterns: Vec<Regex>,
    /// Context-aware analysis
    context_analyzer: SqlContextAnalyzer,
}

impl SqlInjectionDetector {
    pub fn new() -> Result<Self, String> {
        let sql_keywords = vec![
            "select", "union", "insert", "update", "delete", "drop",
            "create", "alter", "exec", "execute", "sp_executesql",
            "waitfor", "benchmark", "sleep", "pg_sleep",
        ];

        let keyword_matcher = AhoCorasick::new_auto_configured(&sql_keywords)
            .map_err(|e| format!("Failed to create SQL keyword matcher: {}", e))?;

        let injection_patterns = vec![
            // Classic SQL injection patterns
            Regex::new(r"(?i)(\s|^)(union\s+select|union\s+all\s+select)")?,
            Regex::new(r"(?i)(select\s+.*\s+from\s+.*\s+where\s+.*=.*)")?,
            Regex::new(r"(?i)(insert\s+into\s+.*\s+values\s*\()")?,
            Regex::new(r"(?i)(update\s+.*\s+set\s+.*=.*)")?,
            Regex::new(r"(?i)(delete\s+from\s+.*\s+where\s+.*=.*)")?,

            // Blind SQL injection patterns
            Regex::new(r"(?i)(and\s+\d+\s*=\s*\d+|or\s+\d+\s*=\s*\d+)")?,
            Regex::new(r"(?i)(and\s+.*\s+like\s+.*|or\s+.*\s+like\s+.*)")?,

            // Time-based SQL injection
            Regex::new(r"(?i)(waitfor\s+delay|benchmark\s*\(|sleep\s*\(|pg_sleep\s*\()")?,

            // Error-based SQL injection
            Regex::new(r"(?i)(convert\s*\(|cast\s*\(|extractvalue\s*\()")?,
        ];

        Ok(Self {
            sql_keywords: keyword_matcher,
            injection_patterns,
            context_analyzer: SqlContextAnalyzer::new(),
        })
    }

    pub fn analyze(&self, request: &HttpRequest) -> Result<Option<Threat>, String> {
        let mut sql_indicators = 0;
        let mut evidence = Vec::new();
        let mut max_severity = 0.0;

        // Analyze URL parameters
        if let Some(query) = &request.query_string {
            let (indicators, query_evidence, severity) = self.analyze_string(query)?;
            sql_indicators += indicators;
            evidence.extend(query_evidence);
            max_severity = max_severity.max(severity);
        }

        // Analyze POST body
        if let Some(body) = &request.body {
            let (indicators, body_evidence, severity) = self.analyze_string(body)?;
            sql_indicators += indicators;
            evidence.extend(body_evidence);
            max_severity = max_severity.max(severity);
        }

        // Analyze headers (some attacks use headers)
        for (key, value) in &request.headers {
            if key.to_lowercase().contains("x-") || key.to_lowercase().contains("user-agent") {
                let (indicators, header_evidence, severity) = self.analyze_string(value)?;
                sql_indicators += indicators;
                evidence.extend(header_evidence);
                max_severity = max_severity.max(severity);
            }
        }

        // Determine if this is likely SQL injection
        if sql_indicators >= 2 || max_severity > 0.7 {
            Ok(Some(Threat {
                threat_type: ThreatType::SqlInjection,
                severity: max_severity,
                description: format!("SQL injection detected with {} indicators", sql_indicators),
                evidence,
            }))
        } else {
            Ok(None)
        }
    }

    fn analyze_string(&self, input: &str) -> Result<(usize, Vec<String>, f64), String> {
        let mut indicators = 0;
        let mut evidence = Vec::new();
        let mut max_severity = 0.0;

        // URL decode the input
        let decoded = url_decode(input);
        let input_lower = decoded.to_lowercase();

        // Check for SQL keywords
        for mat in self.sql_keywords.find_iter(&input_lower) {
            indicators += 1;
            let keyword = &input_lower[mat.start()..mat.end()];
            evidence.push(format!("SQL keyword: {}", keyword));
        }

        // Check against regex patterns
        for (i, pattern) in self.injection_patterns.iter().enumerate() {
            if pattern.is_match(&input_lower) {
                indicators += 2; // Regex matches are more significant
                let severity = match i {
                    0..=4 => 0.8,  // Classic injection patterns
                    5..=6 => 0.6,  // Blind injection patterns
                    7 => 0.9,      // Time-based injection
                    8 => 0.7,      // Error-based injection
                    _ => 0.5,
                };
                max_severity = max_severity.max(severity);
                evidence.push(format!("SQL injection pattern #{}", i));
            }
        }

        // Context-aware analysis
        let context_score = self.context_analyzer.analyze_context(&decoded);
        if context_score > 0.5 {
            indicators += 1;
            max_severity = max_severity.max(context_score);
            evidence.push("Suspicious SQL context detected".to_string());
        }

        Ok((indicators, evidence, max_severity))
    }
}

/// Context-aware SQL analysis
pub struct SqlContextAnalyzer {
    /// Common SQL table names
    table_names: AhoCorasick,
    /// SQL operators and functions
    sql_operators: AhoCorasick,
}

impl SqlContextAnalyzer {
    pub fn new() -> Self {
        let table_names = vec![
            "users", "user", "admin", "administrators", "accounts", "login",
            "passwords", "password", "members", "member", "customers",
            "orders", "products", "sessions", "logs", "config", "settings",
        ];

        let sql_operators = vec![
            "where", "order by", "group by", "having", "limit", "offset",
            "inner join", "left join", "right join", "outer join",
            "count(", "sum(", "avg(", "max(", "min(",
        ];

        Self {
            table_names: AhoCorasick::new_auto_configured(&table_names).unwrap(),
            sql_operators: AhoCorasick::new_auto_configured(&sql_operators).unwrap(),
        }
    }

    pub fn analyze_context(&self, input: &str) -> f64 {
        let input_lower = input.to_lowercase();
        let mut score = 0.0;

        // Check for table names
        let table_matches = self.table_names.find_iter(&input_lower).count();
        if table_matches > 0 {
            score += 0.3 * (table_matches as f64).min(3.0) / 3.0;
        }

        // Check for SQL operators
        let operator_matches = self.sql_operators.find_iter(&input_lower).count();
        if operator_matches > 0 {
            score += 0.4 * (operator_matches as f64).min(5.0) / 5.0;
        }

        // Check for quotes and comment patterns
        let single_quotes = input_lower.matches('\'').count();
        let double_quotes = input_lower.matches('"').count();
        let sql_comments = input_lower.matches("--").count() + input_lower.matches("/*").count();

        if single_quotes > 2 || double_quotes > 2 {
            score += 0.2;
        }

        if sql_comments > 0 {
            score += 0.3;
        }

        score.min(1.0)
    }
}

// Helper function for URL decoding
fn url_decode(input: &str) -> String {
    let mut result = String::with_capacity(input.len());
    let mut chars = input.chars().peekable();

    while let Some(ch) = chars.next() {
        if ch == '%' {
            // Try to decode hex sequence
            let hex1 = chars.next();
            let hex2 = chars.next();

            if let (Some(h1), Some(h2)) = (hex1, hex2) {
                if let Ok(byte) = u8::from_str_radix(&format!("{}{}", h1, h2), 16) {
                    result.push(byte as char);
                    continue;
                }
            }

            // If decoding failed, keep the original characters
            result.push(ch);
            if let Some(h1) = hex1 { result.push(h1); }
            if let Some(h2) = hex2 { result.push(h2); }
        } else if ch == '+' {
            result.push(' ');
        } else {
            result.push(ch);
        }
    }

    result
}

Cryptographic Services for Edge Security

Implementing high-performance cryptography optimized for WASM:

use aes_gcm::{Aes256Gcm, KeyInit, Nonce};
use aes_gcm::aead::{Aead, OsRng};
use chacha20poly1305::{ChaCha20Poly1305, Key};
use hmac::{Hmac, Mac};
use sha2::Sha256;
use blake3::Hasher;
use ring::{digest, rand::SecureRandom};

/// High-performance cryptographic services for WASM
pub struct CryptoService {
    /// Random number generator
    rng: ring::rand::SystemRandom,
    /// Performance metrics
    crypto_metrics: CryptoMetrics,
}

impl CryptoService {
    pub fn new() -> Result<Self, String> {
        Ok(Self {
            rng: ring::rand::SystemRandom::new(),
            crypto_metrics: CryptoMetrics::new(),
        })
    }

    /// Encrypt data using AES-256-GCM
    pub fn encrypt_aes_gcm(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
        if key.len() != 32 {
            return Err("Key must be 32 bytes for AES-256".to_string());
        }

        let start_time = js_sys::Date::now();

        // Create AES-GCM cipher
        let cipher = Aes256Gcm::new_from_slice(key)
            .map_err(|e| format!("Failed to create cipher: {}", e))?;

        // Generate random nonce
        let mut nonce_bytes = [0u8; 12];
        self.rng.fill(&mut nonce_bytes)
            .map_err(|e| format!("Failed to generate nonce: {}", e))?;
        let nonce = Nonce::from_slice(&nonce_bytes);

        // Encrypt the data
        let ciphertext = cipher.encrypt(nonce, data)
            .map_err(|e| format!("Encryption failed: {}", e))?;

        // Prepend nonce to ciphertext
        let mut result = Vec::with_capacity(12 + ciphertext.len());
        result.extend_from_slice(&nonce_bytes);
        result.extend_from_slice(&ciphertext);

        // Record performance metrics
        let duration = js_sys::Date::now() - start_time;
        self.crypto_metrics.record_encryption(data.len(), duration);

        Ok(result)
    }

    /// Decrypt data using AES-256-GCM
    pub fn decrypt_aes_gcm(&self, encrypted_data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
        if key.len() != 32 {
            return Err("Key must be 32 bytes for AES-256".to_string());
        }

        if encrypted_data.len() < 12 {
            return Err("Encrypted data too short".to_string());
        }

        let start_time = js_sys::Date::now();

        // Extract nonce and ciphertext
        let (nonce_bytes, ciphertext) = encrypted_data.split_at(12);
        let nonce = Nonce::from_slice(nonce_bytes);

        // Create AES-GCM cipher
        let cipher = Aes256Gcm::new_from_slice(key)
            .map_err(|e| format!("Failed to create cipher: {}", e))?;

        // Decrypt the data
        let plaintext = cipher.decrypt(nonce, ciphertext)
            .map_err(|e| format!("Decryption failed: {}", e))?;

        // Record performance metrics
        let duration = js_sys::Date::now() - start_time;
        self.crypto_metrics.record_decryption(plaintext.len(), duration);

        Ok(plaintext)
    }

    /// Encrypt using ChaCha20-Poly1305 (often faster than AES on some platforms)
    pub fn encrypt_chacha20poly1305(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
        if key.len() != 32 {
            return Err("Key must be 32 bytes for ChaCha20-Poly1305".to_string());
        }

        let cipher = ChaCha20Poly1305::new(Key::from_slice(key));

        // Generate random nonce
        let mut nonce_bytes = [0u8; 12];
        self.rng.fill(&mut nonce_bytes)
            .map_err(|e| format!("Failed to generate nonce: {}", e))?;
        let nonce = chacha20poly1305::Nonce::from_slice(&nonce_bytes);

        // Encrypt
        let ciphertext = cipher.encrypt(nonce, data)
            .map_err(|e| format!("ChaCha20-Poly1305 encryption failed: {}", e))?;

        // Prepend nonce
        let mut result = Vec::with_capacity(12 + ciphertext.len());
        result.extend_from_slice(&nonce_bytes);
        result.extend_from_slice(&ciphertext);

        Ok(result)
    }

    /// Generate cryptographically secure random bytes
    pub fn generate_random_bytes(&self, length: usize) -> Result<Vec<u8>, String> {
        let mut bytes = vec![0u8; length];
        self.rng.fill(&mut bytes)
            .map_err(|e| format!("Failed to generate random bytes: {}", e))?;
        Ok(bytes)
    }

    /// Hash data using BLAKE3 (faster than SHA-256)
    pub fn hash_blake3(&self, data: &[u8]) -> Vec<u8> {
        let start_time = js_sys::Date::now();

        let mut hasher = Hasher::new();
        hasher.update(data);
        let hash = hasher.finalize();

        // Record performance metrics
        let duration = js_sys::Date::now() - start_time;
        self.crypto_metrics.record_hash(data.len(), duration);

        hash.as_bytes().to_vec()
    }

    /// Hash data using SHA-256
    pub fn hash_sha256(&self, data: &[u8]) -> Vec<u8> {
        let digest = digest::digest(&digest::SHA256, data);
        digest.as_ref().to_vec()
    }

    /// Generate HMAC-SHA256
    pub fn generate_hmac_sha256(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>, String> {
        type HmacSha256 = Hmac<Sha256>;

        let mut mac = HmacSha256::new_from_slice(key)
            .map_err(|e| format!("Invalid HMAC key: {}", e))?;

        mac.update(data);
        let result = mac.finalize();

        Ok(result.into_bytes().to_vec())
    }

    /// Verify HMAC-SHA256
    pub fn verify_hmac_sha256(&self, data: &[u8], signature: &[u8], key: &[u8]) -> bool {
        match self.generate_hmac_sha256(data, key) {
            Ok(expected) => {
                // Constant-time comparison
                expected.len() == signature.len() &&
                expected.iter().zip(signature.iter()).all(|(a, b)| a == b)
            }
            Err(_) => false,
        }
    }

    /// Generate a secure session token
    pub fn generate_session_token(&self, user_id: &str, expiry: u64) -> Result<String, String> {
        // Create token payload
        let payload = format!("{}:{}", user_id, expiry);

        // Generate random key
        let key = self.generate_random_bytes(32)?;

        // Create HMAC
        let signature = self.generate_hmac_sha256(payload.as_bytes(), &key)?;

        // Encode token
        let token_data = [payload.as_bytes(), &key, &signature].concat();
        Ok(base64::encode(token_data))
    }

    /// Verify session token
    pub fn verify_session_token(&self, token: &str) -> Result<(String, u64), String> {
        let token_data = base64::decode(token)
            .map_err(|e| format!("Invalid token encoding: {}", e))?;

        if token_data.len() < 64 {
            return Err("Token too short".to_string());
        }

        // Extract components
        let (payload_and_key, signature) = token_data.split_at(token_data.len() - 32);
        let (payload, key) = payload_and_key.split_at(payload_and_key.len() - 32);

        // Verify HMAC
        if !self.verify_hmac_sha256(payload, signature, key) {
            return Err("Invalid token signature".to_string());
        }

        // Parse payload
        let payload_str = std::str::from_utf8(payload)
            .map_err(|e| format!("Invalid payload encoding: {}", e))?;

        let parts: Vec<&str> = payload_str.split(':').collect();
        if parts.len() != 2 {
            return Err("Invalid payload format".to_string());
        }

        let user_id = parts[0].to_string();
        let expiry = parts[1].parse::<u64>()
            .map_err(|e| format!("Invalid expiry: {}", e))?;

        Ok((user_id, expiry))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CryptoMetrics {
    encryptions_performed: u32,
    decryptions_performed: u32,
    hashes_computed: u32,
    average_encryption_time: f64,
    average_decryption_time: f64,
    average_hash_time: f64,
    total_bytes_encrypted: u64,
    total_bytes_decrypted: u64,
    total_bytes_hashed: u64,
}

impl CryptoMetrics {
    pub fn new() -> Self {
        Self {
            encryptions_performed: 0,
            decryptions_performed: 0,
            hashes_computed: 0,
            average_encryption_time: 0.0,
            average_decryption_time: 0.0,
            average_hash_time: 0.0,
            total_bytes_encrypted: 0,
            total_bytes_decrypted: 0,
            total_bytes_hashed: 0,
        }
    }

    pub fn record_encryption(&mut self, bytes: usize, duration_ms: f64) {
        self.encryptions_performed += 1;
        self.total_bytes_encrypted += bytes as u64;
        self.average_encryption_time =
            (self.average_encryption_time * (self.encryptions_performed - 1) as f64 + duration_ms)
            / self.encryptions_performed as f64;
    }

    pub fn record_decryption(&mut self, bytes: usize, duration_ms: f64) {
        self.decryptions_performed += 1;
        self.total_bytes_decrypted += bytes as u64;
        self.average_decryption_time =
            (self.average_decryption_time * (self.decryptions_performed - 1) as f64 + duration_ms)
            / self.decryptions_performed as f64;
    }

    pub fn record_hash(&mut self, bytes: usize, duration_ms: f64) {
        self.hashes_computed += 1;
        self.total_bytes_hashed += bytes as u64;
        self.average_hash_time =
            (self.average_hash_time * (self.hashes_computed - 1) as f64 + duration_ms)
            / self.hashes_computed as f64;
    }
}

Edge Deployment Strategies

Let’s implement deployment strategies for different edge environments:

// Edge deployment configurations for different platforms

/// CDN Edge Worker deployment
#[wasm_bindgen]
pub struct CdnEdgeWorker {
    security_runtime: WasmSecurityRuntime,
    cache: EdgeCache,
    rate_limiter: RateLimiter,
}

#[wasm_bindgen]
impl CdnEdgeWorker {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<CdnEdgeWorker, JsValue> {
        Ok(CdnEdgeWorker {
            security_runtime: WasmSecurityRuntime::new()?,
            cache: EdgeCache::new(1000), // 1000 entry cache
            rate_limiter: RateLimiter::new(100, 60), // 100 requests per minute
        })
    }

    /// Process HTTP request at CDN edge
    #[wasm_bindgen]
    pub async fn process_request(&mut self, request_json: &str) -> Result<JsValue, JsValue> {
        let request: HttpRequest = serde_json::from_str(request_json)?;

        // Check rate limiting first (fastest check)
        if !self.rate_limiter.check_rate_limit(&request.source_ip.as_deref().unwrap_or("unknown")) {
            return Ok(serde_wasm_bindgen::to_value(&SecurityResult {
                allowed: false,
                security_score: 0.0,
                threat_detected: true,
                policy_violations: vec!["rate_limit_exceeded".to_string()],
                processing_time_ms: 1.0,
                details: SecurityAnalysis::new(),
            })?);
        }

        // Check cache for previous analysis
        let cache_key = self.generate_cache_key(&request);
        if let Some(cached_result) = self.cache.get(&cache_key) {
            return Ok(serde_wasm_bindgen::to_value(&cached_result)?);
        }

        // Perform security analysis
        let result = self.security_runtime.analyze_http_request(request_json)?;
        let security_result: SecurityResult = serde_wasm_bindgen::from_value(result)?;

        // Cache the result for future requests
        if security_result.processing_time_ms < 10.0 { // Only cache fast results
            self.cache.insert(cache_key, security_result.clone());
        }

        Ok(serde_wasm_bindgen::to_value(&security_result)?)
    }

    fn generate_cache_key(&self, request: &HttpRequest) -> String {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        let mut hasher = DefaultHasher::new();
        request.url.hash(&mut hasher);
        request.method.hash(&mut hasher);
        request.body.hash(&mut hasher);

        format!("{:x}", hasher.finish())
    }
}

/// IoT Gateway deployment for resource-constrained environments
#[wasm_bindgen]
pub struct IoTGatewaySecruity {
    lightweight_detector: LightweightThreatDetector,
    device_authenticator: DeviceAuthenticator,
    message_validator: MessageValidator,
}

#[wasm_bindgen]
impl IoTGatewaySecruity {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<IoTGatewaySecruity, JsValue> {
        Ok(IoTGatewaySecruity {
            lightweight_detector: LightweightThreatDetector::new(),
            device_authenticator: DeviceAuthenticator::new()?,
            message_validator: MessageValidator::new(),
        })
    }

    /// Validate IoT device message
    #[wasm_bindgen]
    pub fn validate_iot_message(&mut self, message_json: &str) -> Result<JsValue, JsValue> {
        let message: IoTMessage = serde_json::from_str(message_json)?;

        let mut validation_result = IoTValidationResult::new();

        // 1. Authenticate device
        let auth_result = self.device_authenticator.authenticate_device(&message.device_id, &message.signature)?;
        validation_result.device_authenticated = auth_result;

        if !auth_result {
            validation_result.allowed = false;
            validation_result.reason = "Device authentication failed".to_string();
            return Ok(serde_wasm_bindgen::to_value(&validation_result)?);
        }

        // 2. Validate message format and content
        let msg_validation = self.message_validator.validate(&message)?;
        validation_result.message_valid = msg_validation.valid;

        if !msg_validation.valid {
            validation_result.allowed = false;
            validation_result.reason = msg_validation.reason;
            return Ok(serde_wasm_bindgen::to_value(&validation_result)?);
        }

        // 3. Lightweight threat detection
        let threat_result = self.lightweight_detector.scan_message(&message)?;
        validation_result.threats_detected = !threat_result.threats.is_empty();
        validation_result.threat_score = threat_result.risk_score;

        // Final decision
        validation_result.allowed = validation_result.device_authenticated &&
                                  validation_result.message_valid &&
                                  validation_result.threat_score < 0.7;

        Ok(serde_wasm_bindgen::to_value(&validation_result)?)
    }
}

/// Browser-based security for client-side protection
#[wasm_bindgen]
pub struct BrowserSecurityShield {
    dom_protector: DomProtector,
    xss_detector: XssDetector,
    csp_enforcer: CspEnforcer,
}

#[wasm_bindgen]
impl BrowserSecurityShield {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<BrowserSecurityShield, JsValue> {
        Ok(BrowserSecurityShield {
            dom_protector: DomProtector::new(),
            xss_detector: XssDetector::new()?,
            csp_enforcer: CspEnforcer::new(),
        })
    }

    /// Monitor DOM mutations for malicious changes
    #[wasm_bindgen]
    pub fn monitor_dom_mutations(&mut self, mutations_json: &str) -> Result<JsValue, JsValue> {
        let mutations: Vec<DomMutation> = serde_json::from_str(mutations_json)?;

        let mut protection_result = DomProtectionResult::new();

        for mutation in mutations {
            // Check for script injection
            if let Some(xss_threat) = self.xss_detector.analyze_dom_mutation(&mutation)? {
                protection_result.threats.push(xss_threat);
                protection_result.blocked_mutations.push(mutation.clone());
            }

            // Check against CSP policies
            if !self.csp_enforcer.allows_mutation(&mutation) {
                protection_result.csp_violations.push(mutation.clone());
                protection_result.blocked_mutations.push(mutation);
            }
        }

        protection_result.safe = protection_result.threats.is_empty() &&
                               protection_result.csp_violations.is_empty();

        Ok(serde_wasm_bindgen::to_value(&protection_result)?)
    }

    /// Validate JavaScript execution
    #[wasm_bindgen]
    pub fn validate_script_execution(&self, script_content: &str) -> Result<JsValue, JsValue> {
        let analysis = self.xss_detector.analyze_javascript(script_content)?;
        Ok(serde_wasm_bindgen::to_value(&analysis)?)
    }
}

Performance Optimization and Benchmarking

Let’s implement comprehensive performance optimization for WASM deployment:

/// Performance optimizer for WASM security runtime
pub struct WasmPerformanceOptimizer {
    /// Memory pool for reducing allocations
    memory_pool: MemoryPool,
    /// String interning for common patterns
    string_interner: StringInterner,
    /// Compilation cache for regex patterns
    regex_cache: RegexCache,
    /// Performance profiler
    profiler: WasmProfiler,
}

impl WasmPerformanceOptimizer {
    pub fn new() -> Self {
        Self {
            memory_pool: MemoryPool::new(1024 * 1024), // 1MB pool
            string_interner: StringInterner::new(),
            regex_cache: RegexCache::new(100), // Cache 100 patterns
            profiler: WasmProfiler::new(),
        }
    }

    /// Optimize memory usage for WASM environment
    pub fn optimize_memory_usage(&mut self) {
        // Run garbage collection
        self.memory_pool.collect_garbage();

        // Compact string interner
        self.string_interner.compact();

        // Clear unused regex patterns
        self.regex_cache.cleanup_unused();
    }

    /// Profile performance hotspots
    pub fn profile_performance(&mut self, operation: &str, duration_ms: f64) {
        self.profiler.record_operation(operation, duration_ms);

        // Auto-optimize if we detect performance issues
        if self.profiler.needs_optimization(operation) {
            self.auto_optimize(operation);
        }
    }

    fn auto_optimize(&mut self, operation: &str) {
        match operation {
            "threat_detection" => {
                // Optimize threat detection patterns
                self.optimize_threat_patterns();
            }
            "crypto_operations" => {
                // Optimize cryptographic operations
                self.optimize_crypto_performance();
            }
            "string_processing" => {
                // Optimize string processing
                self.optimize_string_operations();
            }
            _ => {}
        }
    }
}

/// Memory pool for reducing WASM allocations
pub struct MemoryPool {
    /// Pre-allocated buffers
    buffers: Vec<Vec<u8>>,
    /// Available buffer indices
    available: Vec<usize>,
    /// Total pool size
    total_size: usize,
}

impl MemoryPool {
    pub fn new(size: usize) -> Self {
        let buffer_count = 64;
        let buffer_size = size / buffer_count;

        let mut buffers = Vec::with_capacity(buffer_count);
        let mut available = Vec::with_capacity(buffer_count);

        for i in 0..buffer_count {
            buffers.push(vec![0u8; buffer_size]);
            available.push(i);
        }

        Self {
            buffers,
            available,
            total_size: size,
        }
    }

    pub fn acquire_buffer(&mut self, min_size: usize) -> Option<Vec<u8>> {
        if let Some(index) = self.available.pop() {
            let mut buffer = std::mem::take(&mut self.buffers[index]);

            if buffer.len() < min_size {
                buffer.resize(min_size, 0);
            }

            Some(buffer)
        } else {
            // Pool exhausted, allocate new buffer
            Some(vec![0u8; min_size])
        }
    }

    pub fn release_buffer(&mut self, mut buffer: Vec<u8>) {
        if self.available.len() < self.buffers.len() {
            // Clear the buffer
            buffer.clear();

            // Find an empty slot
            for (i, buf) in self.buffers.iter_mut().enumerate() {
                if buf.is_empty() {
                    *buf = buffer;
                    self.available.push(i);
                    return;
                }
            }
        }

        // Buffer will be dropped here if pool is full
    }
}

/// JavaScript interface for performance monitoring
#[wasm_bindgen]
pub struct WasmPerformanceMonitor {
    start_times: std::collections::HashMap<String, f64>,
    metrics: PerformanceMetrics,
}

#[wasm_bindgen]
impl WasmPerformanceMonitor {
    #[wasm_bindgen(constructor)]
    pub fn new() -> WasmPerformanceMonitor {
        WasmPerformanceMonitor {
            start_times: std::collections::HashMap::new(),
            metrics: PerformanceMetrics::new(),
        }
    }

    /// Start timing an operation
    #[wasm_bindgen]
    pub fn start_timer(&mut self, operation: &str) {
        let start_time = js_sys::Date::now();
        self.start_times.insert(operation.to_string(), start_time);
    }

    /// End timing an operation
    #[wasm_bindgen]
    pub fn end_timer(&mut self, operation: &str) -> f64 {
        if let Some(start_time) = self.start_times.remove(operation) {
            let duration = js_sys::Date::now() - start_time;
            self.metrics.record_operation(operation, duration);
            duration
        } else {
            0.0
        }
    }

    /// Get performance metrics
    #[wasm_bindgen]
    pub fn get_metrics(&self) -> Result<JsValue, JsValue> {
        Ok(serde_wasm_bindgen::to_value(&self.metrics)?)
    }

    /// Get memory usage statistics
    #[wasm_bindgen]
    pub fn get_memory_usage(&self) -> JsValue {
        let memory = wasm_bindgen::memory();
        let buffer = memory.buffer();

        serde_wasm_bindgen::to_value(&serde_json::json!({
            "used_bytes": buffer.byte_length(),
            "total_pages": memory.grow(0), // Get current page count
        })).unwrap_or(JsValue::NULL)
    }
}

/// Benchmark suite for WASM security operations
#[wasm_bindgen]
pub struct WasmBenchmarkSuite {
    security_runtime: WasmSecurityRuntime,
    test_data: TestDataGenerator,
}

#[wasm_bindgen]
impl WasmBenchmarkSuite {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<WasmBenchmarkSuite, JsValue> {
        Ok(WasmBenchmarkSuite {
            security_runtime: WasmSecurityRuntime::new()?,
            test_data: TestDataGenerator::new(),
        })
    }

    /// Run comprehensive performance benchmarks
    #[wasm_bindgen]
    pub fn run_benchmarks(&mut self) -> Result<JsValue, JsValue> {
        let mut results = BenchmarkResults::new();

        // Benchmark threat detection
        let threat_benchmark = self.benchmark_threat_detection(1000)?;
        results.add_result("threat_detection", threat_benchmark);

        // Benchmark cryptographic operations
        let crypto_benchmark = self.benchmark_crypto_operations(500)?;
        results.add_result("crypto_operations", crypto_benchmark);

        // Benchmark policy evaluation
        let policy_benchmark = self.benchmark_policy_evaluation(1000)?;
        results.add_result("policy_evaluation", policy_benchmark);

        Ok(serde_wasm_bindgen::to_value(&results)?)
    }

    fn benchmark_threat_detection(&mut self, iterations: usize) -> Result<BenchmarkResult, JsValue> {
        let test_requests = self.test_data.generate_http_requests(iterations);

        let start_time = js_sys::Date::now();
        let mut total_threats = 0;

        for request in test_requests {
            let request_json = serde_json::to_string(&request).unwrap();
            let result = self.security_runtime.analyze_http_request(&request_json)?;
            let security_result: SecurityResult = serde_wasm_bindgen::from_value(result)?;

            if security_result.threat_detected {
                total_threats += 1;
            }
        }

        let total_time = js_sys::Date::now() - start_time;
        let avg_time = total_time / iterations as f64;

        Ok(BenchmarkResult {
            operation: "threat_detection".to_string(),
            iterations,
            total_time_ms: total_time,
            average_time_ms: avg_time,
            operations_per_second: (iterations as f64 * 1000.0) / total_time,
            additional_metrics: serde_json::json!({
                "threats_detected": total_threats,
                "detection_rate": (total_threats as f64) / (iterations as f64)
            }),
        })
    }
}

Conclusion

WebAssembly security runtimes represent the future of edge protection, combining the performance of native code with the security of sandboxed execution. Our Rust implementation delivers:

Performance Achievements:

Security Benefits:

Production Results:

Key innovations:

The complete implementation includes deployment scripts for major CDN providers, integration guides for IoT platforms, and performance optimization tools.

Next Steps

WebAssembly security runtimes enable ubiquitous protection—from cloud to edge to device. With Rust’s safety and performance guarantees, we can secure the entire distributed computing spectrum.