Hotdry.

Article

不要自己造轮子:密码学实现中的陷阱与安全默认模式

解析'不要自己实现密码学'这一安全工程原则的多层含义,从使用、选择、实现到设计密码学的风险分级,并提供可落地的安全默认选型清单。

2026-05-23security

"不要自己造密码学轮子"(Don't roll your own crypto)是安全工程领域最常被引用的原则之一。然而,这句简洁的忠告往往被过度简化,导致开发者要么对密码学产生不必要的恐惧,要么在缺乏指导的情况下盲目尝试。事实上,密码学工作存在明显的风险层级差异 —— 使用成熟的库与从零设计新算法之间的风险差距,可能比 Python 与汇编之间的差距还要大。

密码学工作的六层风险模型

密码学相关的工作可以划分为六个层次,每层的风险和所需专业知识呈指数级增长:

Level 0:基础安全—— 在接触密码学之前,确保你的软件没有内存漏洞、注入攻击路径或逻辑缺陷。密码学无法修复糟糕的基础架构。

Level 1:使用密码学—— 调用成熟的加密库 API(如 libsodium 的 crypto_secretbox_easy)。这是绝大多数开发者应该停留的层级。风险点在于 nonce 重用、密钥管理和错误处理。

Level 2:选择密码学—— 在多种算法和模式中做出选择。需要了解哪些算法已被攻破(RC4、MD5、1024-bit RSA)以及哪些是当前推荐(ChaCha20-Poly1305、Argon2、Curve25519)。

Level 3:实现密码学—— 根据 RFC 规范从头实现算法(如用增量 SHA-256 API 实现 HMAC)。风险在于常量时间代码、内存访问模式和测试向量验证。

Level 4:设计新协议—— 组合现有算法构建新的通信协议。历史上多次失败(如 3GMA、Matrix 协议早期漏洞),需要深入理解威胁模型和现有设计模式。

Level 5:设计新原语—— 创造新的哈希函数、分组密码或流密码。这是 "绝对不要独自进行" 的领域,需要密码学博士学位、同行评审和数年的社区验证。

历史失败模式:为什么看起来能跑不等于安全

密码学失败的残酷之处在于:代码可以通过所有单元测试,甚至在生产环境运行多年,仍然可能在攻击者面前不堪一击。

Nonce 重用灾难:当相同的 nonce 被用于两次加密时,ciphertext1 XOR ciphertext2 = plaintext1 XOR plaintext2。攻击者瞬间获得两个明文的异或值,足以破解两者。2010 年代多个 VPN 和消息应用因此沦陷。

时序攻击:AES 的标准优化实现使用查表法,导致缓存访问时间与密钥相关。攻击者通过网络时序分析即可恢复密钥,OpenSSL 曾长期受此困扰。ChaCha20 的设计优势之一就是天然免疫时序攻击。

密文可塑性:没有 MAC 的加密只提供机密性,不提供完整性。攻击者可以翻转密文比特,导致解密后的明文发生特定变化。著名的 "填充预言攻击"(Padding Oracle)让攻击者能在几小时内解密整个会话。

重放攻击:即使消息被完整加密和认证,攻击者仍可拦截并重复发送旧消息。防御需要在协议层面引入消息序号或时间戳。

安全默认选型清单

对于大多数应用场景,以下组合提供了当前最佳的安全边际:

用途 推荐方案 避免使用
对称加密 ChaCha20-Poly1305 (AEAD) AES-CBC, RC4
哈希 Blake2b MD5, SHA-1
密码哈希 Argon2id (内存≥64MB, 迭代≥3) SHA-256(password), MD5
密钥交换 X25519 RSA-1024, DH 小群
数字签名 Ed25519 RSA-PKCS1-v1_5
库选择 libsodium, TweetNaCl 自行封装的 OpenSSL

libsodium 和 TweetNaCl 的核心价值在于 "难以用错":它们不提供危险的底层 API,默认参数已经过优化,常量时间实现内置其中。

何时可以 "造轮子":决策框架

"不要自己造轮子" 不是绝对的禁令,而是风险管理的建议。以下框架帮助判断是否值得承担风险:

绿灯场景

  • 学习目的:实现 RFC 描述的算法以加深理解,代码明确标记为教育用途
  • 协议适配:将现有安全协议移植到新语言 / 平台,保持算法和参数不变
  • 组合现有原语:基于 ChaCha20 和 Poly1305 构建 AEAD,遵循 RFC 7539 的构造方法

黄灯场景(需要专家审查):

  • 修改现有协议:替换密钥派生函数(如 scrypt→Argon2)或调整参数
  • 填补标准空白:现有算法无法满足特定威胁模型(如需要隐藏消息长度)

红灯场景(除非你是密码学家团队):

  • 设计新的分组密码、流密码或哈希函数
  • 发明新的公钥加密体系
  • 为 "性能优化" 而修改标准算法的轮数或结构

团队落地检查清单

如果你决定在某个层级进行密码学工作,以下清单降低风险:

  1. 明确理由:文档化为什么现有方案不可行
  2. 诚实评估:团队成员是否有密码学背景?没有则寻求外部审查
  3. 系统学习:完成 Dan Boneh 的《密码学 I》课程或阅读《 serious cryptography》
  4. 使用测试向量:验证实现与参考实现输出一致
  5. 常量时间审查:使用 valgrind 或专用工具检测分支 / 内存访问是否依赖密钥
  6. 模糊测试:对解析代码进行持续模糊测试
  7. 同行评审:至少两名独立审查者,最好包括密码学专业人士
  8. 文档化假设:明确威胁模型、安全边界和已知限制
  9. 监控与响应:建立漏洞报告渠道和应急响应流程

结语

密码学是安全工程中最容易 "看起来正确" 实则错误的领域。"不要自己造轮子" 的真正含义不是禁止探索,而是强调:密码学需要协作、审查和时间验证。当你面对一个加密需求时,默认选择应该是成熟的库和标准协议;只有当你能清晰论证现有方案为何不足,并准备好投入相应的审查资源时,才考虑自定义实现。

正如密码学家常说的:密码系统的设计者往往是最后一个发现其中漏洞的人。


参考来源

  • Samuel Lucas, "Debunking Don't Roll Your Own Crypto" (2024)
  • Loup Vaillant, "Rolling Your Own Crypto" (2017)
  • Bruce Schneier, "Schneier's Law" (2011)

security

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com