第二讲 密码学基础回顾:对称加密,非对称加密,哈希函数

密码学听起来离我们很远,但核心就那么几块。说白了,密钥边界设计就是研究“钥匙该放哪、怎么用、谁来管”,绕不开这些老伙计。

我这些年做密钥管理,踩过最大的坑就是:把密码学工具当成黑盒,读完文档就往上堆。结果呢?线上爆过内存泄露,也出过密钥混淆。嗯,今天咱们先打好底。

密码学三大基础分类 对称加密 加解密用同一把密钥 代表算法:AES, SM4 密钥管理是核心痛点 非对称加密 公钥加密,私钥解密 代表算法:RSA, ECDSA 私钥必须保密 哈希函数 单向不可逆,定长输出 代表算法:SHA-256,SHA-3 用于完整性校验、签名 速度快,量大时首选 密钥分发方便 不可逆,防篡改

2.1 对称加密:一把钥匙开一把锁

对称加密,加解密用的是同一把密钥。就好比你用同一把钥匙锁门和开门。速度极快,适合加密大量数据。

核心特征: 加密=解密密钥相同。安全性完全依赖密钥的保密性。

常见的对称算法大致分两类:

  • 分组密码:AES、SM4、DES。把明文切成固定大小的块,一块一块加密。AES 的密钥长度可选 128/192/256,现在行业最低标准是 AES-128。
  • 流密码:ChaCha20、RC4。逐字节或逐位加密,适合数据流场景。我曾在物联网项目中用过 ChaCha20,资源消耗比 AES 小很多。

用 Python 写个 AES-CBC 的例子,感受一下:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import os

key = os.urandom(32)  # 256 位密钥
iv = os.urandom(16)   # 初始向量

cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = b"密钥边界设计实战"
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

# 解密
cipher2 = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher2.decrypt(ciphertext), AES.block_size)
print(decrypted.decode())  # 密钥边界设计实战
注意: IV 不要重复使用!CBC 模式下 IV 需要随机生成,且每次加密用新 IV,否则会被攻击者用来恢复明文。我在项目中见过同事把 IV 写死在代码里,差点出事。

2.2 非对称加密:公钥私钥两把锁

非对称加密,一对密钥:公钥公开,私钥保密。公钥加密的,只有对应的私钥能解;反过来,私钥签名,公钥验证。

你想想看,如果两个人初次通信,怎么安全地交换对称密钥?用非对称加密来传输密钥就解决了。这就是密钥分发的经典场景。

特性 对称加密 非对称加密
速度 快(硬件加速可达数 Gbps) 慢(适合小数据)
密钥数量 每对通信双方需要单独密钥(N 方需 N(N-1)/2) 每人一对密钥即可
典型用法 加密大块数据 密钥交换、数字签名
安全性依赖 密钥保密 私钥保密 + 数学难题

RSA 的密钥生成过程我简单写一下,让你有手感:

from Crypto.PublicKey import RSA

# 生成 2048 位 RSA 密钥对
key = RSA.generate(2048)

private_key = key.export_key()
public_key = key.publickey().export_key()

print(private_key.decode()[:100] + "...")  # 打印前 100 字符示意
经验: 我个人习惯在非对称加密中优先使用 ECC(椭圆曲线),比如 ECDSA 或 Ed25519。同样的安全强度下,ECC 的密钥比 RSA 短很多,性能更好。但生态兼容性需要注意,有些老旧系统只认 RSA。

这里有个避坑点。我曾经在金融项目里用 RSA-OAEP 加密,结果忘了检查密钥对的匹配性。上线后有一部分数据用错了公钥,恢复不了。后来我强制在存储前做一次加解密自检。

2.3 哈希函数:不可逆的数字指纹

哈希函数不是加密算法,它没有密钥。输入任意长度,输出固定长度(比如 SHA-256 输出 256 位)。关键性质:

  1. 单向性:从哈希值几乎不可逆推原消息。
  2. 抗碰撞性:极难找到两个不同输入产生相同哈希值。
  3. 雪崩效应:输入改一个比特,输出翻转一半以上。

哈希在密钥边界设计里经常用在几个地方:

  • 完整性校验:验证数据在传输或存储中是否被篡改。
  • 口令存储:服务端不存明文密码,存哈希值。注意要用加盐(salt)的慢哈希(如 bcrypt、Argon2)。
  • 密钥派生:通过 PBKDF2、HKDF 从密码学上安全的种子派生出多个子密钥。

看个简单的 SHA-256 例子:

import hashlib

data = "密钥边界设计"
hash_obj = hashlib.sha256(data.encode())
print(hash_obj.hexdigest())
# 输出类似 d2e8...(64 位十六进制)
安全警告: 不要直接用 MD5 或 SHA-1!它们已经不再安全,可在毫秒级内被碰撞攻击。即使只用做校验,也建议用 SHA-256 或更高。

我参与过一个审计系统,用了 SHA-1 做日志完整性校验。后来安全团队扫描发现风险,我们全部替换为 SHA-256。那段时间加班调接口,真是教训。

2.4 混合加密:三者协作

实际项目里不会只用一种,而是混合使用。典型流程:

  1. 发送方用 非对称加密 传递一次性的会话密钥。
  2. 双方用这个会话密钥做 对称加密 加密业务数据。
  3. 同时用 哈希函数 计算数据摘要,实现完整性校验。

HTTPS 的 TLS 握手就是这么干的。你想想看,没有哈希保证完整性,攻击者可以篡改密文然后在应用层搞破坏。

一句话记住: 对称加密负责快,非对称加密负责安全分发,哈希负责验真。密钥边界设计就是管好这三把钥匙。