🔒 TLS — 互联网安全的基石
TLS (Transport Layer Security) 保护着互联网上绝大多数通信。TLS 1.3 于 2018 年发布,大幅简化了握手过程并移除了不安全的密码套件。
TLS 1.3 握手流程
Client Server
|--- ClientHello (支持的组+签名+密钥分享) ---->|
|<-- ServerHello (选定的组+签名+密钥分享) -----|
|<-- {EncryptedExtensions} --------------------|
|<-- {Certificate} ---------------------------|
|<-- {CertificateVerify} ---------------------|
|<-- {Finished} ------------------------------|
|--- {Finished} ----------------------------->|
// TLS 1.3 优化点:
// 1. 1-RTT握手(TLS 1.2需要2-RTT)
// 2. 0-RTT恢复(PSK模式)
// 3. 移除RSA密钥交换(仅ECDHE)
// 4. 移除CBC模式密码套件(仅AEAD)
// 5. 握手加密(ServerHello后全部加密)
TLS 配置最佳实践 (2024)
| 项目 | 推荐 | 避免 |
| 协议版本 | TLS 1.3 优先 | TLS 1.0/1.1 |
| 密钥交换 | X25519, P-256 | RSA密钥交换 |
| 认证签名 | Ed25519, ECDSA P-256 | RSA-PKCS#1 v1.5 |
| 对称加密 | AES-256-GCM, ChaCha20-Poly1305 | 3DES, RC4, AES-CBC |
| 证书 | ECDSA/P-256 + Let's Encrypt | RSA-1024, 自签名 |
| HSTS | max-age ≥ 1年 + includeSubDomains | 不设置 |
📚 密码学库选型
| 库 | 语言 | 许可证 | 特色 | 适用场景 |
| OpenSSL | C | Apache-2.0 | 最全面,工业标准 | TLS、证书、通用密码学 |
| BoringSSL | C | ISC+OpenSSL | Google维护,精简安全 | Chrome、Android |
| LibreSSL | C | OpenSSL+ISC | OpenBSD分支,移除旧API | OpenBSD生态 |
| libsodium | C | ISC | NaCl家族,API极简安全 | 现代应用首选 |
| Ring | Rust | ISC+MIT | Rust原生,无unsafe依赖 | Rust项目首选 |
| Tink | Java/C++/Go/ObjC | Apache-2.0 | Google出品,防误用设计 | 多语言项目 |
| age | Go | BSD-3 | 现代文件加密,极简CLI | 文件/密钥加密 |
| NaCl/libsodium | C/多语言绑定 | ISC | 高安全原语集 | 加密通信 |
Python密码学生态
| 库 | 定位 | 推荐度 | 备注 |
| cryptography | 通用密码学 | ⭐⭐⭐ | 基于OpenSSL,API安全 |
| PyNaCl | NaCl绑定 | ⭐⭐⭐ | libsodium的Python绑定 |
| hashlib | 哈希函数 | ⭐⭐⭐ | 标准库,够用 |
| hmac | HMAC | ⭐⭐⭐ | 标准库 |
| PyCryptodome | 通用密码学 | ⭐⭐ | 替代PyCrypto,API略旧 |
| passlib | 密码哈希 | ⭐⭐⭐ | argon2/bcrypt/scrypt |
选型原则:1) 优先使用高层API而非底层原语;2) 使用经过审计的库而非自己实现;3) 默认选择最安全的选项(如Ed25519而非RSA);4) 关注库的维护状态和漏洞历史。**永远不要自己实现密码学算法!**
🔢 哈希函数与MAC
哈希函数选型
| 函数 | 输出长度 | 速度 | 安全级别 | 用途 |
| SHA-256 | 256 bit | 快 | 128-bit安全 | 通用哈希、TLS |
| SHA-3-256 | 256 bit | 中 | 128-bit安全 | 替代SHA-2 |
| BLAKE2b | 可变(≤512) | 极快 | 128-bit安全 | 高性能哈希 |
| BLAKE3 | 可变 | 最快 | 128-bit安全 | 并行哈希、大文件 |
| SHA-512 | 512 bit | 快(64bit) | 256-bit安全 | 高安全需求 |
密码哈希函数(慢哈希)
用于存储用户密码,刻意设计为计算缓慢,增加暴力破解成本:
| 函数 | 内存硬度 | GPU抵抗 | 推荐 |
| Argon2id | 高 | 强 | ⭐ 首选 |
| scrypt | 高 | 强 | 备选 |
| bcrypt | 中 | 中 | 旧系统兼容 |
| PBKDF2 | 低 | 弱 | 避免使用 |
// Argon2id 推荐参数 (OWASP 2024)
// 时间成本 t = 3 (迭代次数)
// 内存成本 m = 64 MB (65536 KiB)
// 并行度 p = 4
// 输出长度 = 32 bytes
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=4)
hash = ph.hash("mypassword") # $argon2id$v=19$m=65536,t=3,p=4$...
ph.verify(hash, "mypassword") # True
🔑 密钥派生函数 (KDF)
KDF将一个秘密输入(如密码、共享密钥)转换为密码学安全的密钥。与密码哈希不同,KDF需要输出指定长度的密钥。
常用KDF
| KDF | 输入 | 特点 | 用途 |
| HKDF | 高熵共享密钥 | 基于HMAC,极快 | TLS密钥派生、协议密钥 |
| PBKDF2 | 低熵密码 | 迭代哈希,可调 | 旧系统兼容 |
| Argon2id | 低熵密码 | 内存硬,GPU抵抗 | 密码存储 |
| XOF (SHAKE/BLAKE3) | 任意输入 | 可变长输出 | 需要自定义长度密钥 |
// HKDF 使用示例
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
hkdf = HKDF(
algorithm=hashes.SHA256(),
length=32, # 输出密钥长度
salt=salt_bytes, # 随机salt(非秘密但应随机)
info=b"encryption", # 上下文信息
)
key = hkdf.derive(shared_secret)
🔮 后量子密码 (PQC)
量子计算机威胁当前的RSA和ECC。NIST后量子密码标准化于2024年完成,三个算法正式发布为FIPS标准:
| 算法 | FIPS | 类型 | 密钥/签名大小 | 状态 |
| ML-KEM (Kyber) | FIPS 203 | 密钥封装 | 公钥1.6KB/密文1.6KB | ✅ 标准化 |
| ML-DSA (Dilithium) | FIPS 204 | 数字签名 | 公钥2.5KB/签名3.3KB | ✅ 标准化 |
| SLH-DSA (SPHINCS+) | FIPS 205 | 数字签名 | 公钥64B/签名29KB | ✅ 标准化 |
| Falcon | 待定 | 数字签名 | 公钥1.3KB/签名666B | 草案中 |
| BIKE | — | 密钥封装 | 较大 | 备选 |
| HQC | — | 密钥封装 | 较大 | 备选 |
迁移策略
- 混合模式:同时使用经典和PQC算法(如 X25519 + ML-KEM-768),任一未被攻破即安全。Chrome、Signal、Apple已部署
- 仅PQC模式:完全使用PQC算法,密钥和签名更大,性能稍差。适用于新系统
- 证书层次:根证书使用SLH-DSA(长期安全),中间证书使用ML-DSA(较小体积)
// 使用 liboqs 进行 PQC 密钥交换
#include
// 生成 ML-KEM-768 密钥对
OQS_KEM *kem = OQS_KEM_new("ML-KEM-768");
uint8_t public_key[OQS_KEM_ml_kem_768_length_public_key];
uint8_t secret_key[OQS_KEM_ml_kem_768_length_secret_key];
OQS_KEM_keypair(kem, public_key, secret_key);
// 封装(对方执行)
uint8_t ciphertext[OQS_KEM_ml_kem_768_length_ciphertext];
uint8_t shared_secret[OQS_KEM_ml_kem_768_length_shared_secret];
OQS_KEM_encaps(kem, ciphertext, shared_secret, public_key);
// 解封
uint8_t shared_secret_d[OQS_KEM_ml_kem_768_length_shared_secret];
OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key);
// shared_secret == shared_secret_d ✅
迁移紧迫性:Google的"Harvest Now, Decrypt Later"威胁是真实的——攻击者现在存储加密流量,等量子计算机成熟后解密。对于需要长期保密(10年+)的数据,现在就应该部署PQC。Chrome 124+已默认启用X25519+ML-KEM-768混合密钥交换。
📋 密码学速查表
🎯 场景 → 算法推荐
常见错误 & 正确做法
| ❌ 错误 | ✅ 正确 | 原因 |
| AES-ECB | AES-GCM / ChaCha20-Poly1305 | ECB模式泄露数据模式 |
| MD5 / SHA-1 | SHA-256 / BLAKE2b | 已被碰撞攻破 |
| RSA-PKCS#1 v1.5 | RSA-OAEP / RSA-PSS | 填充oracle攻击 |
| 自建IV/Nonce | 随机生成,绝不重用 | Nonce重用导致灾难性失败 |
| 硬编码密钥 | KMS/HSM + 密钥轮换 | 密钥泄露风险 |
| 自己实现加密 | 使用成熟库的高层API | 实现缺陷难以发现 |
| RSA-1024 | RSA-3072+ 或 Ed25519 | 1024位已不安全 |
| PBKDF2 + 低迭代 | Argon2id + 足够参数 | GPU暴力破解 |