
对称加密与非对称加密
对称加密使用相同的密钥对数据进行加密和解密。它速度快、效率高,非常适合加密大量数据。其挑战在于密钥分发——双方在通信前需要安全地共享密钥。
非对称加密(如 RSA)使用公钥/私钥对。它解决了密钥分发问题,但速度慢得多。实践中,大多数系统两者兼用:非对称加密用于安全交换对称密钥,然后对称加密用于实际数据传输。HTTPS 正是这样工作的。

AES 算法
AES(高级加密标准)是世界上最广泛使用的对称密码,由 NIST 于 2001 年标准化。它取代了 DES 和 3DES,并用于几乎所有现代安全协议——TLS、磁盘加密、VPN 等。
AES 对 128 位数据块(每次 16 字节)进行操作,使用 128、192 或 256 位的密钥。它应用多轮替换、置换和混合变换。
AES 密钥长度
| 变体 | 密钥长度 | 轮数 | 安全性 |
|---|---|---|---|
| AES-128 | 128 位(16 字节) | 10 | ✅ 安全 |
| AES-192 | 192 位(24 字节) | 12 | ✅ 安全 |
| AES-256 | 256 位(32 字节) | 14 | ✅ 推荐 |
AES-128 和 AES-256 在安全性上没有实际差异——两者在当前和可预见的未来技术下都能抵御暴力破解攻击。AES-256 提供了针对量子计算机(理论上通过 Grover 算法将有效密钥长度减半)的安全余量。
分组密码模式
像 AES 这样的分组密码一次只能加密恰好一个 128 位数据块。操作模式定义了如何将分组密码应用于任意长度的数据。

ECB(电子密码本)——切勿使用
每个数据块独立加密。相同的明文块产生相同的密文块。这会暴露结构化数据中的模式(经典例子是加密图像——形状仍然可见)。
CBC(密码分组链接)
每个数据块在加密前与前一个密文块进行 XOR 运算。第一个块需要随机的初始化向量(IV)。IV 每次加密必须唯一,但无需保密。
C₀ = IV
Cᵢ = Encrypt(K, Pᵢ ⊕ Cᵢ₋₁)
适合文件加密。需要填充以处理非块大小的数据。
GCM(伽罗瓦/计数器模式)——推荐
将计数器模式(流密码)与伽罗瓦消息认证码(GMAC)结合。提供认证加密:输出包含一个认证标签,可检测任何篡改。
AES-256-GCM 是对称加密的黄金标准——TLS 1.3 在 HTTPS 中使用它。

CTR(计数器模式)
加密连续的计数器值并与明文进行 XOR 运算。可并行化,无需填充。无认证。
算法比较
| 算法 | 状态 | 密钥长度 | 安全性 |
|---|---|---|---|
| DES | 🔴 已破解 | 56 位 | 1999 年被破解 |
| 3DES | 🟡 已弃用 | 112/168 位 | 慢,正在退役 |
| AES-128 | ✅ 安全 | 128 位 | 标准 |
| AES-256 | ✅ 推荐 | 256 位 | 抗量子余量 |
| ChaCha20 | ✅ 现代 | 256 位 | 移动/嵌入式设备上快 |
3DES(三重 DES)用于遗留系统——新开发应避免使用。AES 已完全取代它。
从密码派生密钥
当使用密码而非随机密钥进行加密时,必须使用**密钥派生函数(KDF)**将密码转换为合适的加密密钥。切勿直接将密码用作 AES 密钥。
// 使用 PBKDF2 从密码派生密钥
const key = await crypto.subtle.importKey(...);
const derivedKey = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },
key, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']
);
常见 KDF:PBKDF2、scrypt、Argon2。使用高迭代次数(PBKDF2 至少 100,000 次)以减缓暴力破解攻击。
实际加密示例
// Web Crypto API(浏览器)
async function encryptText(plaintext, password) {
const encoder = new TextEncoder();
const data = encoder.encode(plaintext);
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const keyMaterial = await crypto.subtle.importKey(
'raw', encoder.encode(password), 'PBKDF2', false, ['deriveKey']
);
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },
keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['encrypt']
);
const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data);
return { encrypted, salt, iv };
}
→ 尝试 加密工具