cryptography 基础教程
下面给你一份 超实用 + 清晰分层的《Python cryptography 库 教程》,涵盖常用功能、最佳实践、常见错误处理、生产环境建议。内容基于最新版(cryptography ≥ 42+)风格,保证你马上能用。
适合:后端开发者 / 安全开发 / Token / 加密存储 / HTTPS / JWT / 非对称加密
目录
- 📦 安装
- 🔐 高层(Fernet)对称加密
- 🗝 低层(Hazmat)AES-GCM
- 🔑 非对称 RSA(生成密钥 / 加解密 / 签名)
- 🔑 非对称 ECC(更快、更安全)
- 🧾 哈希(SHA256、HMAC)
- 🎫 JWT 自建签名系统(不依赖第三方库)
- 📁 文件加密
- 🛡 证书、TLS 工具(X509)
- 🧨 错误处理
- 🏭 生产环境最佳实践
pip install cryptography
Fernet 封装了 AES + HMAC,几乎是“拿来就用”的安全方案。
生成密钥
from cryptography.fernet import Fernet
key = Fernet.generate_key()
print(key)
加密 & 解密
from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
token = f.encrypt(b"hello world")
plain = f.decrypt(token)
print(token, plain)
特点
- AES128 + HMAC-SHA256 组合
- 默认提供时间戳
- 易用、安全、适合绝大部分“加密字符串/敏感配置”场景
适合你需要:
- 自己处理 IV / tag
- 加密二进制数据
- 与其他语言互通(AES-GCM 是标准)
AES-GCM 示例
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = AESGCM.generate_key(bit_length=256)
aesgcm = AESGCM(key)
nonce = os.urandom(12) # 推荐 12 字节
data = b"secret message"
aad = b"authenticated data"
ciphertext = aesgcm.encrypt(nonce, data, aad)
plaintext = aesgcm.decrypt(nonce, ciphertext, aad)
print(ciphertext, plaintext)
生成 RSA 密钥
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
print(pem.decode())
RSA 加密 & 解密(OAEP)
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
public_key = private_key.public_key()
ciphertext = public_key.encrypt(
b"hello",
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
)
)
推荐 Curve25519 / Ed25519。
Ed25519 签名
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()
msg = b"hello"
signature = private_key.sign(msg)
public_key.verify(signature, msg)
优点:
- 密钥更短
- 速度比 RSA 快
- 非常适合签名(JWT、API 签名)
SHA256
from cryptography.hazmat.primitives import hashes
digest = hashes.Hash(hashes.SHA256())
digest.update(b"hello")
print(digest.finalize().hex())
HMAC
from cryptography.hazmat.primitives.hmac import HMAC
h = HMAC(b"secret-key", hashes.SHA256())
h.update(b"hello")
tag = h.finalize()
print(tag.hex())
不依赖 PyJWT,用 cryptography 原生实现。
HS256(对称)
import base64
import json
from cryptography.hazmat.primitives import hmac, hashes
def b64(x):
return base64.urlsafe_b64encode(x).rstrip(b'=')
header = b64(json.dumps({"alg": "HS256", "typ": "JWT"}).encode())
payload = b64(json.dumps({"uid": 1}).encode())
msg = header + b"." + payload
h = hmac.HMAC(b"secret", hashes.SHA256())
h.update(msg)
sig = b64(h.finalize())
jwt = msg + b"." + sig
print(jwt.decode())
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = AESGCM.generate_key(256)
aes = AESGCM(key)
with open("input.bin", "rb") as f:
data = f.read()
nonce = os.urandom(12)
ciphertext = aes.encrypt(nonce, data, None)
with open("input.bin.enc", "wb") as f:
f.write(nonce + ciphertext)
生成简易自签证书
import datetime
from cryptography.x509 import NameOID
from cryptography import x509
from cryptography.hazmat.primitives import hashes
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(NameOID.COMMON_NAME, u"test.local"),
])
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.utcnow())
.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365))
.sign(private_key, hashes.SHA256())
)
print(cert.public_bytes(serialization.Encoding.PEM).decode())
| 错误 | 原因 | 解决 |
|---|---|---|
| InvalidTag | AES-GCM 解密失败(密钥/nonce/AAD 错误) | 保证 nonce 不重复 / 验证 AAD |
| UnsupportedAlgorithm | 使用过时算法 | 使用 SHA256+ / AES-GCM |
| ValueError: Encryption/decryption failed | RSA 填充不匹配 | 使用 OAEP,避免 PKCS1v1.5 |
- 对称加密:优先使用 AES-GCM
- 简单字符串加密:Fernet
- 签名:Ed25519
- 公钥加密:RSA-OAEP 或 X25519
密钥存储放在:
- Kubernetes secret
- Vault
- 环境变量 + 文件挂载
❌ 不要:
- 不要重复使用 AES-GCM nonce
- 不要使用 DES / RC4 / ECB
- 不要把私钥提交到 Git