摘要

  • RFC 9879 允许在 PKCS #12 中使用 PBMAC1,规定了必须支持的 PBKDF2/HMAC-SHA-256 组合,并纠正了 RFC 9579 留下的密码编码规则。
  • 兼容设计可能让旧读者在不支持新 MAC 时仍触及加密密钥材料;弱 KDF 参数和弱密码也不会因算法名称更新而消失。
  • 可靠迁移必须分别记录真实参数、校验结果、失败处置和导入后的密钥托管,不能把一个算法标识当成安全结论。

一只可移植密钥容器至少有五道不同的问题:格式能否解析,密文能否解开,完整性是否验证,参数是否满足本地政策,私钥导入后是否仍留在预定托管边界。它们前后相接,却不能互相代答。

RFC 9879 只解决其中一层。它于 2025 年 9 月以 IETF 信息类 RFC 发布,废止 RFC 9579,并更新 PKCS #12 与 PKCS #5。文档允许 id-PBMAC1 成为 PKCS #12 DigestInfo 中的完整性算法;一旦选用该标识,PBMAC1-params 必须存在且自洽,摘要值也必须按这些参数对 authSafe 计算。

这项变化拆开了旧有耦合。原先的 PKCS #12 密码完整性方式把 MAC 密钥生成绑定在容器专用的派生方法上。PBMAC1 则明确携带 KDF 与消息认证函数。所有实现都必须支持 PBKDF2 配合 HMAC-SHA-256,同时把 HMAC-SHA-256 用作 PBKDF2 的伪随机函数;其他 SHA-2 HMAC 值得支持,scrypt 等其他 KDF 也可以实现。

灵活性并没有取消约束,而是把约束移进参数。派生密钥长度必须明确编码;PBKDF2 参数若没有 keyLength,实现必须拒绝。采用 SHA-256 HMAC 时,派生长度应为 32 字节。PBKDF2 配合 SHA-1 HMAC 不应再用,输出不超过 160 位的其他摘要函数则不得使用。

两个看似熟悉的外层字段也不再拥有决定权。PBMAC1 生效时,PKCS #12 外层 macSalt 和 iterations 必须被忽略;为了照顾旧软件,RFC 9879 又建议它们不要为空或为零。若审计程序只采集外层迭代次数,却没有沿算法标识进入 PBMAC1-params,就可能得到一条格式漂亮但与实际计算无关的记录。

兼容条款更值得管理层注意。新语法的设计目标之一,是让不认识新完整性保护的旧应用仍有机会解密密钥材料,条件是它能够忽略 MAC 校验失败。这能降低迁移断裂,却也清楚说明:“文件打开了”不等于“完整性通过了”。RFC 9879 没有点名任何产品采用这种行为,本文也不会据此推断某个厂商的默认设置。

密码编码的修订展示了运行事实的价值。RFC 9579 曾要求 PBMAC1 密码使用带 NULL 终止符的 BMPString。后来获确认的勘误指出,生成测试向量的实现实际上保留了 UTF-8 字节。RFC 9879 最终要求 UTF-8,且不得附带 NULL 终止符或字节序标记。这里的教训不是“代码永远高于文档”,而是迁移证据必须落到实际输入输出的字节,不能只写一个人眼看到的密码。

测试向量的证明范围同样有限。文档提供 SHA-256、SHA-512 组合的有效样本,也提供迭代次数错误、盐错误和缺少密钥长度的无效样本。通过它们可以说明某个实现完成了指定计算,却不能说明生产密码足够强、本地参数下限已经启用、未知算法一定失败关闭,或私钥导入后仍在合规设备内。

RFC 9879 还明确提醒:有些 KDF 允许产生短至一个字节的输出,这会降低暴力尝试 HMAC 的成本;而 KDF 参数本身并不受密码学保护。文档建议拒绝短于 20 字节的派生密钥,也允许实现拒绝其他弱参数。这是一项留给本地执行的判断,不是所有读者已执行的证据。

更深的密码限制来自 PKCS #5。PBMAC1 校验过程很清楚:读取盐、迭代次数和密钥长度,从密码派生密钥,重算 MAC,最后输出正确或错误。但这种确定性并不能阻止离线猜测。盐与工作因子只能抬高成本,不能给弱密码凭空增加熵。scrypt 用内存成本削弱并行硬件优势,但 RFC 9879 并未要求所有实现支持它。因此,“PBMAC1”标识的是机制,不是统一的强度等级。

一次完整导入应留下这样的链条:收到容器;识别生成器与读者版本;解析真实算法和参数;本地参数政策通过;密码按指定字节规则编码;MAC 验证成功;加密层另行验证;密钥使用政策通过;导入进入明确托管边界;再次导出后的格式与强度得到观察。任何断点都应原样保留。

来源