简单了解默克尔(Merkle)树

1 篇文章 0 订阅
1 篇文章 0 订阅

       Merkle树是Ralph Merkle在1988年发明的,旨在构建更好的数字签名。原文是A DIGITAL SIGNATURE BASED ON A CONVENTIONAL ENCRYPTION FUNCTION本篇论文在Weki百科中显示比较难以读懂(对于非密码学专业的人来说),第二篇参考是Providing Authentication and Integrity in Outsourced Databases using Merkle Hash Tree's,比较容易读懂。当然两篇文章我是在维基上找到的,只有几行字来介绍提出Merkle tree的文献。

       

一、先讲解一下hash函数。

         哈希函数(Hash function),也被称为散列或杂凑函数。哈希函数是一个公开函数,主要的功能是将消息M映射成一个长度较短且固定的值H(M),是一个明文到密文的不可逆映射,只有加密而没有解密过程。函数如下:

其中,value是一个定长的数值,作为输入value1和value2的哈希值。value的特点是,如果value1或者value2中有一个值发生了变化,那么它的数值将会与原来完全不一致,而且这种不一致的变化是没有任何规律可言的。同时,我们也不可能根据value的值反推出value1和value2的数值。哈希函数的特点保证了对于任意的两个输入组合,都有唯一的输出数值与之对应,这个特性可以用于校验输入函数参数的性质。

        

 

原因:学习区块链相关的内容的时候发现Merkle tree和hash不是很了解。

先讲解一下hash的介绍:

无论输入是什么数字格式、文件有多大,输出都是固定长度的比特串。以比特币使用的Sh256算法为例,无论输入是什么数据文件,输出就是256bit

         哈希算法:“单向加密”,是指丢掉一部分信息的加密算法。

 

二、Merkle Tree

Merkle tree看起来像是二叉树,是一个满二叉树(每一个层的结点数都达到最大值的二叉树),一棵Merkle树的结构如下:

红色的是根结点,灰色的是非叶子结点,黄色的是叶子结点。叶子结点的数值是直接根据数据块的值与0作为参数,经过Hash运算得来的,而灰色结点的值是以两个孩子结点的hash值作为输入,经过Hash运算得来的。一般的方法图

一棵Merkle树有如下特点:

  1. 叶子结点的值是实际数据块的Hash值。
  2. 每个非叶子结点的值,都是孩子结点的Hash值。根结点称为Merkle根
  3. 如果树是二叉树的话,称为二叉Merkle树,且二叉Merkle树一定是满二叉树(奇数叶子凑成偶数个,如果出现需要处理的数据块是奇数个,只需要把这些数据块中的任意一个复制一份凑成偶数个就行,一般选择复制最后一个块。

很自然的,我们会想到一个问题,为什么使用Merkle树,而不是直接把所有叶子结点经过一次Hash计算之后,直接给出结论?比如像上面的介绍图中,共有16个叶子结点,那么总共需要进行16Hash运算即可:

假设A将上面的Root发给下一个人B之后,A需要向B证明M6没有被修改过,那么需要将M6到M15的数据都发送给B,B则需要将这些数据重新进行Hash计算来验证正确性,操作的复杂度是O(n),验证的复杂度高,同时应该明白系统验证的次数应该会远远高于计算的次数。

相反如果使用Merkle树来进行记录:

当需要验证M6没有被篡改过,A只需要将图中标蓝色的节点数据发给B就行,在二叉树的情况下,它的计算复杂度仅仅是,其中m是数据块的个数。

Merkle Tree的整体结构看上去如下图:

Merkle树大多用来进行完整性验证,比如分布式环境下,从多台主机获取数据,怎么验证获取的数据是否正确呢,只要验证Merkle树根哈希一致,即可。例如,下图中L3数据块发生错误(比如数据被修改了),错误会传导到计算hash(L3),接着传导到计算hash(Hash1-0+Hash1-1),最后传导到根哈希,导致根哈希的不一致,可以说,任何底层数据块的变化,最终都会传导到根哈希。另外如果根哈希不一致,也可以通过Merkle树快速定位到导致不一致的数据。

Merkle树还可以用来对数据进行快速比对,快速定位到不一致的数据。比如分布式存储中,一份数据会有多个副本,并且分布在不同的机器上。为了保持数据一致性,需要进行副本同步,而首要的就是比对当前副本是否一致,如一致,则无需同步,如不一致,还需找出不一致的地方,然后进行同步。很明显,如果采用直接传输数据进行比对,非常低效,一般采用对数据进行哈希,传输哈希值进行对比的方法。为此,可以对每台机器需要比对的数据构造Merkle树,如果根哈希一致,则数据相同,如果根哈希不一致,则通过Merkle树快速检索到不一致的数据。下面举例说明快速检索的过程,如上图蓝色标注所示。假设两台机器中L3数据块不一致,我们对比根哈希,发现根哈希不一致,即,数据不一致,此时需要找出是那一块不一致,分别对比Hash0Hash1,发现是Hash1不一致,接着向下发现是Hash1-0不一致,这样就定位到是L3数据块不一致。定位过程的算法复杂度为O(log(n))

还有一种数据结构,在一定程度上可以看做是Merkle树的子树,但又不完全一样,这个数据结构是Hash list(为了避免中文哈希列表与哈希表的误解,这里使用英文名称),我们下面看一下这个Hash list

三、Hash list

    在点对点网络中数据传输的时候,为了提高效率往往会同时从多个机器下载数据的不同部分,即,不是从一台机器下载整个数据,而是将完整数据分成不同的部分,分别同时从不同的机器获取完整数据的不同组成部分。这样分块传输不但可以同时从多台机器下载数据,另一个好处是如果这一小块数据传输过程中损坏了,只要重新下载这一小数据块就可以了,不用重新下载整个数据。

但这种分布式环境下,很多机器应该认为是不稳定或者不可信的,如何校验整个数据的完整性及每一小数据块的完整性呢?

为了校验每一个数据块,我们需要对每个数据块做哈希,形成一个哈希列表,这样进行下载前,我们先要获取一个哈希列表,下载后,我们就能够通过哈希列表,来验证每一个数据块。哪怎么保证这个哈希列表是正确的呢,或者说怎么校验完整数据呢?只要每一个数据块哈希是正确的,最终获取的完整数据就一定是正确的,所以,我们需要对哈希列表进行哈希得到根哈希,将此根哈希放到一个可信源中,在下载数据前,先从可信数据源哪里获取到数据的跟哈希,然后从任意机器获取哈希列表,再下载数据块。这样,数据完整性可以通过根哈希来保证。

 

以上都是来源于网络,我只是将其整合了一下。更加容易方便的阅读。

 

  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值