密码学应用基础 · kp-010
密码学误用:随机数、模式错配与密钥管理
一句话定义
现实中的密码学失效绝大多数不是算法被攻破,而是误用:弱随机数、错误模式(ECB、nonce 重用)、硬编码密钥、缺少认证的加密——本课把这些高频误用模式整理成一张防御自查清单。
为什么重要
从 kp-006 到 kp-009 可以看到,安全由"算法 + 用法 + 密钥管理"三者共同决定,而工程事故几乎全部集中在后两者。把误用模式当作 checklist 在代码评审与设计评审中使用,是性价比最高的防御动作之一;它也是"我们用了 AES 所以很安全"这类虚假安全感的解药。
前置知识
kp-006(对称加密与模式):理解 ECB 与 GCM nonce 的约束。 kp-008(哈希与 HMAC):理解无认证加密与口令哈希的正确姿势。
核心概念
- 弱随机数:普通 PRNG(如各语言默认 Math.random)是可预测的;安全用途(密钥、nonce、盐、会话 ID、令牌)必须用密码学安全随机数(CSPRNG):getrandom/os.urandom/SecRandom/Web Crypto 的 getRandomValues。
- nonce 纪律:GCM/CTR 等计数器模式下,同一密钥的 nonce 重用是灾难级失效;随机 96 位 nonce 在大流量下有碰撞风险,应改用确定性计数器或换 ChaCha20-Poly1305 并谨慎设计。
- ECB 复活:即便不用 ECB 一词,"按记录逐条独立加密"的写法在结构上就是 ECB。
- 硬编码与密钥管理:密钥写进源码或配置提交进仓库,等于随代码分发;应使用密钥管理服务(KMS)或至少独立的密钥存储与轮换流程。
- 无认证加密:只加密不认证,攻击者可翻转密文位造成可预测的明文变化(可延展性);必须 AEAD 或 Encrypt-then-MAC。
- 算法协商降级:协议若允许协商弱算法且未防护降级,攻击者可把双方压到最弱公共选项(TLS 对降级有专门防护)。
公式、模型或图示
误用 → 后果 速查表
Math.random() 生成密钥/令牌 ──▶ 可预测 → 冒用
GCM nonce 重用 ──▶ 密钥流重用 + 认证崩塌
ECB / 逐条独立加密 ──▶ 图案泄露
只加密无 MAC ──▶ 可延展篡改
密钥硬编码进仓库 ──▶ 泄露面 = 仓库可见者
sha256(password) 存口令 ──▶ 秒级离线爆破原理与机制
这些误用有一个共同根因:把密码学当作"一个函数调用"而非"一个系统"。安全的成立依赖分布在这些函数之外的前提——随机源质量、参数唯一性、密钥生命周期、认证顺序。防御策略因此分三层:第一层是选对库(libsodium/Tink/平台 AEAD 接口),让库的默认值替你避开历史坑(这类库刻意不提供 ECB、强制 nonce 参数化);第二层是评审清单化,把上表变成 PR 检查项;第三层是监控与演练(密钥轮换演练、证书到期告警),保证管理前提在运行期仍然成立。JWT 的 alg: none 历史事故是三层缺一不可的实证:库允许了、代码信了头部声明、评审没拦住。
实例或案例
某服务用 Math.random() 生成重置口令令牌(6 位数字范围被猜中概率极高),攻击者批量枚举接管账号——修复为 CSPRNG 生成的 128 位令牌并限时限次。这个模式在真实世界反复出现,因为它"看起来也能用"。
直观类比
误用像把防盗门装在纸糊的墙上:门(AES)本身没问题,问题是它依赖的前提(墙)不成立。安全工程的大半工作是检查"门装在哪里",而不是反复研究门的锁芯。
常见误区
- "我们加密了所以安全":无认证的加密可被篡改;保密性不等于完整性(回看 kp-001)。
- "随机数差不多随机就行":可预测性是二元的,种子一旦可猜,整个体系塌陷。
- "换个库就行,参数随便配":库只保证正确实现你指定的用法,错误用法照样致命。
与其他知识点的关系
- kp-016(OWASP Top 10 与安全响应头):A02 密码学失败在 Web 场景的具体形态。
- kp-024(供应链与依赖治理):密钥与签名材料的管理同属供应链完整性。
自测题
- 为什么生成会话 ID 不能用语言默认随机函数?要点:默认 PRNG 可预测,会话 ID 一旦被猜出即身份冒用;必须 CSPRNG 且熵足够(≥128 位)。
- "只加密不认证"的攻击面是什么?要点:可延展性——密文位翻转导致明文可预测变化,可在不知密钥时篡改语义;应使用 AEAD。
- 密钥管理的最低要求有哪些?要点:不进代码仓库、独立存储与访问控制、可轮换、有泄露应急与到期告警。
延伸阅读
《Cryptography Engineering》(Ferguson/Schneier/Kohno):以"如何不误用"为主线的设计指南。