密码学基础回顾:对称加密、非对称加密、哈希函数、数字签名
做安全架构,密码学是绕不开的基石。我见过不少团队在密钥边界划分上出问题,追根溯源,往往是对这四种基本原语理解不够透。今天咱们就把对称加密、非对称加密、哈希函数、数字签名这四兄弟理清楚。
别小看这些基础。我记得有一次评审一个支付系统,他们用同一个对称密钥做全链路加密,连签名都省了。结果泄露一个点,整个系统裸奔。为什么?边界没划清,本质上是没搞清楚每种原语该管什么事。
对称加密:密钥就是命根子
对称加密,说白了就是加密和解密用同一个密钥。你想想看,两个人通信,得先商量好一把“钥匙”。速度快是它最大的优点,AES-256在硬件加速下搞Gbps级吞吐没问题。
但密钥分发是个大坑。我在一个物联网项目里遇到过,设备出厂时预置了对称密钥,结果固件被逆向,所有设备密钥泄漏——厂家连夜召回。为什么?密钥存在设备本地,没有硬件安全隔离。
核心原则:对称加密只解决“机密性”,不解决身份认证和完整性。密钥一旦泄漏,所有密文等于明文。
常用的有 AES(高级加密标准)、SM4(国密)。工作模式也得注意,ECB 模式有模式重复问题,我建议默认用 GCM 或 CTR 模式。
# Python 示例:AES-GCM 加密/解密
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
key = get_random_bytes(32) # 256位密钥
nonce = get_random_bytes(12) # 96位随机数
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
ciphertext, tag = cipher.encrypt_and_digest(b"敏感数据")
# decrypt
cipher2 = AES.new(key, AES.MODE_GCM, nonce=nonce)
plain = cipher2.decrypt_and_verify(ciphertext, tag)
我曾经排查过一个线上故障:系统重启后随机数种子被重置,导致每次生成的 nonce 相同,GCM 模式被攻破。记住,nonce 不允许重复使用。
非对称加密:公私钥的哲学
非对称加密解决了密钥分发难题。公钥随便给人,私钥自己藏着。常见的 RSA、ECC(椭圆曲线)以及国密 SM2。RSA 现在推荐至少 3072 位,ECC 用 256 位就能达到同等强度。
速度慢是它的硬伤。你想想看,用 RSA 加密 1KB 数据就要几毫秒,而 AES 加密 1MB 数据也就几微秒。所以实际项目中,我们通常用非对称加密来保护“会话密钥”——也就是混合加密方案。
我个人习惯:TLS 握手时用 ECDHE 交换临时密钥,再用对称加密传输业务数据。这样既安全又高效。
密钥边界划分时,非对称密钥的私钥必须放在 HSM(硬件安全模块)或 TEE(可信执行环境)里,不能出现在应用日志或数据库里。我曾经审计过一个项目,私钥居然写在配置文件的注释里——真事。
| 对比项 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 一个密钥 | 一对密钥(公/私) |
| 速度 | 快(硬件加速后可到 Gbps) | 慢(RSA 4096 签名约 1ms) |
| 典型算法 | AES, SM4, ChaCha20 | RSA, ECDSA, SM2 |
| 主要用途 | 大量数据加密 | 密钥交换、数字签名 |
哈希函数:数据的指纹
哈希函数把任意长度的数据映射成固定长度的摘要,而且不可逆。你想想看,就算只改了一个 bit,摘要都会面目全非。这就是“雪崩效应”。
常见的哈希算法有 SHA-256、SHA-3,国密用 SM3。MD5 和 SHA-1 已经不安全了,千万别用。我去年还碰到一个老旧系统用 MD5 存密码哈希——直接判了安全漏洞。
注意:哈希不提供机密性,只提供完整性校验。比如下载文件,网站给一个 SHA-256 值,你本地算了比对,就知道文件有没有被篡改。
但哈希有致命弱点:彩虹表攻击和碰撞攻击。所以存储密码时,不能只用哈希,一定要加盐(salt)和拉伸(例如 bcrypt、Argon2)。
# 安全密码哈希(Python 示例)
import hashlib, os
salt = os.urandom(16)
password = b"my_secret_pass"
hash_obj = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
print(hash_obj.hex())
我曾经帮一个客户做过渗透测试,他们用 SHA-256 直接哈希用户密码,连盐都没加。结果数据库泄露后,超过一半的密码被彩虹表秒破。加盐不是选项,是强制要求。
数字签名:防抵赖的终极武器
数字签名 = 哈希 + 非对称加密。签名方先用哈希对消息生成摘要,再用自己的私钥对摘要加密(签名)。验签方用公钥解密摘要,再和自己算的哈希比对。
为什么需要哈希?因为非对称加密太慢,签名大文件不现实。先哈希,再签名,相当于给文件盖一个“电子公章”。
常见的签名算法有 RSA-PSS、ECDSA、Ed25519。Ed25519 效率高且实现安全,我最近几年用的越来越多。
我建议:在安全架构中,签名和加密的密钥一定要分开。用同一把私钥既做签名又做解密,会破坏不可否认性——签名方可以说“这是解密操作,不是我的签名”。
数字签名通常是 CA 体系的核心,证书的本质就是 CA 对你公钥的签名。密钥边界划分时,签名私钥所在的系统必须严格隔离,通常放在离线签名机里,只在可信环境接触网络。
# Ed25519 签名与验证(Python + ed25519)
import ed25519
sk, vk = ed25519.create_keypair()
message = b"重要合约内容"
signature = sk.sign(message)
try:
vk.verify(signature, message)
print("签名验证通过")
except ed25519.BadSignatureError:
print("签名无效")
关键理解:数字签名提供的“不可否认性”依赖于私钥的保密。如果私钥落入他人之手,签名就不再可信。密钥边界划分的核心,就是围绕私钥的生命周期做隔离。
好了,这四种原语我们回顾完了。总结一下:对称加密管机密性,哈希管完整性,非对称加密配合哈希做数字签名管身份认证和不可否认性。实际系统往往是混合使用,比如 TLS 就把它们全用上了。搞清楚了各自边界,密钥管理系统才不会设计成一锅粥。