背景
哈希签名是指只依赖哈希函数的数字签名算法(而非某个数学问题,例如ECC的离散对数问题、RSA的大整数因式分解)。这类算法一直不是主流,但随着量子计算机及其配套算法(舒尔算法)的出现,ECC和RSA的安全性降低,并且任何基于离散对数问题的算法都不能幸免。而哈希签名可以更好地对抗量子计算机的攻击,SPHINCS+算法(2019年公布的哈希签名算法)也通过了NIST的评选,不出意外将会成为正式标准。
概述
Leslie Lamport的Constructing digital signatures from a one way function. Technical Report SRI-CSL-98, SRI International Computer Science Laboratory (1979)是我追溯到的最早的哈希签名算法,现在很多文献都会引用它。这个文献现在已经公开可以免费下载。
本文将会详细介绍其第2章所述的算法并翻译部分内容,但不会给出代码。Lamport40有很多缺点,现在已经没有软件会直接使用它。
一般说Lamport算法都是指面包店算法,Leslie Lamport的代表作,所以我起了一个新名字"Lamport40",选择编号40是因为原文使用长度为40的数组作为公钥。
算法描述
设m表示待签名的数据,Z表示{1,2,3,......,40}的子集中恰好包含20个元素的集合构成的集合,也就是{1,2,3,......,40}的幂集的一部分(译者注:原文是,一文中使用Z代替。40和20可以替换为2n和n,译文会按照原文直接使用40和20)。
设F是一个哈希函数。为叙述简便,约定其输出的哈希长度为32字节。
设G是一个哈希函数,其值域是Z。G的构造并不复杂,可以参考原文第3章。
签名者首先选择40个整数作为私钥,记为ki(i=1,2,3,...,40),计算这40个数的哈希值F(ki),令a=(F(k1),F(k2),...,F(k40))作为公钥发送。
签名过程:首先计算G(m)={i1,i2,i3,...,i20},令i1<i2<i3<...<i20,得到一个元组(i1,i2,i3,...,i20),将(ki1,ki2,ki3,...,ki20)作为签名值发出。
验签过程:首先计算G(m)={i1,i2,i3,...,i20},令i1<i2<i3<...<i20,得到一个元组(i1,i2,i3,...,i20),计算F(ki1)~F(ki20),验证20个哈希值是否与公钥对应。需要注意的是验签过程计算的哈希值要按照i的值放入长度为40(不是20)的数组中,和公钥比较时只比较有值的部分,如果全部相同则验签通过。
算法缺陷
1、公钥长度和签名长度过长。
2、签名值包含私钥的部分内容,因此密钥对只能一次性使用。