高级密码学概念:从 CSPRNG 到前向安全性
在普遍存在数据泄露和复杂的国家级监控的时代,密码学的角色已从一门小众的学术学科转变为数字经济的基石。虽然许多开发人员熟悉“哈希”或“对称加密”等基本概念,但系统的实际安全性通常取决于更高级、更细微的原语。
在本指南中,我们将探讨使 TLS 1.3 和 Signal 等现代密码协议成为可能的关键组件:从随机数的生成到即使明天的密钥被泄露也能保证今天的秘密安全的保证。
1. 随机性的基础:CSPRNG
每一次密码操作都始于一个秘密,而每一个秘密都始于随机性。然而,在计算机世界中——计算机本质上是确定性机器——真正的随机性出奇地难以找到。
什么是 CSPRNG?
密码学安全伪随机数生成器 (CSPRNG) 是一种专门设计的算法,用于产生与真实随机噪声无法区分的数字序列。与标准 PRNG(如 JavaScript 中的 Math.random())不同,CSPRNG 必须满足两个关键要求:
- 下一比特测试: 给定序列的前 k 位,具有无限计算能力的攻击者不应能以显著大于 50% 的概率预测第 $(k+1)$ 位。
- 状态泄露扩展: 如果生成器的内部状态被泄露,应该无法重建之前的随机输出(抗回溯性)或预测未来的输出(抗预测性,前提是添加了新的熵)。
熵源
CSPRNG 的质量取决于其熵源。现代操作系统从硬件事件中收集“噪声”——如键盘敲击时机、鼠标移动、磁盘 I/O 中断和热噪声——来为生成器提供种子。在 Linux 中,这由 /dev/urandom 处理。
2. 关联数据的认证加密 (AEAD)
几十年来,开发人员被教导使用加密来保证机密性,并使用 MAC(如 HMAC)来保证完整性。这种“先加密后 MAC”的方法是安全的,但容易出现实现错误。
AEAD 的兴起
AEAD(关联数据的认证加密) 通过在单个密码原语中同时提供机密性和完整性来简化此过程。当您使用 AES-GCM 或 ChaCha20-Poly1305 等 AEAD 模式时,算法会产生:
- 密文: 加密后的数据。
- 认证标签: 一个密码校验和,证明密文未被篡改。
关联数据 (AD)
“AD”部分允许您验证未加密的数据。例如,在网络数据包中,标头(包含目标 IP)必须保持明文以便路由器阅读,但它应该经过认证,以便攻击者无法在不被发现的情况下更改目标地址。
3. 密钥派生函数 (KDF)
您永远不应将原始密码直接用作加密密钥。人类选择的密码具有可预测性,而密码算法需要高熵、均匀分布的比特串。
KDF 的作用是什么?
密钥派生函数 (KDF) 接收熵源(如密码或密钥交换中的共享密钥),并从中“拉伸”或“派生”出一个或多个密码学强密钥。
现代 KDF 标准
- PBKDF2: 一个较旧的标准,使用重复哈希来减慢暴力攻击。
- Argon2: 密码哈希竞赛 (PHC) 的获胜者,旨在抵御基于 GPU 和 ASIC 的破解。
- HKDF(基于 HMAC 的 KDF): 广泛用于 TLS 1.3 等协议中,从单个共享密钥派生多个独立的密钥(例如,一个加密密钥和一个认证密钥)。
4. 临时密钥交换和前向安全性
现代密码学中功能最强大的概念之一是完全前向安全性 (PFS)。
静态密钥的问题
在旧版本的 SSL 中,服务器使用静态 RSA 私钥来交换会话密钥。如果攻击者记录了您多年来的所有加密流量,然后设法窃取了服务器的私钥,他们就可以回头解密他们收集到的所有历史流量。
解决方案:临时密钥交换
现代协议使用临时 Diffie-Hellman (DHE) 或椭圆曲线 Diffie-Hellman (ECDHE)。
- 临时 (Ephemeral) 意味着密钥是暂时的;为每一个会话生成一个新的、唯一的密钥对。
- 会话结束后,密钥将从内存中删除。
实现前向安全性
因为服务器的长期身份密钥仅用于对交换进行签名(证明服务器身份),而不是用于加密会话密钥,所以泄露长期密钥并不能帮助攻击者解密过去的流量。这是隐私保护的黄金标准。
5. 总结:构建安全系统
要构建现代、安全的应用程序,您应遵循以下架构模式:
- 使用系统提供的 CSPRNG 生成秘密(例如,浏览器中的
crypto.getRandomValues()或 Node.js 中的crypto.randomBytes())。 - 使用 Argon2 或 Scrypt 存储密码。
- 使用 AES-256-GCM 等 AEAD 模式保护静态数据。
- 使用带有 ECDHE 的 TLS 1.3 保护传输中的数据以实现前向安全性。
- 使用 HKDF 派生子密钥,而不是将同一个主密钥用于不同的目的。
通过理解这些高级概念,您将超越仅仅“满足安全要求”,开始构建能够抵御当前威胁和未来漏洞的系统。