密码学基础:对称/非对称加密
约 1680 字大约 6 分钟
cryptographyencryption
2025-08-08
概述
密码学是信息安全的基石,它提供了数据机密性、完整性、身份认证和不可否认性四大安全目标。本文将系统介绍对称加密、非对称加密、密钥交换和数字签名等核心概念。
密码学体系总览
对称加密
对称加密使用同一个密钥进行加密和解密,其核心优势是速度快,适合大量数据加密。
AES (Advanced Encryption Standard)
AES 是当前最广泛使用的对称加密算法,支持 128、192、256 位密钥长度。
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import os
# AES-256-CBC 加密
def aes_cbc_encrypt(plaintext: bytes, key: bytes) -> tuple[bytes, bytes]:
iv = os.urandom(16) # 初始化向量,每次加密必须不同
# PKCS7 填充(分组密码要求输入长度为块大小的整数倍)
padder = padding.PKCS7(128).padder()
padded_data = padder.update(plaintext) + padder.finalize()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
return iv, ciphertext
def aes_cbc_decrypt(iv: bytes, ciphertext: bytes, key: bytes) -> bytes:
cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
decryptor = cipher.decryptor()
padded_data = decryptor.update(ciphertext) + decryptor.finalize()
unpadder = padding.PKCS7(128).unpadder()
return unpadder.update(padded_data) + unpadder.finalize()
# 使用示例
key = os.urandom(32) # 256-bit key
message = b"Hello, Cryptography!"
iv, encrypted = aes_cbc_encrypt(message, key)
decrypted = aes_cbc_decrypt(iv, encrypted, key)AES-GCM 认证加密
GCM(Galois/Counter Mode)是目前推荐的加密模式,它同时提供加密和认证(AEAD)。
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
def aes_gcm_encrypt(plaintext: bytes, key: bytes, aad: bytes = None) -> tuple[bytes, bytes]:
"""AES-GCM 认证加密,返回 (nonce, 密文+tag)"""
nonce = os.urandom(12) # GCM 推荐 96-bit nonce
aesgcm = AESGCM(key)
# 密文末尾自动附加 16 字节的认证标签
ciphertext = aesgcm.encrypt(nonce, plaintext, aad)
return nonce, ciphertext
def aes_gcm_decrypt(nonce: bytes, ciphertext: bytes, key: bytes, aad: bytes = None) -> bytes:
"""AES-GCM 认证解密,自动验证完整性"""
aesgcm = AESGCM(key)
return aesgcm.decrypt(nonce, ciphertext, aad)
# 附加认证数据(AAD)不会被加密,但会被认证
key = AESGCM.generate_key(bit_length=256)
nonce, ct = aes_gcm_encrypt(b"secret data", key, aad=b"metadata")加密模式对比
| 模式 | 并行加密 | 并行解密 | 认证 | IV/Nonce 复用安全 | 推荐程度 |
|---|---|---|---|---|---|
| ECB | 是 | 是 | 否 | N/A | 禁止使用 |
| CBC | 否 | 是 | 否 | 不安全 | 需配合 HMAC |
| CTR | 是 | 是 | 否 | 灾难性 | 需配合 HMAC |
| GCM | 是 | 是 | 是 | 灾难性 | 强烈推荐 |
ECB 模式将相同的明文块加密为相同的密文块,会泄露数据模式(经典案例:ECB 企鹅图),绝对不应在生产中使用。
非对称加密
非对称加密使用公钥/私钥对,公钥加密的数据只有对应的私钥能解密。
RSA
RSA 基于大整数分解的困难性,密钥长度至少 2048 位(推荐 4096 位)。
from cryptography.hazmat.primitives.asymmetric import rsa, padding as asym_padding
from cryptography.hazmat.primitives import hashes, serialization
# 生成 RSA 密钥对
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
public_key = private_key.public_key()
# RSA-OAEP 加密(推荐的填充方案)
ciphertext = public_key.encrypt(
b"short message", # RSA 只能加密较短的数据
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密
plaintext = private_key.decrypt(
ciphertext,
asym_padding.OAEP(
mgf=asym_padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 导出密钥为 PEM 格式
pem_private = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase")
)ECC 椭圆曲线密码
ECC 在更短的密钥长度下提供与 RSA 同等的安全性,256 位 ECC 约等于 3072 位 RSA。
from cryptography.hazmat.primitives.asymmetric import ec
# P-256 曲线(NIST 标准,也称 secp256r1)
private_key = ec.generate_private_key(ec.SECP256R1())
# Curve25519 (X25519) 用于密钥交换
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
private_key_x = X25519PrivateKey.generate()
public_key_x = private_key_x.public_key()安全强度对比
| 安全级别(bits) | 对称密钥 | RSA 密钥 | ECC 密钥 |
|---|---|---|---|
| 80 | 80 | 1024 | 160 |
| 112 | 112 | 2048 | 224 |
| 128 | 128 | 3072 | 256 |
| 192 | 192 | 7680 | 384 |
| 256 | 256 | 15360 | 512 |
密钥交换
Diffie-Hellman 密钥交换
DH 协议允许双方在不安全信道上协商出共享密钥。
ECDH (Elliptic Curve Diffie-Hellman)
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
# Alice 侧
alice_private = X25519PrivateKey.generate()
alice_public = alice_private.public_key()
# Bob 侧
bob_private = X25519PrivateKey.generate()
bob_public = bob_private.public_key()
# 双方计算共享密钥
alice_shared = alice_private.exchange(bob_public)
bob_shared = bob_private.exchange(alice_public)
# alice_shared == bob_shared
# 使用 HKDF 派生最终密钥
derived_key = HKDF(
algorithm=hashes.SHA256(),
length=32,
salt=None,
info=b"handshake data",
).derive(alice_shared)数字签名
数字签名提供身份认证和不可否认性。私钥签名,公钥验证。
from cryptography.hazmat.primitives.asymmetric import ed25519
# Ed25519 签名(高性能、安全、无需选择参数)
private_key = ed25519.Ed25519PrivateKey.generate()
public_key = private_key.public_key()
message = b"Important document content"
signature = private_key.sign(message)
# 验证签名(失败会抛出 InvalidSignature 异常)
try:
public_key.verify(signature, message)
print("Signature is valid")
except Exception:
print("Signature is invalid")PGP/GPG 实践
PGP(Pretty Good Privacy)结合了对称和非对称加密,广泛用于邮件加密和软件签名。
# 生成 GPG 密钥对
gpg --full-generate-key
# 导出公钥
gpg --armor --export user@example.com > public.asc
# 加密文件(混合加密:RSA + AES)
gpg --encrypt --recipient user@example.com document.pdf
# 签名文件
gpg --sign --armor document.txt
# 验证签名
gpg --verify document.txt.asc最佳实践
- 对称加密优先选择 AES-256-GCM,它同时提供加密和认证
- 永远不要使用 ECB 模式,它会泄露明文的统计特征
- RSA 密钥至少 2048 位,新系统推荐 4096 位或改用 ECC
- 优先使用 Curve25519/Ed25519,它们设计简洁、性能优秀、无后门争议
- Nonce/IV 绝不能重复,GCM 模式下 nonce 复用会导致认证密钥泄露
- 使用 HKDF 派生密钥,不要直接使用 DH 交换的原始共享密钥
- 混合加密是标准实践:非对称加密交换密钥,对称加密处理数据
- 密钥管理比算法选择更重要,使用专业的密钥管理系统
总结
现代密码学体系中,对称加密(AES-GCM)负责高效的数据加密,非对称加密(ECC/RSA)负责密钥交换和数字签名,两者结合构成了 TLS、Signal Protocol 等安全协议的基础。选择经过充分审计的标准算法,避免自行设计密码方案,是安全实践的第一原则。
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于