五种常用 Web 加密算法实战及原理详解
在现代 Web 开发中,数据安全是重中之重。无论是传输中的敏感信息还是存储的密码,选择合适的加密方案都是构建安全应用的基础。下面我们来深入探讨五种最常用的 Web 加密算法,结合原理、场景以及 Node.js 和浏览器环境下的实战代码。
1. AES (高级加密标准)
原理详解
AES 是一种对称加密算法,意味着加密和解密使用同一个密钥。它基于替代 - 置换网络 (SPN) 结构,通过多轮迭代来混淆数据。主要流程包括密钥扩展、初始轮的轮密钥加,以及主轮中的字节替换、行移位、列混淆等操作。最终轮会省略列混淆步骤。AES 支持 128、192 和 256 位密钥长度,分别对应 10、12 和 14 轮加密。

应用场景
- HTTPS 传输中的数据加密
- 数据库敏感字段加密
- 文件加密存储
实战代码(Node.js)
在 Node.js 中,我们直接使用内置的 crypto 模块。这里以 AES-256-CBC 模式为例,注意初始化向量 (IV) 必须随机生成且不可预测。
const crypto = require('crypto');
// AES-256-CBC 加密
function encrypt(text, key, iv) {
const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return encrypted.toString('hex');
}
// AES-256-CBC 解密
function decrypt(encryptedText, key, iv) {
const encryptedBuffer = Buffer.from(encryptedText, 'hex');
const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
let decrypted = decipher.update(encryptedBuffer);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}
// 使用示例
const key = crypto.randomBytes(32); // 256 位密钥
const iv = crypto.randomBytes(16); // 初始向量
const message = 'Secret Message';
const encrypted = encrypt(message, key, iv);
console.log('Encrypted:', encrypted);
const decrypted = decrypt(encrypted, key, iv);
console.log('Decrypted:', decrypted);
2. RSA (非对称加密)
原理详解
RSA 基于大整数因数分解的数学难题。它包含一对密钥:公钥用于加密,私钥用于解密。生成过程涉及选择两个大素数 p 和 q,计算模数 n 和欧拉函数 φ(n),进而导出公钥指数 e 和私钥指数 d。虽然安全性高,但计算开销较大,通常只用于加密小数据量或交换对称密钥。

应用场景
- SSL/TLS 握手过程中的密钥交换
- 数字签名
- 加密对称密钥
实战代码(Node.js)
Node.js 提供了 generateKeyPairSync 方法快速生成密钥对。实际应用中,建议将公钥分发给客户端,私钥严格保密。
const crypto = require('crypto');
// 生成 RSA 密钥对
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
// RSA 加密
function rsaEncrypt(data, publicKey) {
return crypto.publicEncrypt({
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256'
}, Buffer.from(data)).toString('base64');
}
// RSA 解密
function rsaDecrypt(encryptedData, privateKey) {
return crypto.privateDecrypt({
key: privateKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256'
}, Buffer.from(encryptedData, 'base64')).toString();
}
// 使用示例
const message = 'Confidential Data';
const encrypted = rsaEncrypt(message, publicKey);
console.log('RSA Encrypted:', encrypted);
const decrypted = rsaDecrypt(encrypted, privateKey);
console.log('RSA Decrypted:', decrypted);
3. SHA-256 (安全哈希算法)
原理详解
SHA-256 属于 SHA-2 家族,输出固定长度的 256 位哈希值。它不是加密算法,无法解密,主要用于验证数据完整性。其过程包括消息填充、分块处理以及 64 轮压缩函数运算。任何微小的输入变化都会导致哈希值的巨大差异(雪崩效应)。

应用场景
- 密码存储(需配合盐值)
- 数据完整性验证
- 区块链和加密货币
- 数字签名
实战代码(浏览器环境)
现代浏览器支持 Web Crypto API,这是比 crypto-js 等库更底层、更安全的选择。注意这是一个异步操作。
// 浏览器中使用 Web Crypto API 进行 SHA-256 哈希
async function sha256Hash(message) {
// 将字符串编码为 Uint8Array
const encoder = new TextEncoder();
const data = encoder.encode(message);
// 计算哈希
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
// 将 ArrayBuffer 转换为十六进制字符串
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
// 使用示例
sha256Hash('Hello World').then(hash => console.log('SHA-256 Hash:', hash));
4. HMAC (基于哈希的消息认证码)
原理详解
HMAC 结合了哈希函数和共享密钥,既能验证消息来源的真实性,又能确保消息未被篡改。公式上,它是对密钥进行两次哈希填充(ipad 和 opad)后与消息混合。这能有效防止重放攻击和伪造请求。

应用场景
- API 请求认证
- JWT 签名
- 消息完整性验证
实战代码(Node.js)
实现 HMAC 时,务必使用恒定时间比较函数(如 timingSafeEqual)来验证结果,防止时序攻击泄露有效签名。
const crypto = require('crypto');
// 生成 HMAC
function generateHMAC(message, secret) {
return crypto.createHmac('sha256', secret).update(message).digest('hex');
}
// 验证 HMAC
function verifyHMAC(message, secret, hmac) {
const expectedHmac = generateHMAC(message, secret);
return crypto.timingSafeEqual(
Buffer.from(expectedHmac),
Buffer.from(hmac)
);
}
// 使用示例
const secretKey = 'mySecretKey123';
const message = 'Important Data';
const hmac = generateHMAC(message, secretKey);
console.log('HMAC:', hmac);
const isValid = verifyHMAC(message, secretKey, hmac);
console.log('Verification:', isValid ? 'Valid' : 'Invalid');
5. PBKDF2 (基于密码的密钥派生函数)
原理详解
PBKDF2 专门用于将弱密码转化为强密钥。它通过大量迭代哈希运算增加暴力破解的成本。输入包括密码、盐值、迭代次数和期望密钥长度。每次迭代的输出会与上一次结果异或,最终组合成派生密钥。

应用场景
- 用户密码存储
- 从密码生成加密密钥
实战代码(Node.js)
密码存储场景中,盐值必须唯一且随机。验证密码时,重新计算哈希并与存储值比对。
const crypto = require('crypto');
// 使用 PBKDF2 派生密钥
function deriveKey(password, salt, iterations, keyLength, digest) {
return crypto.pbkdf2Sync(
password,
salt,
iterations,
keyLength,
digest
).toString('hex');
}
// 使用示例
const password = 'userPassword123';
const salt = crypto.randomBytes(16).toString('hex'); // 生成随机盐
const iterations = 10000; // 迭代次数
const keyLength = 32; // 密钥长度(字节)
const digest = 'sha256'; // 哈希算法
const derivedKey = deriveKey(password, salt, iterations, keyLength, digest);
console.log('Derived Key:', derivedKey);
console.log('Salt:', salt);
// 验证密码示例
function verifyPassword(password, storedHash, storedSalt, iterations, keyLength, digest) {
const newHash = deriveKey(password, storedSalt, iterations, keyLength, digest);
return newHash === storedHash;
}
const isMatch = verifyPassword('userPassword123', derivedKey, salt, iterations, keyLength, digest);
console.log('Password Match:', isMatch);
加密算法对比表
| 算法 | 类型 | 密钥长度 | 安全性 | 性能 | 适用场景 |
|---|---|---|---|---|---|
| AES | 对称加密 | 128/192/256 位 | 高 | 快 | 大数据量加密 |
| RSA | 非对称加密 | 2048 位 + | 高 | 慢 | 密钥交换、数字签名 |
| SHA-256 | 哈希算法 | 256 位输出 | 高 | 快 | 数据完整性验证 |
| HMAC | 消息认证码 | 可变 | 高 | 中等 | 消息认证 |
| PBKDF2 | 密钥派生 | 可变 | 高 | 可调 | 密码存储 |
安全最佳实践
- 密钥管理:永远不要硬编码密钥,建议使用环境变量或密钥管理系统(如 AWS KMS、Hashicorp Vault),并定期轮换。
- 算法选择:对称加密首选 AES-256,非对称加密使用 RSA 2048 位或 ECC 256 位以上,哈希函数推荐 SHA-256 或 SHA-3。
- 密码存储:严禁明文存储,必须使用 PBKDF2、bcrypt 或 Argon2,且每个用户需使用唯一的盐值。
- 传输安全:始终启用 HTTPS,敏感数据在客户端也应考虑加密。
- 错误处理:加密失败时避免暴露详细信息,使用恒定时间比较防止时序攻击。
进阶主题
除了上述基础算法,还可以关注椭圆曲线加密 (ECC)、更现代的密码哈希算法 (bcrypt/Argon2)、抗量子计算的格密码、同态加密以及零知识证明等技术。掌握这些核心加密算法及其实现,已具备构建安全 Web 应用的基础能力。在实际项目中,应根据具体需求选择合适的算法组合,并严格遵循安全最佳实践来保护用户数据。

