3. 加密基础知识回顾
说实话,我在做对象存储加密SDK对接时,发现很多问题根源都在基础概念没吃透。尤其是刚接触加密的同学,经常把对称加密和非对称加密混着用,跑出来的密文自己都解不开。这一节我们把这些基础好好捋一捋。
3.1 对称加密 vs 非对称加密:核心区别
这两个概念,说白了就是「一把钥匙」和「两把钥匙」的区别。
对称加密:加密和解密用同一把密钥。你想想看,就像你用一把锁锁上箱子,同一把钥匙又能打开。速度快,适合加密大文件。但问题来了——怎么把密钥安全地交给对方?
非对称加密:有一对密钥——公钥和私钥。公钥公开,私钥自己藏好。别人用你的公钥加密数据,只有你能用私钥解开。速度慢,但解决了密钥分发难题。
我记得刚开始做加密时,总觉得非对称加密更安全,所有场景都想用RSA。结果有一次加密一个几百MB的文件,跑了好几分钟都没出来……后来才意识到,实际项目中多用「混合加密」:用RSA加密AES的密钥,用AES加密真正的数据。
| 特性 | 对称加密 | 非对称加密 |
|---|---|---|
| 密钥数量 | 1 个(共享密钥) | 2 个(公钥 + 私钥) |
| 速度 | 快(硬件加速支持好) | 慢(数学运算复杂) |
| 典型算法 | AES, ChaCha20 | RSA, ECC |
| 适用场景 | 大量数据加密 | 密钥交换、数字签名 |
| 密钥分发 | 困难(需要安全通道) | 简单(公钥可公开) |
3.2 AES:对称加密的工业标准
AES(Advanced Encryption Standard)是目前最主流的对称加密算法,支持128、192、256位密钥。我建议你在对象存储加密场景中优先使用 AES-256-GCM 模式,它同时提供加密和完整性校验。
下面是一个使用 Python cryptography 库进行 AES-GCM 加密解密的例子:
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
# 生成 256 位密钥
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)
# 生成随机 nonce(12 字节)
nonce = os.urandom(12)
# 加密
plaintext = b"Hello, Object Storage!"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
# 解密
decrypted = aesgcm.decrypt(nonce, ciphertext, None)
print(decrypted.decode()) # 输出: Hello, Object Storage!
3.3 RSA:最经典的非对称加密
RSA 的名字来自三位发明者的姓氏首字母。它的安全性基于大整数分解的数学难题——用两张大素数生成密钥很容易,但从公钥反推私钥几乎不可能。
我刚开始做加密时,总觉得密钥越长越安全,一上来就生成 4096 位的 RSA 密钥。结果生成一次等了好几分钟,加密小数据也慢得离谱。后来才学会根据场景选择:2048 位对大多数场景已经足够安全,而且性能尚可。
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# 生成 2048 位密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# 公钥加密(只能加密少量数据)
message = b"AES Key: 1234567890abcdef"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 私钥解密
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(plaintext.decode())
3.4 哈希函数:数据的「指纹」
哈希函数能把任意长度的数据,计算成一个固定长度的摘要。关键特性是:不可逆——从摘要无法还原原文。而且输入稍微改一点,摘要就完全不一样。
你想想看,这就像给数据打了一个「指纹」。在对象存储里,我常用它来验证文件有没有被篡改——上传时计算哈希,下载后再算一次,对比就知道文件是否完整。
常见的哈希算法有 MD5(已不推荐)、SHA-1(已不推荐)、SHA-256、SHA-3 等。目前在对象存储场景中,SHA-256 是最主流的选择。
import hashlib
# 计算文件的 SHA-256 哈希
def sha256_file(filepath):
sha256 = hashlib.sha256()
with open(filepath, 'rb') as f:
# 分块读取,避免大文件占用太多内存
for chunk in iter(lambda: f.read(8192), b''):
sha256.update(chunk)
return sha256.hexdigest()
# 示例
digest = sha256_file('example.dat')
print(f'SHA-256: {digest}')
3.5 消息认证码:带密钥的哈希
哈希函数只能保证「数据没被改过」,但无法判断「数据是谁发的」——因为哈希算法是公开的,谁都能算。消息认证码(MAC)就是为了解决这个问题:在哈希计算中加入共享密钥,只有知道密钥的人才能生成和验证这个码。
最常见的实现是 HMAC(Hash-based Message Authentication Code),它把密钥和消息按特定方式混合后再做哈希。
import hmac
import hashlib
# 共享密钥(必须双方提前约定)
key = b'secret-object-storage-key'
message = b'important-file-content'
# 计算 HMAC-SHA256
hmac_obj = hmac.new(key, message, hashlib.sha256)
digest = hmac_obj.hexdigest()
print(f'HMAC-SHA256: {digest}')
# 验证方用相同的密钥和消息重新计算,对比结果
def verify_hmac(key, message, expected_hmac):
computed = hmac.new(key, message, hashlib.sha256).hexdigest()
# 使用 hmac.compare_digest 防止时序攻击
return hmac.compare_digest(computed, expected_hmac)
is_valid = verify_hmac(key, message, digest)
print(f'验证通过: {is_valid}')
hmac.compare_digest(),不要直接用 == 比较字符串。为什么?因为直接比较会在遇到第一个不同字符时就返回 False,攻击者可以根据响应时间推断出正确的 HMAC 值——这就是「时序攻击」。我踩过这个坑,后来被安全团队要求整改,印象深刻。
3.6 知识体系总览
上面讲的四个概念,构成了对象存储加密的核心基础。它们之间不是孤立的:对称加密和非对称加密经常配合使用(混合加密),消息认证码(HMAC)也建立在哈希函数之上。下面这张图帮你把关系理清楚。
这张图把四个核心概念和它们之间的关系串在了一起。你可以看到:对称加密和非对称加密通过「混合加密」配合使用,哈希函数和消息认证码通过「HMAC」连在一起。在后续的章节中,我们会多次用到这些基础——尤其是 AES-GCM 和 HMAC-SHA256,它们是对象存储加密中最常用的两个工具。