2. 哈希签名核心构件
SLH-DSA(Stateless Hash-Based Digital Signature Algorithm,FIPS 205)不是凭空设计出来的签名方案,而是把三个经典哈希签名原语——WOTS+、FORC 和 Merkle 树——按“一次性签名 → 少量次签名 → 无状态多次签名”的层次逐级封装而成。理解这三块积木各自解决什么问题、彼此如何拼接,是读懂 SLH-DSA 参数集、签名长度和验证流程的前提。
一、WOTS+:把哈希链当作一次性签名
WOTS+(Winternitz One-Time Signature Plus)是 SLH-DSA 最底层的签名单元。它的核心思想是:把消息摘要按 w 位一组切分,每一组对应一条长度为 w 的哈希链,链上每个节点是前一个节点做一次哈希函数 F 的结果。签名者持有链的起点(私钥),公开链的终点(公钥)。签名时,对每个 w 位分组值 v,从起点向后走 v 步,得到的中间节点就是该分组的签名片段;验证者拿到片段后,继续向后走 (w−1−v) 步,若结果等于公钥终点,则签名有效。
WOTS+ 的关键约束是“一次性”:同一条链上若对两个不同消息各签一次,攻击者就能通过两个中间节点推出更多链上位置,进而伪造签名。因此 WOTS+ 只能签一条消息。SLH-DSA 采用 w=16、n=16 或 24 或 32 字节的配置,一条 WOTS+ 签名由 67 个 n 字节片段组成(len = 67),签名长度约为 1 KB 量级。
二、FORC:用少量 WOTS+ 拼出“少量次”签名
FORC(Forest of Random Chains)是 SLH-DSA 中用于把多个 WOTS+ 公钥组织成“可签少量消息”的结构。它本质上是一棵高度为 h/d 的子树,叶子是 WOTS+ 公钥的哈希值,内部节点是子节点哈希的拼接再哈希。FORC 的根就是该子树的公钥代表。签名一条消息时,FORC 会选取一个尚未使用的叶子索引,用对应的 WOTS+ 私钥签名,并附上从该叶子到根的认证路径(authentication path)。验证者用路径重算根,与已知根比对。
FORC 的“少量次”体现在:一棵高度为 h' 的 FORC 最多可签 2^h' 条消息,超过就会重复使用叶子,破坏安全性。SLH-DSA 通过把整棵大树的签名能力切分成多个 FORC 子树,并让每个子树只签有限条消息,从而在“无状态”前提下控制风险。
三、Merkle 树:把 FORC 根汇聚成全局公钥
SLH-DSA 的最上层是一棵高度为 h 的 Merkle 树,叶子是各 FORC 子树的根。树根即全局公钥 PK.root。签名时,算法根据消息摘要和随机数选出一个叶子索引,用该叶子对应的 FORC 子树完成一次 WOTS+ 签名,再附上从该 FORC 根到全局根的认证路径。验证者只需 PK.root、消息、签名三样东西,就能独立重算路径并判断有效性——这正是“无状态”的含义:签名者不需要维护已用叶子的计数器,验证者也不需要任何历史状态。
构造骨架一句话总结:WOTS+ 负责“签一个摘要”,FORC 负责“把多个 WOTS+ 公钥聚成一棵可签少量消息的子树”,Merkle 树负责“把多个 FORC 根聚成全局公钥”。三层嵌套,逐级放大签名能力,同时把状态需求压到零。
四、安全归约思路:为什么这三层能拼出可证明安全的签名
SLH-DSA 的安全性归约可以概括为一条链:若存在敌手能伪造 SLH-DSA 签名,则能构造出算法攻破底层哈希函数的抗第二原像性或抗碰撞性。具体来说,伪造一条 SLH-DSA 签名意味着敌手要么伪造了某个 WOTS+ 签名(需要找到哈希链上的第二原像),要么伪造了 FORC 认证路径(需要找到 Merkle 树内部节点的碰撞),要么伪造了全局 Merkle 路径(同样需要碰撞)。由于 SLH-DSA 只依赖哈希函数,不依赖数论假设,它的安全性在量子计算模型下依然成立——这是它相对于 RSA/ECC 签名的根本优势。
需要特别注意的是“无状态”与“一次性”的张力。WOTS+ 本身是一次性的,FORC 是少量次的,但 SLH-DSA 通过“每次签名随机选取叶子索引”的方式,把重复使用叶子的概率压到可忽略。具体地,若树高为 h,最多可签 2^h 条消息;当签名数量远小于 2^h 时,碰撞概率极低。SLH-DSA 的参数集(如 SLH-DSA-SHA2-128s 使用 h=63、d=7)正是围绕这一概率边界设计的。
五、参数速查与工程含义
| 构件 | 作用 | 关键参数 | 工程影响 |
|---|---|---|---|
| WOTS+ | 签一个消息摘要 | n(哈希长度)、w(Winternitz 参数) | n 越大签名越长、安全性越高;w 越大签名越短但计算越多 |
| FORC | 把多个 WOTS+ 公钥聚成子树 | h'(子树高度) | 决定单棵子树可签消息数,影响签名中认证路径长度 |
| Merkle 树 | 聚成全局公钥 PK.root | h(总高度)、d(层数) | h 越大可签消息越多,但签名和公钥越大;d 影响子树划分 |
学习建议:先手推一条 w=16、n=16 的 WOTS+ 哈希链,数清楚 67 个片段是怎么来的;再画一棵高度为 3 的 FORC 子树,标出认证路径;最后把 FORC 根当作叶子,画一棵高度为 2 的 Merkle 树。三层画完,SLH-DSA 的签名结构和验证流程就基本清楚了。
常见误区:不要把 FORC 和 Merkle 树混为一谈。FORC 的叶子是 WOTS+ 公钥,Merkle 树的叶子是 FORC 根;FORC 解决“少量次签名”,Merkle 树解决“全局公钥聚合”。两者层级不同、职责不同,但都依赖哈希函数的抗碰撞性。