3. SLH-DSA算法框架与参数集

SLH-DSA(Stateless Hash-Based Digital Signature Algorithm)是NIST后量子密码标准化中基于哈希的数字签名方案,其安全性仅依赖于底层哈希函数的抗碰撞性和抗原像性,不依赖任何数论困难问题。理解它的算法框架与参数集,是正确实现和评估该方案的前提。本节从三个核心函数出发,解析其内部结构,并说明标准参数集的构成逻辑与选择依据。

一、整体框架:三层结构

SLH-DSA的算法框架可以概括为“超树 + 少次签名 + 一次签名”的三层嵌套结构。最底层是WOTS+(Winternitz一次性签名),它只能安全地签一条消息;中间层是FORS(Few-Time Signature,少次签名),用于对消息摘要进行“压缩承诺”;最上层是Hypertree(超树),由多层Merkle树堆叠而成,把一次性公钥的验证路径逐层向上锚定到根公钥。

密钥生成阶段,算法自底向上构造超树:先生成最底层各棵子树的WOTS+密钥对,计算其叶节点,再逐层向上哈希得到各层树根,最终最顶层的树根即为公钥PK.root;私钥则由主种子SK.seed、伪随机函数种子SK.prf和公钥种子PK.seed组成。签名阶段,签名者对消息做两级哈希得到摘要,用FORS对摘要的前若干位签名,得到FORS公钥;再用超树中对应叶子的WOTS+私钥对“FORS公钥 + 树索引”签名,并附上从该叶子到根的各层认证路径。验证阶段则反向执行:用签名中的WOTS+签名重建叶节点,沿认证路径逐层哈希到根,与公钥比对;同时用FORS签名重建FORS公钥,校验摘要一致性。

SLH-DSA 三层签名结构(以 SHA-256 变体为例) 消息 M 任意长度 H_msg 摘要 n 字节 + 索引 FORS 少次签名 k 棵子树,各取 1 叶 输出 FORS 公钥 Hypertree 超树(d 层,每层 2^h 个叶子) 第 d 层(顶层) 根 → PK.root 第 d-1 层 树 树 树 第 0 层(底层) 叶 叶 叶 叶 叶 WOTS+ 一次性签名 签 FORS 公钥 + 树索引 签名 σ = (随机数 R, FORS 签名, 超树 WOTS+ 签名, 各层认证路径)

二、标准参数集:哈希函数与安全级别的组合

FIPS 205 定义了 12 个参数集,由两个维度交叉组合而成。第一个维度是哈希函数族:SHA-256 与 SHAKE256。SHA-256 变体使用 SHA-256 配合预计算的简单哈希函数族,速度快、实现成熟;SHAKE256 变体使用 SHAKE256 作为可扩展输出函数,天然支持任意长度输出,适合需要灵活参数或硬件资源受限的场景。第二个维度是安全级别:128 位、192 位、256 位,分别对应 NIST 安全类别 1、3、5。

每个安全级别下又分为“s”(small,小签名)与“f”(fast,快速签名)两种优化取向。以 SHA-256 为例,参数集命名为 SLH-DSA-SHA2-128s、SLH-DSA-SHA2-128f、SLH-DSA-SHA2-192s、SLH-DSA-SHA2-192f、SLH-DSA-SHA2-256s、SLH-DSA-SHA2-256f;SHAKE256 变体同理命名为 SLH-DSA-SHAKE-128s 等。s 变体通过增大超树层数 d、减小每层高度 h,使签名更短但签名计算更慢;f 变体则相反,签名更快但签名体积更大。

参数集 n(字节) h(每层高度) d(层数) 签名长度(字节) 公钥长度(字节)
SLH-DSA-SHA2-128s1697785632
SLH-DSA-SHA2-128f163221708832
SLH-DSA-SHA2-192s24971622448
SLH-DSA-SHA2-192f243223566448
SLH-DSA-SHA2-256s32882979264
SLH-DSA-SHA2-256f324174985664

表中数值为 FIPS 205 标准规定的固定值,可直接用于实现时的缓冲区分配与长度校验。可以看到,安全级别越高,n 越大,签名长度随之增长;同一安全级别下,f 变体的签名长度约为 s 变体的 2 倍左右,但签名速度显著更快。

三、参数选择对性能与安全的影响

参数选择的核心矛盾在于签名体积、签名速度与验证速度之间的权衡。超树总高度 H = h × d 决定了需要签名的层数,也决定了签名中认证路径的总长度。增大 d 会减少每层认证路径的长度,从而缩短签名,但签名者需要为每一层计算 WOTS+ 签名,计算量随 d 线性增长;减小 d 则相反。这就是 s 与 f 两类变体的本质区别。

从安全角度看,n 直接决定哈希输出的字节数,进而决定抗碰撞安全强度(约为 n/2 位)和抗原像安全强度(约为 n 位)。128 位安全级别对应 n=16 字节,256 位对应 n=32 字节。需要特别注意的是,SLH-DSA 的安全归约对哈希函数有额外要求:FORS 和 WOTS+ 的安全性依赖于哈希函数在特定输入分布下的抗原像性,因此实现中必须严格使用标准规定的哈希函数族构造,不能随意替换为“看起来等价”的哈希。

在实际工程中,若应用场景对带宽敏感(如区块链交易、嵌入式固件签名),优先选择 s 变体;若对签名延迟敏感(如高频交易、实时认证),优先选择 f 变体。SHA-256 变体在通用 CPU 上通常比 SHAKE256 变体更快,而 SHAKE256 变体在支持 Keccak 指令的硬件上可能更具优势。

四、实现要点与验证判据

实现 SLH-DSA 时,首先应根据所选参数集确定所有长度常量:n、h、d、FORS 的 k 与 a、WOTS+ 的 w 等。这些常量直接决定密钥、签名和中间缓冲区的布局。其次,密钥生成、签名、验证三个函数必须共享同一套地址结构(ADRS),用于在哈希调用中区分不同的树、层、链和哈希类型,地址编码错误是导致验证失败的最常见原因之一。

验证阶段的判据非常明确:用签名中的 WOTS+ 签名和认证路径重建出的根,必须与公钥中的 PK.root 逐字节相等;同时,用 FORS 签名重建的 FORS 公钥必须与 WOTS+ 签名所承诺的值一致。任一环节不匹配即判定签名无效。实现时应先做长度校验(签名长度必须等于参数集规定值),再做密码学验证,避免因缓冲区越界引发安全问题。

// 以 SLH-DSA-SHA2-128s 为例的长度常量(示例)
#define N        16      // 哈希输出字节数
#define H        9       // 每层树高
#define D        7       // 超树层数
#define SIG_LEN  7856    // 签名总长度
#define PK_LEN   32      // 公钥长度(2*N)
#define SK_LEN   64      // 私钥长度(4*N)

上述常量在实现中应作为编译期常量或配置项固化,并在签名与验证入口处做断言检查。对于需要支持多参数集的库,建议将参数集抽象为结构体,把 n、h、d、签名长度等字段集中管理,避免散落在各函数中的魔数导致维护错误。

SLH-DSA 是无状态签名方案,签名者不需要维护任何计数器或状态,这一点与 XMSS、LMS 等有状态哈希签名方案有本质区别。但也正因如此,其签名体积远大于传统签名,且签名速度较慢。在评估是否采用 SLH-DSA 时,应把签名体积和签名延迟作为硬约束纳入系统设计,而不是事后优化。

综上,SLH-DSA 的框架可归纳为“FORS 压缩消息、WOTS+ 承诺叶节点、超树锚定到根”的三级结构;参数集则在哈希函数族、安全级别和 s/f 优化取向三个维度上展开。正确理解 h、d、n 三个核心参数的作用,是选择参数集、预估性能和分析安全边界的关键。