Skip to main content

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 (密钥熵和随机值)

密钥的强度仅取决于用于生成它们的熵量. 所有密钥应该 (SHOULD) 使用至少 128 位熵, 并且根据应用程序上下文, 可能需要更多.

实现必须随机生成公钥/私钥对、MAC 密钥和填充值. 使用不充分的伪随机数生成器 (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 Differences between Digital Signatures and MACs (数字签名和 MAC 之间的差异)

虽然 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 哈希, 在撰写本文时, 对于这些哈希没有已知的原像攻击.
  • 要求 "alg" Header Parameter 包含在 JWS Protected Header 中. (使用 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 Certificate Thumbprints (SHA-1 证书指纹)

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

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

10.12 JSON Security Considerations (JSON 安全注意事项)

严格的 JSON [RFC7159] 验证是一项安全要求. 如果收到格式错误的 JSON, 则无法可靠地辨别生产者的意图. 如果使用的 JSON 解析器不拒绝格式错误的 JSON 语法, 则可能会出现模糊且可能被利用的情况. 特别是, JSON 解析器必须 (MUST) 完全拒绝任何不符合 RFC 7159 中定义的 JSON-text 语法的 JSON 输入.

"The JavaScript Object Notation (JSON) Data Interchange Format" [RFC7159] 第 4 节指出, "对象内的名称应该 (SHOULD) 是唯一的", 而本规范指出

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 Comparison Security Considerations (Unicode 比较安全注意事项)

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