加密算法基础
这一章,我们来啃一啃加密算法这块硬骨头。你可能会想:“不就是把数据变乱吗?用个AES不就行了?”——嗯,实际落地时坑不少。我这些年做对象存储加密SDK,见过太多因为选错算法、配错参数导致的性能灾难。所以咱们得把对称加密、非对称加密、密钥协商这三板斧的原理和坑点都捋清楚。
对称加密:AES
AES(Advanced Encryption Standard)是最主流的对称加密算法。说白了,就是加密和解密用同一把钥匙。速度快,适合加密大块数据——比如你的图片、视频文件。
我习惯用pycryptodome库做原型验证。AES核心参数就三个:密钥长度、工作模式、初始向量(IV)。密钥长度选128、192或256位,256更安全但慢一丢丢;模式我首推GCM,因为它自带认证,能防篡改。你还真别说,有一次我在项目中图省事用了ECB模式,结果密文块重复特征明显,被安全审计怼了回来…从那以后我再也不敢偷懒。
下面是一个AES-GCM加密/解密的Python示例:
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
key = get_random_bytes(32) # AES-256
nonce = get_random_bytes(12) # GCM推荐12字节nonce
plaintext = b"Hello, Object Storage!"
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
# 解密
cipher_dec = AES.new(key, AES.MODE_GCM, nonce=nonce)
data = cipher_dec.decrypt_and_verify(ciphertext, tag)
print(data.decode()) # 输出明文
工作中最常对比的模式如下表,方便你选型时参考:
| 模式 | 是否需要IV | 并行解密 | 认证 | 典型场景 |
|---|---|---|---|---|
| ECB | 否 | 是 | 无 | 只适合短固定数据(❌ 不推荐) |
| CBC | 是 | 否 | 无 | 传统文件加密(需配合HMAC) |
| GCM | 是(nonce) | 是 | 有 | 网络传输、对象存储(✅ 推荐) |
| CTR | 是 | 是 | 无 | 流式加密 |
我的习惯:在对象存储场景,直接用AES-256-GCM,128位nonce。省心,还能应对合规审计。
非对称加密:RSA
AES快,但怎么安全地把密钥传给对方?这就是RSA登场的原因。RSA用一对密钥:公钥加密,私钥解密。反过来还能做数字签名。
项目里RSA最常用的地方就是加密AES密钥。比如客户端生成一个AES密钥,用服务端公钥加密后上传,服务端用私钥解密得到AES密钥,后续用AES加密数据。这叫“混合加密”,既安全又高效。
我曾在一次联调中踩过RSA长度的坑:当时用了512位密钥,本地跑飞快,一上线就被安全扫描报弱密钥。后来强制升级到2048位,性能下降不少,但合规是硬指标。我建议你现在就直接用2048或4096位。
RSA加密代码(使用OAEP填充):
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
# 生成密钥对
key = RSA.generate(2048)
public_key = key.publickey()
# 加密AES密钥
aes_key = b"this-is-a-32-byte-key-12345"
cipher_rsa = PKCS1_OAEP.new(public_key)
encrypted_key = cipher_rsa.encrypt(aes_key)
# 解密
cipher_rsa_dec = PKCS1_OAEP.new(key)
decrypted_key = cipher_rsa_dec.decrypt(encrypted_key)
print(decrypted_key == aes_key) # True
对称和非对称的核心区别,我整理成了一张对比表:
| 特性 | AES | RSA |
|---|---|---|
| 密钥 | 单一密钥 | 公钥/私钥对 |
| 速度 | 快(GB/s级别) | 慢(MB/s级别) |
| 适合加密数据量 | 任意大小 | 有限(≈密钥长度) |
| 用途 | 数据加密 | 密钥交换、签名 |
注意:RSA直接加密大数据会失败(2048位RSA最多加密256字节)。所以实际方案永远是“RSA加密AES密钥,AES加密业务数据”。
密钥协商
知道了AES和RSA,你可能有一个问题:如果客户端和服务端事先没有共享密钥,怎么安全地建立对称密钥?密钥协商就是来解决这个问题的。最经典的是Diffie-Hellman(DH)协议,它让双方在不安全的信道上共同算出同一个秘密数,而不泄露秘密本身。
在对象存储加密SDK里,我常常用ECDH(基于椭圆曲线的DH)来协商临时AES密钥。每个会话生成一次密钥对,计算共享密钥后立即销毁私钥——这叫“前向安全性”。就算服务器私钥泄露,历史数据也解不开。
我举个例子(简化版ECDH):
from Crypto.PublicKey import ECC
from Crypto.Protocol import DH
# 客户端生成密钥对
client_key = ECC.generate(curve='P-256')
# 服务端生成密钥对
server_key = ECC.generate(curve='P-256')
# 计算共享密钥(双方得到的值相同)
client_shared = DH.key_agreement(
static_priv=client_key,
static_pub=server_key.public_key()
)
server_shared = DH.key_agreement(
static_priv=server_key,
static_pub=client_key.public_key()
)
print(client_shared == server_shared) # True
注意这个共享密钥不能直接当AES密钥用,通常需要再通过KDF(如HKDF)导出。我曾经在实现时忘了做这一步,直接用原始字节当密钥,结果被安全工具检测出不足熵…嗯,教训深刻。
核心逻辑梳理:
- 对称加密(AES)负责数据加密,速度快。
- 非对称加密(RSA/ECC)负责加密AES密钥或数字签名,安全性高。
- 密钥协商(DH/ECDH)让双方在无预先密钥的情况下安全地得到共享秘密。
把这三种算法的关系画成一个图,会直观很多。下面这张SVG图展示了它们在对象存储加密中的典型协作流程:
你看,整个流程并不复杂。对称加密负责数据搬砖,非对称加密负责保护钥匙,密钥协商负责安全发钥匙——三者缺一不可。搞懂这些基础,后面调SDK参数、做性能优化时,你就能知道该在哪个环节下功夫。