跳到主要内容

10. 安全考虑

10. 安全考虑 (Security Considerations)​

JWS/JWE/JWK 代理必须处理与任何密码学应用相关的所有安全问题. 这些问题包括保护用户的非对称私钥和对称秘密密钥, 以及针对各种攻击采用对策.

"XML Signature Syntax and Processing Version 2.0" [W3C.NOTE-xmldsig-core2-20130411] 中除 XML 特有内容之外的所有安全考虑, 也适用于本规范. 同样, "XML Signature Best Practices" [W3C.NOTE-xmldsig-bestpractices-20130411] 中记录的许多最佳实践, 除 XML 特有内容之外, 也适用于本规范.

10.1 密钥熵和随机值 (Key Entropy and Random Values)​

密钥的强度只取决于生成密钥时使用的熵量. 所有密钥都应至少使用 128 位熵, 并且根据应用上下文, 可能需要更多熵.

实现必须随机生成公钥/私钥对, MAC 密钥和填充值. 使用不充分的伪随机数生成器 (pseudorandom number generator, PRNG) 生成密码学密钥, 可能导致很少安全性甚至没有安全性. 攻击者可能发现, 重现生成这些密钥的 PRNG 环境并搜索由此产生的小规模可能集合, 比对整个密钥空间进行暴力搜索容易得多. 生成高质量随机数是困难的. RFC 4086 [RFC4086] 在这一领域提供了重要指导.

10.2 密钥保护 (Key Protection)​

实现必须保护签名者的私钥. 如果签名者的私钥被泄露, 攻击者就可以冒充签名者.

实现必须保护 MAC 密钥. 如果 MAC 密钥被泄露, 可能导致经认证内容被修改而无法检测.

10.3 密钥来源认证 (Key Origin Authentication)​

用于获取公钥的密钥管理技术必须认证密钥的来源; 否则, 无法知道是哪一方签署了消息.

同样, 用于分发 MAC 密钥的密钥管理技术必须提供数据来源认证; 否则, 内容虽然带有完整性地交付, 但来源未知.

10.4 密码学敏捷性 (Cryptographic Agility)​

关于密码学敏捷性的安全考虑, 请参见 [JWA] 第 8.1 节.

10.5 数字签名和 MAC 之间的差异 (Differences between Digital Signatures and MACs)​

虽然 MAC 和数字签名都可用于完整性检查, 但它们各自提供的安全属性之间存在一些显著差异. 在设计协议和选择协议中使用的算法时, 需要考虑这些差异.

签名和 MAC 都提供完整性检查, 即验证消息自完整性值计算以来未被修改. 但是, MAC 只在特定情况下提供来源标识. 通常可以假设用于签名的私钥只掌握在单个实体手中 (在复制服务器的场景中, 该实体也可能是分布式实体); 但是, MAC 密钥需要由所有使用它进行完整性计算和检查的实体掌握. MAC 验证只能佐证消息是由知道该对称 MAC 密钥的一方生成的. 这意味着, 只有当某个 MAC 密钥仅由两个实体知道, 且接收者知道该消息不是自己创建的时, 才能确定来源. MAC 验证不能用于向第三方证明来源.

10.6 算法验证 (Algorithm Validation)​

某些算法的数字签名表示形式会在签名值内部包含所用算法的信息. 例如, 使用 RSASSA-PKCS1-v1_5 [RFC3447] 生成的签名会编码所用的哈希函数, 并且许多库在验证签名时实际上会使用签名内部指定的哈希算法. 使用这类库时, 作为所执行算法验证的一部分, 实现 MUST 确保签名中编码的算法信息与 "alg" Header Parameter 指定的信息相对应. 如果不这样做, 攻击者就可能声称使用了强哈希算法, 而实际上使用的是签名值中表示的弱哈希算法.

10.7 算法保护 (Algorithm Protection)​

在 JWS 的某些用法中, 存在算法替换攻击的风险. 在这类攻击中, 攻击者可以将现有数字签名值与不同的签名算法一起使用, 使其看起来像是签名者签署了并未签署的内容. 这些攻击已经在 Cryptographic Message Syntax (CMS) [RFC6211] 的上下文中被详细讨论. 当以下所有条件都成立时, 这种风险就会出现:

  • 签名验证者支持多种算法.
  • 给定一个现有签名, 攻击者可以找到另一个载荷, 使其在不同算法下产生相同的签名值.
  • 攻击者构造的载荷在应用上下文中是有效的.

应用可以通过几种方式缓解算法替换攻击:

  • 仅使用不易受替换攻击影响的数字签名算法. 只有当攻击者能够为接收者接受的哈希函数计算原像时, 替换攻击才可行. 截至本文撰写时, 所有 JWA 定义的签名算法都使用 SHA-2 哈希, 尚不存在已知的原像攻击.
  • 要求在 JWS Protected Header 中携带 "alg" Header Parameter. (使用 JWS Compact Serialization 时总是如此, 这也是 CMS [RFC6211] 采用的方法.)
  • 在应用载荷中包含一个表示算法的字段, 并要求在验证期间将其与 "alg" Header Parameter 匹配. (这是 PKIX [RFC5280] 采用的方法.)

10.8 选择明文攻击 (Chosen Plaintext Attacks)​

JWS 的创建者不应允许第三方在消息中插入任意内容, 除非同时添加不受该第三方控制的熵.

10.9 定时攻击 (Timing Attacks)​

如果密码学算法的实现方式使成功操作和失败操作花费的时间不同, 攻击者可能能够利用这种时间差获取有关所用密钥的信息. 因此, 必须避免这种定时差异.

10.10 重放保护 (Replay Protection)​

虽然这并不直接属于本规范的范围, 但请注意, 使用 JWS (或 JWE) 对象的应用可以通过在 JWS (或 JWE) 消息中将唯一消息标识符作为受完整性保护的内容包含进去, 并让接收者验证该消息以前未被接收或处理过, 从而阻止重放攻击.

10.11 SHA-1 证书指纹 (SHA-1 Certificate Thumbprints)​

出于兼容性原因, 计算 "x5t" (X.509 certificate SHA-1 thumbprint) 值时使用 SHA-1 哈希. 如果将来开发出产生 SHA-1 哈希碰撞的有效方法, 并且攻击者希望干扰某个系统上已知证书的使用, 则可以通过创建另一个 SHA-1 哈希值相同的证书并将其添加到预期受害者使用的证书存储中来实现这一点. 这种攻击成功的前提是攻击者具有对预期受害者证书存储的写访问权限.

或者, 可以使用 "x5t#S256" (X.509 certificate SHA-256 thumbprint) Header Parameter 代替 "x5t". 但是, 截至本文撰写时, 尚无已知开发平台支持 SHA-256 证书指纹.

10.12 JSON 安全考虑 (JSON Security Considerations)​

严格的 JSON [RFC7159] 验证是一项安全要求. 如果收到格式错误的 JSON, 则无法可靠判断生成者的意图. 如果所用 JSON 解析器不拒绝格式错误的 JSON 语法, 可能出现歧义且有潜在可利用性的情况. 特别是, 任何不符合 RFC 7159 中定义的 JSON-text 语法的 JSON 输入, 都 MUST 被 JSON 解析器整体拒绝.

"The JavaScript Object Notation (JSON) Data Interchange Format" [RFC7159] 第 4 节指出, "The names within an object SHOULD be unique", 而本规范指出:

JOSE Header 内的 Header Parameter 名称 MUST 唯一; JWS 解析器 MUST 拒绝具有重复 Header Parameter 名称的 JWS, 或者使用一种 JSON 解析器, 该解析器只返回词法顺序上最后一个重复成员名称, 如 ECMAScript 5.1 [ECMAScript] 第 15.12 节 ("The JSON Object") 所规定.

因此, 本规范要求生成者将 [RFC7159] 第 4 节中的 "SHOULD" 视为 "MUST", 并要求使用者将其视为 "MUST", 或按 ECMAScript 5.1 中规定的方式处理. 如果所用 JSON 解析器不强制成员名称唯一性, 或者对重复成员名称返回不可预测的值, 可能出现歧义且有潜在可利用性的情况.

某些 JSON 解析器可能不会拒绝在有效输入之后包含额外有效字符的输入. 例如, 输入 "{"tag":"value"}ABCD" 包含一个有效的 JSON-text 对象, 后面跟着额外字符 "ABCD". 实现 MUST 将包含此类输入的 JWS 视为无效.

10.13 Unicode 比较安全考虑 (Unicode Comparison Security Considerations)​

Header Parameter 名称和算法名称是 Unicode 字符串. 出于安全原因, 在执行任何转义处理之后 (按照 RFC 7159 [RFC7159] 第 8.3 节), 必须逐字比较这些名称的表示形式. 这意味着, 例如, 这些 JSON 字符串必须比较为相等 ("sig", "\u0073ig"), 而这些字符串必须全部比较为既不等于第一组, 也彼此不相等 ("SIG", "Sig", "si\u0047").

JSON 字符串可以包含 Unicode Basic Multilingual Plane 之外的字符. 例如, G 谱号字符 (U+1D11E) 在 JSON 字符串中可以表示为 "\uD834\uDD1E". 理想情况下, JWS 实现 SHOULD 确保 Basic Multilingual Plane 之外的字符得到保留并正确比较; 或者, 如果由于这些字符触发底层 JSON 实现中存在的限制而无法做到这一点, 则 MUST 拒绝包含这些字符的输入.