常用加密算法:对称、非对称与哈希
老实说,加密算法这玩意儿,刚入门时很容易被各种术语绕晕。我自己带团队做 API 加密适配那会儿,最头疼的就是新人分不清「加密」和「签名」的区别。这一章我们就一把捋清楚三个核心家族:AES、RSA 和 SHA。嗯,这都是你天天打交道的东西。
对称加密:AES 为什么能扛大旗
对称加密,说白了就是「一把钥匙开一把锁」—— 加密和解密用同一个密钥。快,是真快,但分发密钥要小心。
我项目中用得最多的对称算法就是 AES。它取代了老旧的 DES 和 3DES。AES 支持三种密钥长度:128 位、192 位、256 位。长度越长越安全,但速度会慢一点。实际项目中我建议你用 AES-256-GCM,既有认证又防篡改。
| 特性 | AES-128 | AES-192 | AES-256 |
|---|---|---|---|
| 密钥长度 | 16 字节 | 24 字节 | 32 字节 |
| 安全强度 | 高 | 更高 | 极高 |
| 性能 | 最快 | 中等 | 较慢(但仍很快) |
| 适用场景 | 数据库字段加密 | 一般 API 参数加密 | 高敏感数据(如支付、医疗) |
代码示例 – Python 中使用 AES-256-GCM 加密
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = AESGCM.generate_key(bit_length=256) # 32 字节密钥
aesgcm = AESGCM(key)
nonce = os.urandom(12) # 96 位随机数,每次加密必须不同
plaintext = b"这是一段敏感数据"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
print(f"加密结果(hex): {ciphertext.hex()}")
我的经验: 密钥不要硬编码在代码里。我用过 Vault 和 KMS 来管理密钥,强烈推荐。另外 nonce 绝不能重复用,否则 GCM 模式会裂开。
非对称加密:RSA 的公私钥哲学
非对称加密的核心是「公钥加密,私钥解密」。你想想看,你公开了公钥,别人用公钥加密数据发给你,只有你能用私钥解开。这解决了对称加密的密钥分发难题。
RSA 是最经典的非对称算法。我做过一个跨系统加密方案,系统 A 用系统 B 的公钥加密请求体,系统 B 用私钥解密,全程不需要共享密钥。但 RSA 性能差,不适合加密大数据。一般只用来加密对称密钥(称为「密钥封装」),或用它做数字签名。
RSA 密钥长度对比
| 密钥长度 | 安全等级(对标 AES) | 加密速度 | 建议 |
|---|---|---|---|
| 1024 位 | 约 80 位 | 快 | 已废弃,不要用了 |
| 2048 位 | 约 112 位 | 中等 | 当前最低标准 |
| 4096 位 | 约 128 位 | 较慢 | 推荐用于高安全场景 |
避坑: 我曾经踩过一个坑——RSA 加密的明文长度不能超过密钥长度减去一定开销(OAEP 填充下约 41 字节)。如果你直接拿大数据去 RSA 加密,会报错。解决方案是先 AES 加密数据,再用 RSA 加密 AES 密钥。
代码示例 – RSA 密钥生成与加解密(Python)
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
# 生成 2048 位密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# 加密
plaintext = b"Hello from RSA"
ciphertext = public_key.encrypt(
plaintext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密
decrypted = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(decrypted) # b"Hello from RSA"
哈希算法:SHA 家族与不可逆性
哈希跟加密不一样。它是单向的:你输入任何长度的数据,输出固定长度的摘要。你不能从摘要反推出原文。我们常用它做密码存储、数据完整性校验和数字签名。
SHA(安全哈希算法)目前主流是 SHA-2 家族(SHA-256、SHA-384、SHA-512)。SHA-1 已经被破解,别用了。而 SHA-3 是最新标准,不过还没大规模普及。
我个人习惯,在数据库适配加密场景中,一般用 SHA-256 做数据完整性校验。比如你先算文件的 SHA-256 哈希,接收方再算一次,比对看是否被篡改。我还做过一个系统,用 SHA-256 对 API 请求参数签名,防止中间人篡改。
哈希与加密的区别
| 特性 | 哈希(SHA) | 对称加密(AES) | 非对称加密(RSA) |
|---|---|---|---|
| 方向 | 单向不可逆 | 双向可逆 | 双向可逆 |
| 密钥 | 无密钥 | 一个共享密钥 | 一对公私钥 |
| 输出长度 | 固定(如 256 位) | 与明文长度相关 | 与密钥长度相关 |
| 主要用途 | 完整性校验、密码存储 | 数据加密传输 | 密钥交换、数字签名 |
重点: 存储密码时不要只用 SHA-256。一定要加盐(salt),并使用慢哈希如 bcrypt、scrypt 或 Argon2。只做一次 SHA-256,彩虹表分分钟给你撞出来。
三种算法如何配合?一张图讲清
其实在一个完整的加密 API 中,三种算法常常混着用。比如 HTTPS 的 TLS 握手:用 RSA(或 ECDHE)做密钥交换,用 AES 加密后续数据,用 SHA 做消息认证。下面这张图展示了我设计统一加密 API 时的核心逻辑。
如何统一这三种算法?
在实际的多数据库适配中,我们需要一个统一的 API 来封装不同算法的调用。比如你只有一个 encrypt() 函数,但背后根据配置自动选用 AES 或 RSA。这样做的好处是:业务层不用关心具体算法,切换数据库或安全策略时只改配置。
我建议这样设计接口:
- 加密: 传入明文、算法类型("AES" 或 "RSA")、密钥,返回密文。
- 解密: 对称算法直接解,非对称算法用私钥解。
- 哈希: 纯函数,传入数据返回摘要。同时支持加盐选项。
我个人习惯在哈希函数里内置一个「盐」,比如当前时间戳杂凑后做一段固定前缀。这样即使两个用户密码相同,存到数据库的哈希值也不一样,更安全。
新手常犯的错
我见过不少同事把哈希当加密用,还说「哈希解密太慢」—— 其实你根本解不了。说白了,要搞清楚你是在做保密性(加密)还是完整性(哈希)。还有一个坑:AES 的 ECB 模式不要用。我当初第一次写加密代码就用了 ECB,被安全审计骂惨了。CBC 或 GCM 才是正解。
嗯,这一章就到这里。记住三点:对称加密快,非对称加密安全分发密钥,哈希做完整性。下一回我们聊聊如何把这些算法封装成统一的 API 接口。
最后提醒: 密钥管理比算法本身更复杂。就算你用 AES-256 加密了数据,如果密钥被泄露,等于白加密。建议配合硬件安全模块(HSM)或云 KMS 使用。