浏览器端加密实战:Web Crypto API与国密SM2/SM3/SM4的实现路径
前端安全(更新于 2026年5月18日)
为什么要在浏览器端做加密?
传统加密流程需要将数据发送到服务器处理,这带来了隐私风险:
传统:明文 → 网络传输 → 服务器加密 → 密文返回
风险:明文可能被截获,服务器可能记录
浏览器端:明文 → 本地加密 → 密文
优势:明文从未离开用户设备
工具库的加密解密模块(30+ 工具)全部在浏览器本地完成,用户数据零上传。
Web Crypto API:浏览器原生加密
核心能力
Web Crypto API 是 W3C 标准,所有现代浏览器均支持:
// 检测支持
if (window.crypto?.subtle) {
// 支持 Web Crypto API
}
| 算法类别 | 支持的算法 | 密钥长度 |
|---|---|---|
| 对称加密 | AES-GCM, AES-CBC, AES-CTR | 128/192/256 |
| 非对称加密 | RSA-OAEP, RSA-PSS, ECDSA | 2048/4096 |
| 密钥派生 | PBKDF2, HKDF, ECDH | - |
| 哈希 | SHA-1, SHA-256, SHA-384, SHA-512 | - |
| HMAC | HMAC (配合以上哈希) | - |
AES-256-GCM 完整实现
async function aesGcmEncrypt(plaintext: string, password: string) {
const enc = new TextEncoder();
// 1. 从口令派生密钥(PBKDF2)
const salt = crypto.getRandomValues(new Uint8Array(16));
const keyMaterial = await crypto.subtle.importKey(
'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']
);
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt']
);
// 2. 生成随机 IV
const iv = crypto.getRandomValues(new Uint8Array(12));
// 3. 加密
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
enc.encode(plaintext)
);
// 4. 拼接:salt + iv + ciphertext
return concatBuffers(salt, iv, ciphertext);
}
关键安全决策
| 决策 | 选择 | 理由 |
|---|---|---|
| 对称模式 | AES-GCM(非 CBC) | GCM 提供认证加密,防篡改 |
| 密钥派生 | PBKDF2 + SHA-256 | 标准、广泛支持 |
| 迭代次数 | 600,000 | OWASP 2023 推荐最低值 |
| IV 长度 | 12 字节(96 位) | GCM 模式推荐长度 |
| Salt | 16 字节随机 | 防止彩虹表攻击 |
国密算法:JS 实现的挑战
国密算法体系
| 算法 | 类型 | 对标国际 | 工具库实现 |
|---|---|---|---|
| SM2 | 非对称加密/签名 | ECDSA (P-256) | sm-crypto |
| SM3 | 哈希 | SHA-256 | sm-crypto |
| SM4 | 对称加密 | AES-128 | sm-crypto |
sm-crypto 库的使用
import { sm2, sm3, sm4 } from 'sm-crypto';
// SM2 密钥对生成
const keyPair = sm2.generateKeyPairHex();
// publicKey: keyPair.publicKey (130 hex chars, uncompressed)
// privateKey: keyPair.privateKey (64 hex chars)
// SM2 加密(C1C3C4 模式,国密标准)
const cipherMode = 1; // 1 = C1C3C4, 0 = C1C2C3
const ciphertext = sm2.doEncrypt(msg, keyPair.publicKey, cipherMode);
// SM2 解密
const plaintext = sm2.doDecrypt(ciphertext, keyPair.privateKey, cipherMode);
// SM3 哈希
const hash = sm3('message');
// SM4 加密(ECB 模式)
const key = '0123456789abcdeffedcba9876543210'; // 128-bit hex
const encrypted = sm4.encrypt(msg, key);
性能对比
| 操作 | Web Crypto (AES-256-GCM) | sm-crypto (SM4) | 倍率 |
|---|---|---|---|
| 1MB 加密 | 2ms | 45ms | 22x |
| 1MB 解密 | 2ms | 42ms | 21x |
| 密钥生成 | 0.5ms | 3ms | 6x |
Web Crypto API 快 20 倍以上,因为它使用浏览器原生 C/Rust 实现(或硬件加速),而 sm-crypto 是纯 JS 大数运算。
优化策略
- Web Worker 卸载:将 SM2/SM4 计算放入 Worker 线程,避免阻塞 UI
- WASM 加速:将 sm-crypto 的核心运算编译为 Wasm(社区已有实验)
- 数据分片:大文件分块加密,显示进度条
加密工具的架构设计
工具库加密模块的层次结构
用户界面层(React 组件)
↓
加密服务层(统一接口)
↓
┌──────────────┬──────────────┐
│ Web Crypto │ sm-crypto │
│ (标准算法) │ (国密算法) │
│ 浏览器原生 │ 纯 JS 实现 │
└──────────────┴──────────────┘
统一加密接口设计
interface CryptoService {
encrypt(data: Uint8Array, key: CryptoKeyInput): Promise<Uint8Array>;
decrypt(data: Uint8Array, key: CryptoKeyInput): Promise<Uint8Array>;
generateKey(): Promise<CryptoKeyOutput>;
}
标准算法和国密算法都实现同一接口,上层组件不感知底层差异。
文件加密的内存管理
async function encryptFile(file: File, password: string) {
// 1. 读取文件到内存
const buffer = await file.arrayBuffer();
// 2. 大文件分片处理(避免单次加密内存溢出)
const CHUNK_SIZE = 64 * 1024 * 1024; // 64MB
if (buffer.byteLength > CHUNK_SIZE) {
return encryptFileInChunks(buffer, password, CHUNK_SIZE);
}
// 3. 加密
const result = await aesGcmEncrypt(new Uint8Array(buffer), password);
// 4. 清理敏感数据
buffer = null; // 让 GC 回收
return result;
}
常见加密误区
误区 1:Base64 = 加密
Base64("密码123") = "5a+G56CBMTIz" ← 一秒还原
AES-256("密码123") = "U2FsdGVkX1..." ← 没有密钥无法还原
Base64 是编码,不是加密。任何人都能解码。
误区 2:MD5/SHA-1 可以加密
哈希是单向函数,不能"解密"。它们用于验证完整性,不是加密。
- MD5:已被破解,不要用于安全场景
- SHA-1:已被碰撞攻击,不推荐
- SHA-256/SM3:目前安全
误区 3:ECB 模式是安全的
ECB 模式:相同明文块 → 相同密文块(可识别图案)
CBC/GCM 模式:相同明文块 → 不同密文块(安全)
工具库的 AES 工具只提供 GCM 模式,不提供不安全的 ECB。
总结
浏览器端加密已经成为现实:
- Web Crypto API:标准算法(AES/RSA/SHA)接近原生性能
- sm-crypto:国密算法纯 JS 实现,满足合规需求
- 零上传架构:密钥和数据不离开用户设备
工具库提供了 AES加密、RSA加密、SM2加密、SM3哈希、SM4加密 等 30+ 种加密解密工具,全部浏览器本地处理,保护你的数据安全。
本站提供浏览器本地工具,免注册即可试用 →
#加密#WebCrypto#国密#SM2#AES#安全