摘要

  • RFC 9814 有两条不同的证据路径:没有签名属性时,Pure SLH-DSA 直接签内容;存在签名属性时,Pure SLH-DSA 签的是 SignedAttributes 的 DER 编码。
  • 在后一条路径里,大文件只通过 message-digest 进入被签信息,CMS 类型通过 content-type 进入;HSM 只能证明它处理了最后那段输入,不能单独证明上游选对了文件、摘要和属性。
  • 这种结构有利于大对象流式处理,也能缩小 HSM 输入,但它不是 SLH-DSA 的预哈希模式。把两者混称,会让 OID、验签输入和审计结论同时出错。

“签过”究竟指什么

设想一份六 GB 的合规归档。审批者在对象存储界面看到文件 A,系统把一个请求送给 HSM,最后生成可通过验签的 CMS 对象。日志记录了密钥标识、时间和成功状态。几年后发生争议:当时送去计算摘要的是不是文件 A 的那个不可变版本?日志回答不了。

问题并非 SLH-DSA 本身失效,而是“内容到签名”的责任被拆成了多段。RFC 9814 是 2025 年 7 月发布的标准轨 RFC,规定 CMS SignedData 使用空上下文的 Pure SLH-DSA。它没有在这一 CMS 用法中规定 HashSLH-DSA 预哈希模式。不过,CMS 自己的签名属性机制可以先对内容求摘要,再让 Pure SLH-DSA 签一个小得多的属性集合。

因此,判断一个实现是否可信,不能先问“是不是后量子算法”,而应先问“SLH-DSA 的消息输入到底是哪一串字节”。

没有签名属性:内容就是消息

当 SignerInfo.signedAttrs 不存在时,Pure SLH-DSA 直接对内容执行签名。规范要求的空上下文属于算法调用条件,不是产品可以自由填写的 CMS 业务标签。

CMS 结构中仍有 digestAlgorithm 字段,但在这条路径上,它不用于预先散列 SLH-DSA 的消息。RFC 9814 明确区分了这件事。字段可能因为 CMS 结构和兼容性继续出现,却不能据此宣称实际操作是“签 SHA-256(内容)”。如果中间件只把一个外部摘要交给签名服务,就已经改变了协议所规定的输入。

这对远程签名和大文件尤为重要。Pure 操作所需的是消息本身。若验证端只在流入期间保留了一个 CMS 摘要,事后不一定能仅凭该摘要完成无属性路径的 Pure 验签。系统必须在存储、重读或接口层面处理真实消息,而不是把结构字段误当成替代物。

存在签名属性:内容变成一项被签声明

当 signedAttrs 存在时,流程发生根本变化。系统使用声明的摘要算法对内容求值,把结果写入必需的 message-digest 属性;同时写入必需的 content-type,说明被封装或外置内容的 CMS 类型。随后,完整属性集合以 DER 生成规范字节,Pure SLH-DSA 对这些字节签名。

完整证明至少包含六个问题:

  1. 哪个不可变对象版本提供了输入字节?
  2. 是否从第一个字节读到最后一个字节,长度是多少?
  3. 哪个摘要算法产生了属性中的值?
  4. 内容类型是否与实际 eContentType 及业务授权一致?
  5. 完整属性集合生成了哪一串 DER 字节?
  6. 哪把 SLH-DSA 密钥以哪个参数集签了这串 DER,证书和策略为何接受它?

HSM 通常只直接回答第六个问题的一部分:某把受保护密钥对所提交的输入产生了签名。它不知道对象存储名称是否在两次读取之间指向了不同版本,也不知道界面显示的内容类型是否等于属性内的值。

验签端必须重新计算收到内容的摘要,并与 message-digest 比较;还必须比较被签 content-type 与内容封装中的类型。后者不是装饰性元数据。内容类型可能决定调用哪个解析器、是否允许运行自动动作、适用哪项保留政策,以及某把密钥是否有权批准该类对象。

DER 是授权事实的一部分

人看到的是属性名称和值,签名算法看到的是字节。DER 为 ASN.1 结构给出唯一的规范编码。标签、长度、集合排序、值类型以及不认识的属性都会影响最终输入。

仅保存一份 JSON 摘要表或屏幕截图,不足以保证几年后能够重建被签字节。最低限度应保存原始 CMS 对象;高责任场景还应保存交给签名器的确切 DER、该字节串的审计摘要、生成组件版本,以及由独立实现重建并比对的结果。

这也暴露出一个经常被低估的控制者:属性构造器。私钥可能在高等级 HSM 中从未导出,但普通应用仍可选错文件、漏掉必需属性、把显示值和实际值分开,或者在批准后重新编码。密钥边界再坚固,也无法为上游消息构造提供追溯证据。

摘要算法和签名算法要形成一致故事

有签名属性时,SignerInfo.digestAlgorithm 标识计算 message-digest 的函数,SignedData.digestAlgorithms 集合要包含各签名者使用的摘要算法。RFC 9814 还要求摘要输出长度满足所选 SLH-DSA 参数集的碰撞安全需要。因此,“摘要相等”仍不是完整结论;系统还要证明算法被允许、参数组合正确且没有被降级。

RFC 9814 为十二个 Pure SLH-DSA 参数集定义签名算法标识,参数必须缺省。验签者要检查签名算法与公钥算法是否一致。RFC 9909 处理相关 X.509 标识和证书使用,但证书链有效不等于内容接合正确;内容摘要正确也不等于密钥具备业务信任。两条证据应在最后裁决处汇合,而不应压成一个绿色图标。

规范还建议加入 RFC 6211 定义的 CMSAlgorithmProtection 签名属性。它把摘要与签名算法标识纳入被签属性,以抵抗外层算法字段被替换。由于这是 SHOULD,接收方必须明确规定缺失时接受、隔离还是拒绝,并对兼容例外进行计数。没有告警的“暂时兼容”最终会变成不可见的生产基线。

为什么它不是 SLH-DSA 预哈希模式

从接口图看,有属性的路径确实像预哈希:大文件进入外部哈希器,小对象进入 HSM。但相似的是数据形状,不是密码操作。

FIPS 205 区分 Pure 与预哈希变体,RFC 9909 也分别处理相应标识。RFC 9814 在 CMS 中选择 Pure。CMS 摘要只是 SignedAttributes 中的一项;Pure SLH-DSA 最终签署的是包含摘要、内容类型及其他属性的 DER 整体,而不是单独签那个外部摘要。

把两者都写成“prehash SLH-DSA”会造成三类错误:开发者选择错误 OID;验证端用错误输入重建签名;审计者把摘要凭证当作完整签名请求。准确的系统描述应是:“Pure SLH-DSA 签 CMS 签名属性,内容经 message-digest 接合。”

流式优势把权力交给谁

签名属性确实适合大对象。接收方可边收边求摘要,不必为了最后的 SLH-DSA 验证长期保留全部高速缓存;签名方也可避免把数 GB 数据送入受限模块。但外部哈希器由此成为信任边界。

流式重试需要单独测试。断线后是从零重算,还是从一个经过认证的内部状态继续?对象名是否指向固定版本?分片是否可能来自两次上传?记录的长度是否与读取量一致?内容类型来自被签结构,还是来自可变 HTTP 头?没有这些答案,正确摘要也可能被错误工作流使用。

每个签名事务应保存:内容标识与不可变版本、长度、摘要算法和值、CMS 内容类型、完整属性集合、DER 输入、SLH-DSA 参数集、公钥与证书标识、签名、策略版本、时间,以及内容读取、摘要匹配、类型匹配、属性策略、算法保护、签名和证书路径各自的结果。

验收测试应逐一改变内容字节、摘要、类型、附加属性、DER 编码、摘要标识、签名标识、公钥和证书链。每次失败都必须落在可命名的阶段,而不是统一报“签名无效”。还要覆盖分离内容、封装内容、多 GB 数据、流中断、CMSAlgorithmProtection 缺失、算法参数不应出现却出现,以及签名成功但证书路径失败的情况。

RFC 9814 规定互操作方式,不承诺厂商普及率、HSM 吞吐量或实际部署性能。它也不会让 CMS 的加密、证书链和所有周边算法自动获得同等安全。随机性、侧信道、故障、密钥生成与保管仍需独立治理;每把 SLH-DSA 密钥少于 2^64 次签名的限制也需要生命周期计数。

卢恒提出的“最小初始规范”在这里不是少写控制,而是先公布最小可验证接口,让不同参与者能测试同一事实。所谓现实层,不是产品页上的合规标识,而是从内容字节到摘要、从摘要与类型到 DER、再从 DER 到签名与策略结论的可重复映射。运行中的代码只有留下这些凭证,才比抽象承诺更接近事实。

来源