摘要

  • RFC 3185 允许第一份 CMS 对象的内容加密密钥为后续对象派生密钥加密密钥,以减少重复的非对称密码运算,但也把第一封消息变成持续状态的起点。
  • 若 MSG1 把 CEK 交给集合 S1,而 MSG2 只声明 S1 的一个子集,S1 的全部成员仍可能解密 MSG2。后来的名单缩小,不构成对旧能力的撤销。

这份 2001 年 10 月发布的文件名为 Reuse of CMS Content Encryption Keys,属于标准轨道,RFC Editor 当前将其列为 Proposed Standard。它解决的是成本:客户端可能在一次交易里分别加密多个字段,服务器之间也可能频繁交换数据;每次重新进行非对称密钥建立并不划算。

RFC 没有把方案包装成完整协议。它称其为需要嵌入更大上下文的“技巧”,并要求外层规范定义引用密钥丢失后的行为。密码学 API 必须允许 CMS 层处理相应密钥材料,内容加密与密钥加密算法还要在格式、长度和强度上兼容。它不适用于一般性的群组密钥管理。

机制从 MSG1 开始。MSG1 的未保护属性含有 CEKReference,用于标识其内容加密密钥。MSG2 把同一值写作 KEKIdentifier。收件方用引用找到先前保存的 CEK,再派生 MSG2 用来解包新 CEK 的 KEK。引用只是索引,不是秘密;只知道引用值,不能获得密钥。

在兼容格式下,派生操作把旧 CEK 的字节倒序,以避免已知明文与密文块被直接充当下一把加密密钥。格式不同时,可选方案用 PBKDF2 处理旧 CEK。这些是 2001 年的规范内容,不应借后来的 CMS、PBKDF2 与 AES 包装标准推断现代部署或自动更新。

真正的权力边界出现在收件人变化。MSG1 若发给 S1,MSG2 即使只写入 S1 的子集,所有 S1 成员仍持有派生所需的旧 CEK。MSG2 的名单是当前声明;MSG1 的密钥交付是历史能力。两者都可能正确,却回答不同问题。

本文把这种现象称为“收件集合延续”,但这不是 RFC 的术语,也不是所有 CMS 的通则。它专指 RFC 3185 的复用链。一个未收到旧 CEK 的主体,不会因为看见 CEKReference 就得到解密能力。

CEKMaxDecrypts 提供一个预期次数。发送方必须遵守,接收方把它当提示;属性缺失时,默认计划复用一次。接收方可以在完成预期成功消息前保留引用与 CEK,同时用自己的时间和容量上限决定清除。

这个整数不是远程销毁命令。它不能证明每个收件人看到了相同数量的消息、按时增加计数、删除所有副本,或让离线存储忘记秘密。过大的值,或迟迟不来的后续消息,反而可能诱导长期占用内存。因此保留与删除仍是各节点的本地动作。

RFC 3185 还明确否定了两种推论。加密不认证发送者;任何人都能制作含有已知引用的 EnvelopedData。正确引用也不防止插入或重放。因此,引用识别、发送者身份、授权、完整性、顺序与新鲜度必须分别留证。

解密成功同样只是有限观察:某个主体找到了密钥材料和参数,得到了通过既有检查的明文。它不证明消息新鲜、旧收件人已经失去能力、明文后来被安全处理,或应用完成了预期结果。

链条还可以滚动:MSG[n] 的新随机 CEK 成为 MSG[n+1] 的来源。RFC 警告不要从同一消息的 KEK 反向产生其 CEK,否则可能意外固定密钥。这要求记录每次派生的来源、目标与新密钥独立性,而不是只保留“解密成功”。

错误也应有类型。找不到引用、本地状态已过期、算法不兼容、派生功能不支持、参数被改动和密钥错误不是一回事。一个统一的“无法解密”会让策略淘汰与攻击迹象混在一起。

RFC 3185 留下的历史教训是:密码学权力沿已经交付的材料流动,而不是沿最新界面中的名单流动。要回答谁能读 MSG2,必须检查 MSG1 的交付、密钥保存、派生参数、过期与实际解密,而不能只看 MSG2 的收件人栏。