【零基础入门哈希签名架构,从Lamport到SPHINCS+】第二集 哈希签名树 Merkle Tree Authentication

第一集 哈希签名始祖 Lamport 方案及其改进版本(Merkle,Winternitz)
第二集 哈希签名树 Merkle Tree Authentication
第三集 HORS Hash to Obtain Random Subset 2002、DBS算法 2008
第四集 GMSS、XMSS、Multi Tree XMSS
第五集 SPHINCS 2015 SPHINCS+ 2019(完结撒花)

在这里插入图片描述

一、为什么提出 Tree Authentication

在第一集中,我们一直忽略了一个问题。

设想一下,假如有一个Hacker(黑客),在截获到Sender发送给Receiver的公钥之后,把这个公钥改成Hacker自己的公钥,然后再发给Receiver,那么Receiver就会误认为这是Sender的公钥。

所以我们之前所说放方案,其安全性都需要建立在一个前提下:Receiver需要确认公钥确实是Sender发出的。在古代,这里确认的方法就是两人当面确认,相当于Sender当着Receiver的面签上自己的名字,这样Receiver才能确认这是Sender的字迹。而在数字时代,这里常见的方法就是数字证书,这里就暂时不详细讲解什么是数字证书。

按照之前的算法,每发一条消息,都要发送一个公钥,就要确认一次(两人就要见面一次)。那为什么不直接在两人见面的时候传输信息呢?弄这个签名机制不是多此一举吗?

对此,Merkle就想出了一种方法,只需要确认一次,就能传输多个信息。

二、Merkle Tree

Merkle 在1990年《A CERTIFIED DIGITAL SIGNATURE》中的第六节“6. Tree Authentication”提出了这个方案。

基于上面提到的问题,Merkle想到了用“树”这个结构,把所有的“要确认的公钥”合成一个“要确认的公钥”。

Mekle在论文中还说了:除了哈希签名这个领域以外,Merkle Tree还可以应用到各种各样的验证方法中。

2.1 Merkle Tree 在哈希签名应用中的 全流程

  1. 确认要发送的消息:Sender需要发送N条消息(N一般为2的正整数次幂,如2,4,8,16……),这个N条消息已经确认了。产生N个私钥 x i , i ∈ [ 1 , N ] x_i, i \in [1,N] xi,i[1,N],每个私钥 x i x_i xi都经过哈希函数得到对应的公钥 y i = H ( x i ) y_i=H(x_i) yi=H(xi)

  2. 构造Merkle树:所有的公钥 y i y_i yi构成叶子节点,两个相邻的叶子节点之间用某种方法“结合”后,再次经过哈希函数,得到它们两个的父节点。这里的“结合”有很多种方法,有时候是使用“或”操作,有时候是先用“或”操作,再跟一个随机数进行“异或”操作,如下图:
    在这里插入图片描述
    在这里插入图片描述
    最终通过计算我们可以得到根节点的值。

  3. Receiver确认阶段:这个环节是新增的,在第一集中是被我们忽略掉的。Sender“当面”与Receiver确认整个树的根节点的值。Receiver记下这个值,命名为root。完毕。

  4. Sender发送信息:Sender需要给Receiver传输三样东西。整颗树(叶子节点就是公钥),私钥(也就是签名,因为我们目前讲到的所有哈希签名方案都是把私钥当作签名的),消息(massage)。而这个传输过程不需要保证“当面”。也就是说,即使Hacker(黑客)在这个传输过程中,截取并且修改里面任意一项,Receiver都可以发现内容被篡改。

  5. Receiver接收并验证:Receiver从根节点开始验证。首先,确认根节点下面的两个子节点是否正确。对这两个字子节点进行“结合”后经过哈希函数,得到一个哈希值。如果这个哈希值就是之前和Sender当面确认的root,说明这两个字节点是Sender发送过来的;否则说明这两个字节点被人篡改过。后面的节点以此类推,直到验证完整颗树。

2.2 Merkle Tree的安全性

在这里插入图片描述

如上图所示:
假设Hacker截获了Sender发送的内容,试图篡改其中的第6条信息 x 6 x_6 x6,同时也要修改对应的 y 6 y_6 y6,然后将这个篡改后的内容发送给Receiver。注意,Hacker只篡改了 y 6 y_6 y6这个叶子节点,树上的其他地方都没有修改

Receiver收到后,开始验证。按下面的顺序验证:

N1,3等于root,N1,3验证完毕。

将N2,2和N3,2“结合”后,经过哈希函数,得到的哈希值,等于N1,3。N2,2和N3,2验证完毕。(也就是可以确认N2,2和N3,2是Sender本人发送过来的)

N4,1和N5,1,N6,1和N7,1,y1和y2,y3和y4同上,验证完毕。

到此为止,Receiver认为,上面提到的所有节点,都是Sender发送过来的,事实也是如此。

验证y5和y6,将y5和y6“结合”后,经过哈希函数,得到的哈希值。Receiver发现,这个哈希值不等于N6,1,他认为,y5和y6中至少有一个消息不是Sender发来的。

这样Receiver就发现了被篡改的部分。

我们再思考这种情况:
在这里插入图片描述
如果N6,1也被Hacker篡改了呢,Hacker重新计算y5(Sender)和y6(Hacker)得到的哈希值,把N6,1改成这个哈希值。

显然,Receiver在用N3,2验证N6,1和N7,1的时候,发现N6,1和N7,1计算出来的哈希值不等于N3,2,就会发现,N6,1和N7,1至少有一个被篡改过。

综上所述,整个树只要有一个地方被修改过,都会被发现出来。要传输完整的正确的树,只有Sender能做到。

这就保证了该算法的安全性。

2.3 Merkle自己的一些改进

在验证的时候,我们不需要每个叶子节点都从根节点开始验证,可以使用我们刚刚用到的方法逐层验证,或者是按照massage块的顺序,使用回溯法进行验证(Merkle的方法)

从根节点开始验证
从根节点开始验证

按照massage块的顺序,使用回溯法进行验证
按照massage块的顺序,使用回溯法进行验证

三、一些疑惑和解答

在学习Merkle Tree的时候,我对此方案感到很疑惑:此方案没有减小公钥和私钥的大小,反而新增了一个数结构,使得传输的信息更多了。验证的速度也没提升。

那这个算法到底有什么优点呢?

有的文章说“这种方法可以让一个公钥使用多次,再也不是一次性的签名了”。但我觉得这种说法很具有误导性,其实哈希签名算法走出“一次性”这个阶段不是在Merkle这里实现的(在第三集中会讲到真正的可以多次使用的哈希签名方案)。我理解的多次使用的方案是,在你发送了消息过后,还可以使用之前的密钥对来进行签名,比如RSA算法。显然Merkle Tree不满足这个条件。因为在你计算root之前,就需要把所有叶子节点的信息都确认下来,你可以分多次传输这些信息,但是你不能再次使用这些密钥对来对新的信息进行签名。因此这种方案是一次性的签名方案。

你可能还会看到有的文章会说,这种方法减小了公钥的大小。你会感到很疑惑:公钥不还是那些叶子节点吗,这些叶子节点还是要发送给Receiver的呀,并没有减少,反而因为树结构的加入使得整个内容变大的,我们可以把整个树看作是公钥,那么公钥的大小应该是增大了才对啊。
其实这种说法所说的“公钥”不是叶子节点的公钥,而是Receiver和Sender要“当前”确认的公钥,就是root。

现在你应该明白了这个算法的意义所在了。

现在回过头来再看看“Merkle树在哈希签名方案中具有的优势”你就能明白了。

Merkle树在哈希签名方案中具有以下几个优势:

  1. 效率:Merkle树可以高效地验证大量数据的完整性。通过将消息分割为固定大小的数据块,并使用哈希算法计算每个数据块的哈希值,可以快速生成树的内部节点和根节点的哈希值。这样,在验证消息的完整性时,只需要比较少量的哈希值而不是整个消息,从而提高了效率。

  2. 安全性:Merkle树可以提供强大的数据完整性保护。根节点的哈希值代表了整个数据集的完整性,即使只有一个叶子节点的数据发生了改变,也会导致根节点的哈希值完全不同。因此,通过比较根节点的哈希值,可以有效地检测到数据是否被篡改。

  3. 紧凑性:Merkle树可以将大量数据以紧凑的方式表示。通过使用哈希值作为叶子节点,Merkle树可以将数据集的完整性表示为一个相对较小的哈希值。这对于在网络传输中发送和存储数据非常有用,可以节省带宽和存储空间。

这里说到的“只需要比较少量的哈希值” “可以节省带宽和存储空间”都是在说Receiver和Sender需要“当前”确认的公钥。

如果还是用第一集中讲到的方法,每个叶子节点都需要Receiver和Sender“当前”确认。需要注意的是,这个“当面”我一直加了引号,因为我们在数字时代,不能做到真正的当面,只能够通过“数字证书”等方法来确认。这些确认方法一般是通过多次签名方案来传输这个root(公钥)的,所说就涉及到了“带宽和存储空间”。

这样一对比就能明白这个方案的意义所在。

四、Merkle Tree真正发挥作用的地方

我们现在所说的Merkle Tree,不能在“传输阶段”把公钥压缩。根本原因有两个:

  1. 要把所有的叶子节点都公布,才能得到最后的根节点来进行验证。
  2. 有没有一种办法,只公布一个叶子节点,最后也能计算出根节点呢?即使有,也没有必要这么做,因为既然所有的叶子节点都已经是对消息进行了签名了的,每次公布几个和全部都公布并不会改变被签名了的消息,没有什么实质性的影响。

到了后面第三集讲解的树的DBS算法和HORS方案,分别解决了第1点和第2点。

  1. 树的DBS算法使得无需公布所有的叶子节点,就能计算出根节点,通过公布“验证路径”的方法来计算出根节点。

  2. HORS方案是革命性的方案,它让哈希签名从OTS变成了可以实现FTS,而且公钥的产生不再依赖于消息。HORS可以先产生公钥,公布出去,然后再用这一个公钥多次签名多条不同的消息。这就给了我们每次只公布一个叶子节点的理由,我们可以每签名一条消息,就公布一个叶子节点,而且由于公钥是不变的,因此树的根节点也不会改变,还是在同一颗树下,解决了第2个问题。

有了HORS和DBS的加入,使得Merkle Tree公钥可以真正的压缩成只有一个根节点。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值