发布于

Rust-Wasm加解密安全防护方案:构建高安全性的Web加密系统

作者

Rust-Wasm加解密安全防护方案:构建高安全性的Web加密系统

在Web应用中,数据安全和隐私保护至关重要。Rust与WebAssembly的结合为构建高性能、高安全性的加密系统提供了理想的平台。本文将详细介绍完整的加解密安全防护方案。

项目配置和依赖

核心依赖配置

# Cargo.toml - 加密安全项目配置
[package]
name = "rust-wasm-crypto"
version = "0.1.0"
edition = "2021"

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

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

# 加密相关依赖
ring = "0.16"
aes-gcm = "0.10"
chacha20poly1305 = "0.10"
rsa = "0.9"
ed25519-dalek = "1.0"
sha2 = "0.10"
sha3 = "0.10"
blake3 = "1.0"
argon2 = "0.5"
rand = "0.8"
rand_chacha = "0.3"
zeroize = { version = "1.0", features = ["zeroize_derive"] }
subtle = "2.4"

[dependencies.web-sys]
version = "0.3"
features = [
  "console",
  "Crypto",
  "SubtleCrypto",
  "CryptoKey",
  "Window",
  "Performance",
]

# 优化配置
[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
panic = "abort"

基础安全模块

// src/lib.rs - 核心安全模块
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use zeroize::{Zeroize, ZeroizeOnDrop};

// 全局设置
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

#[wasm_bindgen(start)]
pub fn main() {
    console_error_panic_hook::set_once();
}

// 安全随机数生成器
#[wasm_bindgen]
pub struct SecureRandom;

#[wasm_bindgen]
impl SecureRandom {
    #[wasm_bindgen(constructor)]
    pub fn new() -> SecureRandom {
        SecureRandom
    }
    
    #[wasm_bindgen]
    pub fn generate_bytes(&self, length: usize) -> Vec<u8> {
        use rand::RngCore;
        let mut rng = rand::thread_rng();
        let mut bytes = vec![0u8; length];
        rng.fill_bytes(&mut bytes);
        bytes
    }
    
    #[wasm_bindgen]
    pub fn generate_u32(&self) -> u32 {
        use rand::RngCore;
        rand::thread_rng().next_u32()
    }
    
    #[wasm_bindgen]
    pub fn generate_u64(&self) -> u64 {
        use rand::RngCore;
        rand::thread_rng().next_u64()
    }
}

// 安全内存管理
#[derive(Zeroize, ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct SecureBuffer {
    #[zeroize(skip)]
    data: Vec<u8>,
}

#[wasm_bindgen]
impl SecureBuffer {
    #[wasm_bindgen(constructor)]
    pub fn new(size: usize) -> SecureBuffer {
        SecureBuffer {
            data: vec![0u8; size],
        }
    }
    
    #[wasm_bindgen]
    pub fn from_bytes(bytes: &[u8]) -> SecureBuffer {
        SecureBuffer {
            data: bytes.to_vec(),
        }
    }
    
    #[wasm_bindgen]
    pub fn len(&self) -> usize {
        self.data.len()
    }
    
    #[wasm_bindgen]
    pub fn as_bytes(&self) -> Vec<u8> {
        self.data.clone()
    }
    
    #[wasm_bindgen]
    pub fn copy_from(&mut self, source: &[u8]) {
        if source.len() <= self.data.len() {
            self.data[..source.len()].copy_from_slice(source);
        }
    }
    
    #[wasm_bindgen]
    pub fn clear(&mut self) {
        self.data.zeroize();
    }
}

// 哈希函数集合
#[wasm_bindgen]
pub struct HashFunctions;

#[wasm_bindgen]
impl HashFunctions {
    #[wasm_bindgen(constructor)]
    pub fn new() -> HashFunctions {
        HashFunctions
    }
    
    #[wasm_bindgen]
    pub fn sha256(&self, data: &[u8]) -> Vec<u8> {
        use sha2::{Sha256, Digest};
        let mut hasher = Sha256::new();
        hasher.update(data);
        hasher.finalize().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn sha512(&self, data: &[u8]) -> Vec<u8> {
        use sha2::{Sha512, Digest};
        let mut hasher = Sha512::new();
        hasher.update(data);
        hasher.finalize().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn sha3_256(&self, data: &[u8]) -> Vec<u8> {
        use sha3::{Sha3_256, Digest};
        let mut hasher = Sha3_256::new();
        hasher.update(data);
        hasher.finalize().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn blake3(&self, data: &[u8]) -> Vec<u8> {
        blake3::hash(data).as_bytes().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn hmac_sha256(&self, key: &[u8], data: &[u8]) -> Vec<u8> {
        use ring::hmac;
        let key = hmac::Key::new(hmac::HMAC_SHA256, key);
        hmac::sign(&key, data).as_ref().to_vec()
    }
}

// 密钥派生函数
#[wasm_bindgen]
pub struct KeyDerivation;

#[wasm_bindgen]
impl KeyDerivation {
    #[wasm_bindgen(constructor)]
    pub fn new() -> KeyDerivation {
        KeyDerivation
    }
    
    #[wasm_bindgen]
    pub fn pbkdf2_sha256(&self, password: &[u8], salt: &[u8], iterations: u32, output_len: usize) -> Vec<u8> {
        use ring::pbkdf2;
        let mut output = vec![0u8; output_len];
        pbkdf2::derive(
            pbkdf2::PBKDF2_HMAC_SHA256,
            std::num::NonZeroU32::new(iterations).unwrap(),
            salt,
            password,
            &mut output,
        );
        output
    }
    
    #[wasm_bindgen]
    pub fn argon2id(&self, password: &[u8], salt: &[u8], memory_cost: u32, time_cost: u32, parallelism: u32, output_len: usize) -> Result<Vec<u8>, JsValue> {
        use argon2::{Argon2, Algorithm, Version, Params};
        
        let params = Params::new(memory_cost, time_cost, parallelism, Some(output_len))
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        
        let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
        
        let mut output = vec![0u8; output_len];
        argon2.hash_password_into(password, salt, &mut output)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        
        Ok(output)
    }
    
    #[wasm_bindgen]
    pub fn hkdf_sha256(&self, ikm: &[u8], salt: &[u8], info: &[u8], output_len: usize) -> Vec<u8> {
        use ring::hkdf;
        let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, salt);
        let prk = salt.extract(ikm);
        let okm = prk.expand(&[info], hkdf::HKDF_SHA256).unwrap();
        let mut output = vec![0u8; output_len];
        okm.fill(&mut output).unwrap();
        output
    }
}

对称加密实现

// src/symmetric.rs - 对称加密模块
use wasm_bindgen::prelude::*;
use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, NewAead}};
use chacha20poly1305::{ChaCha20Poly1305, Key as ChaChaKey, Nonce as ChaChaNonce};
use zeroize::{Zeroize, ZeroizeOnDrop};

// AES-GCM 加密器
#[derive(ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct AesGcmCipher {
    #[zeroize(skip)]
    cipher: Aes256Gcm,
}

#[wasm_bindgen]
impl AesGcmCipher {
    #[wasm_bindgen(constructor)]
    pub fn new(key: &[u8]) -> Result<AesGcmCipher, JsValue> {
        if key.len() != 32 {
            return Err(JsValue::from_str("Key must be 32 bytes"));
        }
        
        let key = Key::from_slice(key);
        let cipher = Aes256Gcm::new(key);
        
        Ok(AesGcmCipher { cipher })
    }
    
    #[wasm_bindgen]
    pub fn encrypt(&self, plaintext: &[u8], nonce: &[u8], aad: &[u8]) -> Result<Vec<u8>, JsValue> {
        if nonce.len() != 12 {
            return Err(JsValue::from_str("Nonce must be 12 bytes"));
        }
        
        let nonce = Nonce::from_slice(nonce);
        
        let ciphertext = if aad.is_empty() {
            self.cipher.encrypt(nonce, plaintext)
        } else {
            self.cipher.encrypt(nonce, aes_gcm::aead::Payload {
                msg: plaintext,
                aad,
            })
        };
        
        ciphertext.map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn decrypt(&self, ciphertext: &[u8], nonce: &[u8], aad: &[u8]) -> Result<Vec<u8>, JsValue> {
        if nonce.len() != 12 {
            return Err(JsValue::from_str("Nonce must be 12 bytes"));
        }
        
        let nonce = Nonce::from_slice(nonce);
        
        let plaintext = if aad.is_empty() {
            self.cipher.decrypt(nonce, ciphertext)
        } else {
            self.cipher.decrypt(nonce, aes_gcm::aead::Payload {
                msg: ciphertext,
                aad,
            })
        };
        
        plaintext.map_err(|e| JsValue::from_str(&e.to_string()))
    }
}

// ChaCha20-Poly1305 加密器
#[derive(ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct ChaCha20Poly1305Cipher {
    #[zeroize(skip)]
    cipher: ChaCha20Poly1305,
}

#[wasm_bindgen]
impl ChaCha20Poly1305Cipher {
    #[wasm_bindgen(constructor)]
    pub fn new(key: &[u8]) -> Result<ChaCha20Poly1305Cipher, JsValue> {
        if key.len() != 32 {
            return Err(JsValue::from_str("Key must be 32 bytes"));
        }
        
        let key = ChaChaKey::from_slice(key);
        let cipher = ChaCha20Poly1305::new(key);
        
        Ok(ChaCha20Poly1305Cipher { cipher })
    }
    
    #[wasm_bindgen]
    pub fn encrypt(&self, plaintext: &[u8], nonce: &[u8], aad: &[u8]) -> Result<Vec<u8>, JsValue> {
        if nonce.len() != 12 {
            return Err(JsValue::from_str("Nonce must be 12 bytes"));
        }
        
        let nonce = ChaChaNonce::from_slice(nonce);
        
        let ciphertext = if aad.is_empty() {
            self.cipher.encrypt(nonce, plaintext)
        } else {
            self.cipher.encrypt(nonce, chacha20poly1305::aead::Payload {
                msg: plaintext,
                aad,
            })
        };
        
        ciphertext.map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn decrypt(&self, ciphertext: &[u8], nonce: &[u8], aad: &[u8]) -> Result<Vec<u8>, JsValue> {
        if nonce.len() != 12 {
            return Err(JsValue::from_str("Nonce must be 12 bytes"));
        }
        
        let nonce = ChaChaNonce::from_slice(nonce);
        
        let plaintext = if aad.is_empty() {
            self.cipher.decrypt(nonce, ciphertext)
        } else {
            self.cipher.decrypt(nonce, chacha20poly1305::aead::Payload {
                msg: ciphertext,
                aad,
            })
        };
        
        plaintext.map_err(|e| JsValue::from_str(&e.to_string()))
    }
}

// 流加密器 (用于大文件)
#[wasm_bindgen]
pub struct StreamCipher {
    cipher: AesGcmCipher,
    chunk_size: usize,
}

#[wasm_bindgen]
impl StreamCipher {
    #[wasm_bindgen(constructor)]
    pub fn new(key: &[u8], chunk_size: usize) -> Result<StreamCipher, JsValue> {
        let cipher = AesGcmCipher::new(key)?;
        Ok(StreamCipher { cipher, chunk_size })
    }
    
    #[wasm_bindgen]
    pub fn encrypt_stream(&self, data: &[u8], base_nonce: &[u8]) -> Result<Vec<u8>, JsValue> {
        if base_nonce.len() != 8 {
            return Err(JsValue::from_str("Base nonce must be 8 bytes"));
        }
        
        let mut result = Vec::new();
        let mut counter = 0u32;
        
        for chunk in data.chunks(self.chunk_size) {
            // 构造唯一的nonce
            let mut nonce = [0u8; 12];
            nonce[..8].copy_from_slice(base_nonce);
            nonce[8..].copy_from_slice(&counter.to_be_bytes());
            
            let encrypted_chunk = self.cipher.encrypt(chunk, &nonce, &[])?;
            result.extend_from_slice(&encrypted_chunk);
            
            counter += 1;
        }
        
        Ok(result)
    }
    
    #[wasm_bindgen]
    pub fn decrypt_stream(&self, data: &[u8], base_nonce: &[u8], original_chunk_size: usize) -> Result<Vec<u8>, JsValue> {
        if base_nonce.len() != 8 {
            return Err(JsValue::from_str("Base nonce must be 8 bytes"));
        }
        
        let mut result = Vec::new();
        let mut counter = 0u32;
        
        // 计算加密后的块大小 (原始大小 + 16字节认证标签)
        let encrypted_chunk_size = original_chunk_size + 16;
        
        for chunk in data.chunks(encrypted_chunk_size) {
            // 构造对应的nonce
            let mut nonce = [0u8; 12];
            nonce[..8].copy_from_slice(base_nonce);
            nonce[8..].copy_from_slice(&counter.to_be_bytes());
            
            let decrypted_chunk = self.cipher.decrypt(chunk, &nonce, &[])?;
            result.extend_from_slice(&decrypted_chunk);
            
            counter += 1;
        }
        
        Ok(result)
    }
}

非对称加密和数字签名

// src/asymmetric.rs - 非对称加密和数字签名
use wasm_bindgen::prelude::*;
use rsa::{RsaPrivateKey, RsaPublicKey, PaddingScheme, PublicKey, Hash};
use ed25519_dalek::{Keypair, PublicKey as Ed25519PublicKey, SecretKey, Signature, Signer, Verifier};
use rand::rngs::OsRng;
use zeroize::{Zeroize, ZeroizeOnDrop};

// RSA 密钥对
#[derive(ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct RsaKeyPair {
    #[zeroize(skip)]
    private_key: RsaPrivateKey,
    #[zeroize(skip)]
    public_key: RsaPublicKey,
}

#[wasm_bindgen]
impl RsaKeyPair {
    #[wasm_bindgen(constructor)]
    pub fn new(bits: usize) -> Result<RsaKeyPair, JsValue> {
        let mut rng = OsRng;
        let private_key = RsaPrivateKey::new(&mut rng, bits)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        let public_key = RsaPublicKey::from(&private_key);
        
        Ok(RsaKeyPair { private_key, public_key })
    }
    
    #[wasm_bindgen]
    pub fn from_private_key_der(der: &[u8]) -> Result<RsaKeyPair, JsValue> {
        let private_key = RsaPrivateKey::from_pkcs8_der(der)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        let public_key = RsaPublicKey::from(&private_key);
        
        Ok(RsaKeyPair { private_key, public_key })
    }
    
    #[wasm_bindgen]
    pub fn get_public_key_der(&self) -> Result<Vec<u8>, JsValue> {
        use rsa::pkcs8::EncodePublicKey;
        self.public_key.to_public_key_der()
            .map(|der| der.as_bytes().to_vec())
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn get_private_key_der(&self) -> Result<Vec<u8>, JsValue> {
        use rsa::pkcs8::EncodePrivateKey;
        self.private_key.to_pkcs8_der()
            .map(|der| der.as_bytes().to_vec())
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, JsValue> {
        let mut rng = OsRng;
        let padding = PaddingScheme::new_oaep::<sha2::Sha256>();
        
        self.public_key.encrypt(&mut rng, padding, plaintext)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, JsValue> {
        let padding = PaddingScheme::new_oaep::<sha2::Sha256>();
        
        self.private_key.decrypt(padding, ciphertext)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, JsValue> {
        let mut rng = OsRng;
        let padding = PaddingScheme::new_pss::<sha2::Sha256, _>(&mut rng);
        
        self.private_key.sign(padding, message)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, JsValue> {
        let mut rng = OsRng;
        let padding = PaddingScheme::new_pss::<sha2::Sha256, _>(&mut rng);
        
        match self.public_key.verify(padding, message, signature) {
            Ok(_) => Ok(true),
            Err(_) => Ok(false),
        }
    }
}

// Ed25519 密钥对
#[derive(ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct Ed25519KeyPair {
    #[zeroize(skip)]
    keypair: Keypair,
}

#[wasm_bindgen]
impl Ed25519KeyPair {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Ed25519KeyPair {
        let mut csprng = OsRng{};
        let keypair = Keypair::generate(&mut csprng);
        
        Ed25519KeyPair { keypair }
    }
    
    #[wasm_bindgen]
    pub fn from_secret_key(secret_key: &[u8]) -> Result<Ed25519KeyPair, JsValue> {
        if secret_key.len() != 32 {
            return Err(JsValue::from_str("Secret key must be 32 bytes"));
        }
        
        let secret = SecretKey::from_bytes(secret_key)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        let public = Ed25519PublicKey::from(&secret);
        let keypair = Keypair { secret, public };
        
        Ok(Ed25519KeyPair { keypair })
    }
    
    #[wasm_bindgen]
    pub fn get_public_key(&self) -> Vec<u8> {
        self.keypair.public.to_bytes().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn get_secret_key(&self) -> Vec<u8> {
        self.keypair.secret.to_bytes().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn sign(&self, message: &[u8]) -> Vec<u8> {
        self.keypair.sign(message).to_bytes().to_vec()
    }
    
    #[wasm_bindgen]
    pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, JsValue> {
        if signature.len() != 64 {
            return Err(JsValue::from_str("Signature must be 64 bytes"));
        }
        
        let sig = Signature::from_bytes(signature)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        
        match self.keypair.public.verify(message, &sig) {
            Ok(_) => Ok(true),
            Err(_) => Ok(false),
        }
    }
}

// 公钥验证器 (只用于验证签名)
#[wasm_bindgen]
pub struct Ed25519Verifier {
    public_key: Ed25519PublicKey,
}

#[wasm_bindgen]
impl Ed25519Verifier {
    #[wasm_bindgen(constructor)]
    pub fn new(public_key: &[u8]) -> Result<Ed25519Verifier, JsValue> {
        if public_key.len() != 32 {
            return Err(JsValue::from_str("Public key must be 32 bytes"));
        }
        
        let public_key = Ed25519PublicKey::from_bytes(public_key)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        
        Ok(Ed25519Verifier { public_key })
    }
    
    #[wasm_bindgen]
    pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, JsValue> {
        if signature.len() != 64 {
            return Err(JsValue::from_str("Signature must be 64 bytes"));
        }
        
        let sig = Signature::from_bytes(signature)
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        
        match self.public_key.verify(message, &sig) {
            Ok(_) => Ok(true),
            Err(_) => Ok(false),
        }
    }
}

安全协议和密钥交换

// src/protocols.rs - 安全协议实现
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
use ring::agreement::{EphemeralPrivateKey, PublicKey, agree_ephemeral, X25519};
use ring::rand::SystemRandom;

// ECDH 密钥交换
#[derive(ZeroizeOnDrop)]
#[wasm_bindgen]
pub struct EcdhKeyExchange {
    #[zeroize(skip)]
    private_key: Option<EphemeralPrivateKey>,
    public_key: Vec<u8>,
}

#[wasm_bindgen]
impl EcdhKeyExchange {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Result<EcdhKeyExchange, JsValue> {
        let rng = SystemRandom::new();
        let private_key = EphemeralPrivateKey::generate(&X25519, &rng)
            .map_err(|e| JsValue::from_str(&format!("Key generation failed: {:?}", e)))?;
        
        let public_key = private_key.compute_public_key()
            .map_err(|e| JsValue::from_str(&format!("Public key computation failed: {:?}", e)))?;
        
        let public_key_bytes = public_key.as_ref().to_vec();
        
        Ok(EcdhKeyExchange {
            private_key: Some(private_key),
            public_key: public_key_bytes,
        })
    }
    
    #[wasm_bindgen]
    pub fn get_public_key(&self) -> Vec<u8> {
        self.public_key.clone()
    }
    
    #[wasm_bindgen]
    pub fn compute_shared_secret(&mut self, peer_public_key: &[u8]) -> Result<Vec<u8>, JsValue> {
        if let Some(private_key) = self.private_key.take() {
            let peer_public_key = PublicKey::from(peer_public_key);
            
            agree_ephemeral(
                private_key,
                &peer_public_key,
                ring::error::Unspecified,
                |shared_secret| {
                    Ok(shared_secret.to_vec())
                }
            ).map_err(|e| JsValue::from_str(&format!("Key agreement failed: {:?}", e)))
        } else {
            Err(JsValue::from_str("Private key already used"))
        }
    }
}

// 安全会话管理
#[derive(Serialize, Deserialize)]
#[wasm_bindgen]
pub struct SecureSession {
    session_id: String,
    encryption_key: Vec<u8>,
    mac_key: Vec<u8>,
    created_at: f64,
    expires_at: f64,
}

#[wasm_bindgen]
impl SecureSession {
    #[wasm_bindgen(constructor)]
    pub fn new(shared_secret: &[u8], session_duration: f64) -> SecureSession {
        use crate::KeyDerivation;
        
        let kdf = KeyDerivation::new();
        let now = js_sys::Date::now();
        
        // 生成会话ID
        let session_id = format!("{:x}", blake3::hash(&[shared_secret, &now.to_be_bytes()].concat()));
        
        // 派生加密密钥和MAC密钥
        let encryption_key = kdf.hkdf_sha256(shared_secret, b"session_encryption", b"", 32);
        let mac_key = kdf.hkdf_sha256(shared_secret, b"session_mac", b"", 32);
        
        SecureSession {
            session_id,
            encryption_key,
            mac_key,
            created_at: now,
            expires_at: now + session_duration * 1000.0,
        }
    }
    
    #[wasm_bindgen]
    pub fn is_valid(&self) -> bool {
        js_sys::Date::now() < self.expires_at
    }
    
    #[wasm_bindgen]
    pub fn get_session_id(&self) -> String {
        self.session_id.clone()
    }
    
    #[wasm_bindgen]
    pub fn encrypt_message(&self, message: &[u8]) -> Result<Vec<u8>, JsValue> {
        if !self.is_valid() {
            return Err(JsValue::from_str("Session expired"));
        }
        
        use crate::AesGcmCipher;
        use crate::SecureRandom;
        
        let cipher = AesGcmCipher::new(&self.encryption_key)?;
        let rng = SecureRandom::new();
        let nonce = rng.generate_bytes(12);
        
        let mut ciphertext = cipher.encrypt(message, &nonce, &[])?;
        
        // 添加nonce到密文前面
        let mut result = nonce;
        result.append(&mut ciphertext);
        
        Ok(result)
    }
    
    #[wasm_bindgen]
    pub fn decrypt_message(&self, encrypted_message: &[u8]) -> Result<Vec<u8>, JsValue> {
        if !self.is_valid() {
            return Err(JsValue::from_str("Session expired"));
        }
        
        if encrypted_message.len() < 12 {
            return Err(JsValue::from_str("Invalid encrypted message"));
        }
        
        use crate::AesGcmCipher;
        
        let cipher = AesGcmCipher::new(&self.encryption_key)?;
        let nonce = &encrypted_message[..12];
        let ciphertext = &encrypted_message[12..];
        
        cipher.decrypt(ciphertext, nonce, &[])
    }
    
    #[wasm_bindgen]
    pub fn to_json(&self) -> Result<String, JsValue> {
        serde_json::to_string(self)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
    
    #[wasm_bindgen]
    pub fn from_json(json: &str) -> Result<SecureSession, JsValue> {
        serde_json::from_str(json)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
}

// 消息认证码
#[wasm_bindgen]
pub struct MessageAuthenticator {
    key: Vec<u8>,
}

#[wasm_bindgen]
impl MessageAuthenticator {
    #[wasm_bindgen(constructor)]
    pub fn new(key: &[u8]) -> MessageAuthenticator {
        MessageAuthenticator {
            key: key.to_vec(),
        }
    }
    
    #[wasm_bindgen]
    pub fn authenticate(&self, message: &[u8]) -> Vec<u8> {
        use crate::HashFunctions;
        let hasher = HashFunctions::new();
        hasher.hmac_sha256(&self.key, message)
    }
    
    #[wasm_bindgen]
    pub fn verify(&self, message: &[u8], mac: &[u8]) -> bool {
        let computed_mac = self.authenticate(message);
        
        // 使用常时间比较防止时序攻击
        use subtle::ConstantTimeEq;
        computed_mac.ct_eq(mac).into()
    }
}

安全防护和反调试

// src/protection.rs - 安全防护模块
use wasm_bindgen::prelude::*;
use web_sys::*;

#[wasm_bindgen]
pub struct SecurityMonitor {
    start_time: f64,
    check_interval: i32,
}

#[wasm_bindgen]
impl SecurityMonitor {
    #[wasm_bindgen(constructor)]
    pub fn new() -> SecurityMonitor {
        SecurityMonitor {
            start_time: js_sys::Date::now(),
            check_interval: 0,
        }
    }
    
    #[wasm_bindgen]
    pub fn start_monitoring(&mut self, callback: &js_sys::Function) {
        let window = web_sys::window().unwrap();
        
        let callback_clone = callback.clone();
        let closure = Closure::wrap(Box::new(move || {
            let mut threats = Vec::new();
            
            // 检查调试器
            if SecurityMonitor::detect_debugger() {
                threats.push("debugger_detected");
            }
            
            // 检查开发者工具
            if SecurityMonitor::detect_devtools() {
                threats.push("devtools_detected");
            }
            
            // 检查时间异常
            if SecurityMonitor::detect_time_manipulation() {
                threats.push("time_manipulation");
            }
            
            // 检查内存篡改
            if SecurityMonitor::detect_memory_tampering() {
                threats.push("memory_tampering");
            }
            
            if !threats.is_empty() {
                let threats_array = js_sys::Array::new();
                for threat in threats {
                    threats_array.push(&JsValue::from_str(threat));
                }
                let _ = callback_clone.call1(&JsValue::NULL, &threats_array);
            }
        }) as Box<dyn FnMut()>);
        
        self.check_interval = window
            .set_interval_with_callback_and_timeout_and_arguments_0(
                closure.as_ref().unchecked_ref(),
                1000,
            )
            .unwrap();
        
        closure.forget();
    }
    
    #[wasm_bindgen]
    pub fn stop_monitoring(&self) {
        if self.check_interval != 0 {
            web_sys::window().unwrap().clear_interval_with_handle(self.check_interval);
        }
    }
    
    fn detect_debugger() -> bool {
        // 检查调试器的多种方法
        let window = web_sys::window().unwrap();
        
        // 方法1: 检查console对象
        let console = window.console();
        if let Ok(console_obj) = js_sys::Reflect::get(&console, &"clear".into()) {
            if console_obj.is_function() {
                // 尝试检测console.clear是否被重写
                let clear_str = console_obj.to_string();
                if clear_str.as_string().unwrap_or_default().contains("native code") {
                    return false;
                }
            }
        }
        
        // 方法2: 检查window.outerHeight和window.innerHeight的差异
        let outer_height = window.outer_height().unwrap_or(0);
        let inner_height = window.inner_height().unwrap_or(0);
        if outer_height - inner_height > 200 {
            return true;
        }
        
        false
    }
    
    fn detect_devtools() -> bool {
        let window = web_sys::window().unwrap();
        
        // 检查窗口大小变化
        let outer_width = window.outer_width().unwrap_or(0);
        let inner_width = window.inner_width().unwrap_or(0);
        let outer_height = window.outer_height().unwrap_or(0);
        let inner_height = window.inner_height().unwrap_or(0);
        
        // 如果内外尺寸差异过大,可能是开发者工具打开
        (outer_width - inner_width > 100) || (outer_height - inner_height > 100)
    }
    
    fn detect_time_manipulation() -> bool {
        let now = js_sys::Date::now();
        let performance_now = web_sys::window().unwrap().performance().unwrap().now();
        
        // 检查时间是否异常
        (now - performance_now).abs() > 1000.0
    }
    
    fn detect_memory_tampering() -> bool {
        // 检查WebAssembly内存是否被篡改
        let memory = wasm_bindgen::memory();
        let buffer = memory.buffer();
        
        // 简单的完整性检查
        buffer.byte_length() > 0
    }
    
    #[wasm_bindgen]
    pub fn obfuscate_string(&self, input: &str) -> String {
        // 简单的字符串混淆
        input.chars()
            .map(|c| {
                let code = c as u32;
                char::from_u32(code ^ 0xAA).unwrap_or(c)
            })
            .collect()
    }
    
    #[wasm_bindgen]
    pub fn deobfuscate_string(&self, input: &str) -> String {
        // 解混淆
        input.chars()
            .map(|c| {
                let code = c as u32;
                char::from_u32(code ^ 0xAA).unwrap_or(c)
            })
            .collect()
    }
    
    #[wasm_bindgen]
    pub fn generate_integrity_hash(&self, data: &[u8]) -> String {
        use crate::HashFunctions;
        let hasher = HashFunctions::new();
        let hash = hasher.blake3(data);
        hex::encode(hash)
    }
    
    #[wasm_bindgen]
    pub fn verify_integrity(&self, data: &[u8], expected_hash: &str) -> bool {
        let computed_hash = self.generate_integrity_hash(data);
        computed_hash == expected_hash
    }
}

// 代码混淆工具
#[wasm_bindgen]
pub struct CodeObfuscator;

#[wasm_bindgen]
impl CodeObfuscator {
    #[wasm_bindgen(constructor)]
    pub fn new() -> CodeObfuscator {
        CodeObfuscator
    }
    
    #[wasm_bindgen]
    pub fn xor_encrypt(&self, data: &[u8], key: u8) -> Vec<u8> {
        data.iter().map(|&b| b ^ key).collect()
    }
    
    #[wasm_bindgen]
    pub fn xor_decrypt(&self, data: &[u8], key: u8) -> Vec<u8> {
        // XOR解密与加密相同
        self.xor_encrypt(data, key)
    }
    
    #[wasm_bindgen]
    pub fn base64_encode(&self, data: &[u8]) -> String {
        use base64::{Engine as _, engine::general_purpose};
        general_purpose::STANDARD.encode(data)
    }
    
    #[wasm_bindgen]
    pub fn base64_decode(&self, data: &str) -> Result<Vec<u8>, JsValue> {
        use base64::{Engine as _, engine::general_purpose};
        general_purpose::STANDARD.decode(data)
            .map_err(|e| JsValue::from_str(&e.to_string()))
    }
}

实际应用示例

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Rust-Wasm Crypto Security Demo</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .demo-section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; }
        .crypto-container { display: flex; gap: 20px; }
        .input-section, .output-section { flex: 1; }
        textarea { width: 100%; height: 100px; margin: 5px 0; }
        button { padding: 10px; margin: 5px; }
        .result { background: #f0f0f0; padding: 10px; margin: 10px 0; }
        .security-status { padding: 10px; margin: 10px 0; border-radius: 5px; }
        .secure { background: #d4edda; color: #155724; }
        .warning { background: #fff3cd; color: #856404; }
        .danger { background: #f8d7da; color: #721c24; }
    </style>
</head>
<body>
    <h1>Rust-Wasm Crypto Security Demo</h1>

    <div class="demo-section">
        <h2>安全状态监控</h2>
        <button onclick="startSecurityMonitoring()">开始监控</button>
        <button onclick="stopSecurityMonitoring()">停止监控</button>
        <div id="security-status" class="security-status secure">系统安全</div>
    </div>

    <div class="demo-section">
        <h2>对称加密演示</h2>
        <div class="crypto-container">
            <div class="input-section">
                <h3>输入</h3>
                <textarea id="symmetric-plaintext" placeholder="输入要加密的文本"></textarea>
                <input type="password" id="symmetric-password" placeholder="密码" style="width: 100%;">
                <button onclick="symmetricEncrypt()">AES-GCM 加密</button>
                <button onclick="symmetricDecrypt()">AES-GCM 解密</button>
            </div>
            <div class="output-section">
                <h3>输出</h3>
                <textarea id="symmetric-output" readonly></textarea>
                <div id="symmetric-result" class="result"></div>
            </div>
        </div>
    </div>

    <div class="demo-section">
        <h2>非对称加密演示</h2>
        <div class="crypto-container">
            <div class="input-section">
                <h3>RSA 操作</h3>
                <button onclick="generateRsaKeyPair()">生成RSA密钥对</button>
                <textarea id="rsa-plaintext" placeholder="输入要加密的文本"></textarea>
                <button onclick="rsaEncrypt()">RSA 加密</button>
                <button onclick="rsaDecrypt()">RSA 解密</button>
                <button onclick="rsaSign()">RSA 签名</button>
                <button onclick="rsaVerify()">RSA 验证</button>
            </div>
            <div class="output-section">
                <h3>输出</h3>
                <textarea id="rsa-output" readonly></textarea>
                <div id="rsa-result" class="result"></div>
            </div>
        </div>
    </div>

    <div class="demo-section">
        <h2>密钥交换演示</h2>
        <div class="crypto-container">
            <div class="input-section">
                <h3>Alice</h3>
                <button onclick="generateAliceKeys()">生成Alice密钥</button>
                <div id="alice-public-key" class="result"></div>
                <button onclick="aliceComputeSecret()">计算共享密钥</button>
            </div>
            <div class="output-section">
                <h3>Bob</h3>
                <button onclick="generateBobKeys()">生成Bob密钥</button>
                <div id="bob-public-key" class="result"></div>
                <button onclick="bobComputeSecret()">计算共享密钥</button>
            </div>
        </div>
        <div id="key-exchange-result" class="result"></div>
    </div>

    <div class="demo-section">
        <h2>安全会话演示</h2>
        <button onclick="createSecureSession()">创建安全会话</button>
        <button onclick="sendSecureMessage()">发送加密消息</button>
        <div id="session-result" class="result"></div>
        <textarea id="session-message" placeholder="输入要发送的消息"></textarea>
        <div id="session-output" class="result"></div>
    </div>

    <script type="module">
        import init, {
            SecureRandom,
            HashFunctions,
            KeyDerivation,
            AesGcmCipher,
            RsaKeyPair,
            Ed25519KeyPair,
            EcdhKeyExchange,
            SecureSession,
            SecurityMonitor,
            CodeObfuscator
        } from './pkg/rust_wasm_crypto.js';

        let secureRandom, hashFunctions, keyDerivation;
        let rsaKeyPair, ed25519KeyPair;
        let aliceKeyExchange, bobKeyExchange;
        let aliceSharedSecret, bobSharedSecret;
        let secureSession;
        let securityMonitor;
        let lastEncryptedData = null;

        async function run() {
            await init();

            // 初始化组件
            secureRandom = new SecureRandom();
            hashFunctions = new HashFunctions();
            keyDerivation = new KeyDerivation();
            securityMonitor = new SecurityMonitor();

            console.log('Crypto security demo loaded!');
        }

        // 安全监控
        window.startSecurityMonitoring = function() {
            securityMonitor.start_monitoring((threats) => {
                const statusDiv = document.getElementById('security-status');

                if (threats.length === 0) {
                    statusDiv.className = 'security-status secure';
                    statusDiv.textContent = '系统安全';
                } else {
                    statusDiv.className = 'security-status danger';
                    statusDiv.textContent = '检测到威胁: ' + Array.from(threats).join(', ');

                    // 可以在这里添加安全响应措施
                    console.warn('Security threats detected:', threats);
                }
            });
        };

        window.stopSecurityMonitoring = function() {
            securityMonitor.stop_monitoring();
            document.getElementById('security-status').className = 'security-status warning';
            document.getElementById('security-status').textContent = '监控已停止';
        };

        // 对称加密
        window.symmetricEncrypt = function() {
            const plaintext = document.getElementById('symmetric-plaintext').value;
            const password = document.getElementById('symmetric-password').value;

            if (!plaintext || !password) {
                alert('请输入文本和密码');
                return;
            }

            try {
                // 使用密码派生密钥
                const salt = secureRandom.generate_bytes(16);
                const key = keyDerivation.pbkdf2_sha256(
                    new TextEncoder().encode(password),
                    salt,
                    100000,
                    32
                );

                // 加密
                const cipher = new AesGcmCipher(key);
                const nonce = secureRandom.generate_bytes(12);
                const plaintextBytes = new TextEncoder().encode(plaintext);
                const ciphertext = cipher.encrypt(plaintextBytes, nonce, []);

                // 组合结果 (salt + nonce + ciphertext)
                const result = new Uint8Array(salt.length + nonce.length + ciphertext.length);
                result.set(salt, 0);
                result.set(nonce, salt.length);
                result.set(ciphertext, salt.length + nonce.length);

                const base64Result = btoa(String.fromCharCode(...result));
                document.getElementById('symmetric-output').value = base64Result;
                document.getElementById('symmetric-result').innerHTML =
                    `<strong>加密成功</strong><br>密文长度: ${result.length} 字节`;

                lastEncryptedData = base64Result;

            } catch (error) {
                document.getElementById('symmetric-result').innerHTML =
                    `<strong>加密失败:</strong> ${error}`;
            }
        };

        window.symmetricDecrypt = function() {
            const ciphertext = document.getElementById('symmetric-output').value || lastEncryptedData;
            const password = document.getElementById('symmetric-password').value;

            if (!ciphertext || !password) {
                alert('请输入密文和密码');
                return;
            }

            try {
                // 解码Base64
                const encryptedData = new Uint8Array(
                    atob(ciphertext).split('').map(c => c.charCodeAt(0))
                );

                // 提取组件
                const salt = encryptedData.slice(0, 16);
                const nonce = encryptedData.slice(16, 28);
                const ciphertextBytes = encryptedData.slice(28);

                // 重新派生密钥
                const key = keyDerivation.pbkdf2_sha256(
                    new TextEncoder().encode(password),
                    salt,
                    100000,
                    32
                );

                // 解密
                const cipher = new AesGcmCipher(key);
                const plaintextBytes = cipher.decrypt(ciphertextBytes, nonce, []);
                const plaintext = new TextDecoder().decode(new Uint8Array(plaintextBytes));

                document.getElementById('symmetric-plaintext').value = plaintext;
                document.getElementById('symmetric-result').innerHTML =
                    `<strong>解密成功</strong><br>明文长度: ${plaintext.length} 字符`;

            } catch (error) {
                document.getElementById('symmetric-result').innerHTML =
                    `<strong>解密失败:</strong> ${error}`;
            }
        };

        // RSA 非对称加密
        window.generateRsaKeyPair = function() {
            try {
                rsaKeyPair = new RsaKeyPair(2048);
                document.getElementById('rsa-result').innerHTML =
                    '<strong>RSA密钥对生成成功</strong><br>密钥长度: 2048位';
            } catch (error) {
                document.getElementById('rsa-result').innerHTML =
                    `<strong>密钥生成失败:</strong> ${error}`;
            }
        };

        window.rsaEncrypt = function() {
            if (!rsaKeyPair) {
                alert('请先生成RSA密钥对');
                return;
            }

            const plaintext = document.getElementById('rsa-plaintext').value;
            if (!plaintext) {
                alert('请输入要加密的文本');
                return;
            }

            try {
                const plaintextBytes = new TextEncoder().encode(plaintext);
                const ciphertext = rsaKeyPair.encrypt(plaintextBytes);
                const base64Result = btoa(String.fromCharCode(...ciphertext));

                document.getElementById('rsa-output').value = base64Result;
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA加密成功</strong><br>密文长度: ${ciphertext.length} 字节`;

            } catch (error) {
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA加密失败:</strong> ${error}`;
            }
        };

        window.rsaDecrypt = function() {
            if (!rsaKeyPair) {
                alert('请先生成RSA密钥对');
                return;
            }

            const ciphertext = document.getElementById('rsa-output').value;
            if (!ciphertext) {
                alert('没有密文可解密');
                return;
            }

            try {
                const ciphertextBytes = new Uint8Array(
                    atob(ciphertext).split('').map(c => c.charCodeAt(0))
                );
                const plaintextBytes = rsaKeyPair.decrypt(ciphertextBytes);
                const plaintext = new TextDecoder().decode(new Uint8Array(plaintextBytes));

                document.getElementById('rsa-plaintext').value = plaintext;
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA解密成功</strong><br>明文: ${plaintext}`;

            } catch (error) {
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA解密失败:</strong> ${error}`;
            }
        };

        window.rsaSign = function() {
            if (!rsaKeyPair) {
                alert('请先生成RSA密钥对');
                return;
            }

            const message = document.getElementById('rsa-plaintext').value;
            if (!message) {
                alert('请输入要签名的消息');
                return;
            }

            try {
                const messageBytes = new TextEncoder().encode(message);
                const signature = rsaKeyPair.sign(messageBytes);
                const base64Signature = btoa(String.fromCharCode(...signature));

                document.getElementById('rsa-output').value = base64Signature;
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA签名成功</strong><br>签名长度: ${signature.length} 字节`;

            } catch (error) {
                document.getElementById('rsa-result').innerHTML =
                    `<strong>RSA签名失败:</strong> ${error}`;
            }
        };

        window.rsaVerify = function() {
            if (!rsaKeyPair) {
                alert('请先生成RSA密钥对');
                return;
            }

            const message = document.getElementById('rsa-plaintext').value;
            const signature = document.getElementById('rsa-output').value;

            if (!message || !signature) {
                alert('请输入消息和签名');
                return;
            }

            try {
                const messageBytes = new TextEncoder().encode(message);
                const signatureBytes = new Uint8Array(
                    atob(signature).split('').map(c => c.charCodeAt(0))
                );

                const isValid = rsaKeyPair.verify(messageBytes, signatureBytes);

                document.getElementById('rsa-result').innerHTML =
                    `<strong>签名验证结果:</strong> ${isValid ? '✓ 有效' : '✗ 无效'}`;

            } catch (error) {
                document.getElementById('rsa-result').innerHTML =
                    `<strong>签名验证失败:</strong> ${error}`;
            }
        };

        // 密钥交换
        window.generateAliceKeys = function() {
            try {
                aliceKeyExchange = new EcdhKeyExchange();
                const publicKey = aliceKeyExchange.get_public_key();
                const base64PublicKey = btoa(String.fromCharCode(...publicKey));

                document.getElementById('alice-public-key').innerHTML =
                    `<strong>Alice公钥:</strong><br>${base64PublicKey.substring(0, 50)}...`;

            } catch (error) {
                document.getElementById('alice-public-key').innerHTML =
                    `<strong>密钥生成失败:</strong> ${error}`;
            }
        };

        window.generateBobKeys = function() {
            try {
                bobKeyExchange = new EcdhKeyExchange();
                const publicKey = bobKeyExchange.get_public_key();
                const base64PublicKey = btoa(String.fromCharCode(...publicKey));

                document.getElementById('bob-public-key').innerHTML =
                    `<strong>Bob公钥:</strong><br>${base64PublicKey.substring(0, 50)}...`;

            } catch (error) {
                document.getElementById('bob-public-key').innerHTML =
                    `<strong>密钥生成失败:</strong> ${error}`;
            }
        };

        window.aliceComputeSecret = function() {
            if (!aliceKeyExchange || !bobKeyExchange) {
                alert('请先生成双方密钥');
                return;
            }

            try {
                const bobPublicKey = bobKeyExchange.get_public_key();
                aliceSharedSecret = aliceKeyExchange.compute_shared_secret(bobPublicKey);

                document.getElementById('key-exchange-result').innerHTML =
                    `<strong>Alice计算共享密钥成功</strong><br>密钥长度: ${aliceSharedSecret.length} 字节`;

            } catch (error) {
                document.getElementById('key-exchange-result').innerHTML =
                    `<strong>Alice密钥计算失败:</strong> ${error}`;
            }
        };

        window.bobComputeSecret = function() {
            if (!aliceKeyExchange || !bobKeyExchange) {
                alert('请先生成双方密钥');
                return;
            }

            try {
                const alicePublicKey = aliceKeyExchange.get_public_key();
                bobSharedSecret = bobKeyExchange.compute_shared_secret(alicePublicKey);

                const secretsMatch = aliceSharedSecret && bobSharedSecret &&
                    aliceSharedSecret.every((val, i) => val === bobSharedSecret[i]);

                document.getElementById('key-exchange-result').innerHTML +=
                    `<br><strong>Bob计算共享密钥成功</strong><br>密钥匹配: ${secretsMatch ? '✓' : '✗'}`;

            } catch (error) {
                document.getElementById('key-exchange-result').innerHTML +=
                    `<br><strong>Bob密钥计算失败:</strong> ${error}`;
            }
        };

        // 安全会话
        window.createSecureSession = function() {
            if (!aliceSharedSecret) {
                alert('请先完成密钥交换');
                return;
            }

            try {
                secureSession = new SecureSession(aliceSharedSecret, 3600); // 1小时

                document.getElementById('session-result').innerHTML =
                    `<strong>安全会话创建成功</strong><br>会话ID: ${secureSession.get_session_id()}<br>有效性: ${secureSession.is_valid() ? '有效' : '无效'}`;

            } catch (error) {
                document.getElementById('session-result').innerHTML =
                    `<strong>会话创建失败:</strong> ${error}`;
            }
        };

        window.sendSecureMessage = function() {
            if (!secureSession) {
                alert('请先创建安全会话');
                return;
            }

            const message = document.getElementById('session-message').value;
            if (!message) {
                alert('请输入要发送的消息');
                return;
            }

            try {
                const messageBytes = new TextEncoder().encode(message);
                const encryptedMessage = secureSession.encrypt_message(messageBytes);
                const base64Encrypted = btoa(String.fromCharCode(...encryptedMessage));

                // 模拟接收和解密
                const decryptedBytes = secureSession.decrypt_message(encryptedMessage);
                const decryptedMessage = new TextDecoder().decode(new Uint8Array(decryptedBytes));

                document.getElementById('session-output').innerHTML =
                    `<strong>消息传输成功</strong><br>` +
                    `加密消息: ${base64Encrypted.substring(0, 50)}...<br>` +
                    `解密消息: ${decryptedMessage}`;

            } catch (error) {
                document.getElementById('session-output').innerHTML =
                    `<strong>消息传输失败:</strong> ${error}`;
            }
        };

        run();
    </script>
</body>
</html>

安全部署建议

生产环境配置

// 生产环境安全配置
#[wasm_bindgen]
pub struct ProductionSecurity {
    integrity_checks: bool,
    obfuscation_enabled: bool,
    debug_protection: bool,
}

#[wasm_bindgen]
impl ProductionSecurity {
    #[wasm_bindgen(constructor)]
    pub fn new() -> ProductionSecurity {
        ProductionSecurity {
            integrity_checks: true,
            obfuscation_enabled: true,
            debug_protection: true,
        }
    }

    #[wasm_bindgen]
    pub fn validate_environment(&self) -> Result<bool, JsValue> {
        // 检查是否在生产环境
        let window = web_sys::window().ok_or("No window object")?;
        let location = window.location();
        let hostname = location.hostname().map_err(|_| "Cannot get hostname")?;

        // 检查域名白名单
        let allowed_domains = ["yourdomain.com", "www.yourdomain.com"];
        if !allowed_domains.iter().any(|&domain| hostname.contains(domain)) {
            return Err(JsValue::from_str("Unauthorized domain"));
        }

        // 检查HTTPS
        let protocol = location.protocol().map_err(|_| "Cannot get protocol")?;
        if protocol != "https:" {
            return Err(JsValue::from_str("HTTPS required"));
        }

        Ok(true)
    }

    #[wasm_bindgen]
    pub fn enable_tamper_detection(&self) -> Result<(), JsValue> {
        // 设置代码完整性检查
        let window = web_sys::window().ok_or("No window object")?;

        // 检查关键函数是否被篡改
        let console = window.console();
        let log_function = js_sys::Reflect::get(&console, &"log".into())?;

        if !log_function.is_function() {
            return Err(JsValue::from_str("Console tampering detected"));
        }

        Ok(())
    }
}

密钥管理最佳实践

// 密钥管理最佳实践
class SecureKeyManager {
    constructor() {
        this.keyStore = new Map();
        this.keyRotationInterval = 24 * 60 * 60 * 1000; // 24小时
    }

    // 安全存储密钥
    storeKey(keyId, keyData, expirationTime) {
        const keyInfo = {
            data: keyData,
            created: Date.now(),
            expires: expirationTime || (Date.now() + this.keyRotationInterval),
            usage: 0
        };

        this.keyStore.set(keyId, keyInfo);

        // 设置自动清理
        setTimeout(() => {
            this.deleteKey(keyId);
        }, keyInfo.expires - Date.now());
    }

    // 获取密钥
    getKey(keyId) {
        const keyInfo = this.keyStore.get(keyId);

        if (!keyInfo) {
            throw new Error('Key not found');
        }

        if (Date.now() > keyInfo.expires) {
            this.deleteKey(keyId);
            throw new Error('Key expired');
        }

        keyInfo.usage++;
        return keyInfo.data;
    }

    // 安全删除密钥
    deleteKey(keyId) {
        const keyInfo = this.keyStore.get(keyId);
        if (keyInfo) {
            // 零化密钥数据
            if (keyInfo.data instanceof Uint8Array) {
                keyInfo.data.fill(0);
            }
            this.keyStore.delete(keyId);
        }
    }

    // 密钥轮换
    rotateKey(keyId, newKeyData) {
        const oldKeyInfo = this.keyStore.get(keyId);
        if (oldKeyInfo) {
            // 保留旧密钥一段时间以支持解密
            const graceKeyId = keyId + '_old_' + Date.now();
            this.storeKey(graceKeyId, oldKeyInfo.data, Date.now() + 60000); // 1分钟宽限期
        }

        this.storeKey(keyId, newKeyData);
    }

    // 获取密钥统计
    getKeyStats() {
        const stats = {
            totalKeys: this.keyStore.size,
            expiredKeys: 0,
            activeKeys: 0
        };

        const now = Date.now();
        for (const [keyId, keyInfo] of this.keyStore) {
            if (now > keyInfo.expires) {
                stats.expiredKeys++;
            } else {
                stats.activeKeys++;
            }
        }

        return stats;
    }
}

总结

Rust-Wasm加解密安全防护方案的核心要点:

🎯 加密技术栈

  1. 对称加密:AES-GCM、ChaCha20-Poly1305高性能加密
  2. 非对称加密:RSA、Ed25519密钥对和数字签名
  3. 密钥派生:PBKDF2、Argon2、HKDF安全密钥生成
  4. 哈希函数:SHA-2、SHA-3、BLAKE3多种哈希算法

✅ 安全协议

  • ECDH密钥交换协议
  • 安全会话管理
  • 消息认证码(MAC)
  • 完整性验证机制

🚀 防护策略

  • 反调试和反篡改检测
  • 代码混淆和字符串保护
  • 内存安全管理
  • 实时安全监控

💡 最佳实践

  • 零化敏感数据
  • 常时间比较防时序攻击
  • 安全随机数生成
  • 多层防护机制

🔒 生产部署

  • 环境验证和域名检查
  • HTTPS强制要求
  • 密钥轮换和管理
  • 完整性监控

构建安全可靠的Web加密系统,保护用户数据安全!


安全是一个持续的过程,需要在设计、实现和部署的各个阶段都保持高度的安全意识和严格的安全标准。