区块链中的密码学技术——哈希算法、Merkle树、公钥密码算法

本文是学习区块链技术中关于密码学这一部分的相关知识点学习总结整理。

哈希算法

哈希函数(散列函数)定义

公式表示形式:

h = H ( m )

函数说明:
m :任意长度消息(不同算法实现,长度限制不同,有的哈希函数(SHA-3)不限制消息长度,有的限制(SHA-2),但即使有限制其长度也非常大,可以认为是任意长度消息)
H :哈希函数
h :固定长度的哈希值

典型的散列函数都有非常大的定义域,比如SHA-2最高接受( 2 64 1 ) / 8 长度的字节字符串。同時散列函數一定有着有限的值域,比如固定长度的比特串(例如:256,512)。在某些情况下,散列函数可以设计成具有相同大小的定义域和值域间的單射。

相关概念

  • 哈希函数定义——密码哈希函数是一类数学函数,可以在有限合理的时间内,将任意长度的消息压缩为固定长度的二进制串,其输出值称为哈希值,也称散列值。
  • 碰撞定义——是指两个不同的消息在同一哈希函数作用下,具有相同的哈希值。
  • 哈希函数的安全性——是指在现有的计算资源(包括时间、空间、资金等)下,找到一个碰撞是不可行的。
  • 抗弱碰撞性——对于给定的消息 M 1 ,要发现另一个消息 M 2 ,满足 H ( M 1 ) = H ( M 2 ) 在计算上是不可行的。
  • 抗强碰撞性——找任意一对不同的消息 M 1 M 2 ,使 H ( M 1 ) = H ( M 2 ) 在计算上是不可行的。
  • 雪崩效应——当一个输入位发生变化时,输出位将有一半会发生变化。

下图形象的说明了哈希函数:
这里写图片描述

哈希算法就是以哈希函数为基础构造的,常用于实现数据完整性和实体认证。一个优秀的 hash 算法,将能实现:

  • 正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
  • 逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
  • 输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
  • 冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。

哈希函数的性质

这里写图片描述

抗碰撞性

哈希函数的抗碰撞性是指寻找两个能够产生碰撞的消息在计算上是不可行的。但找到两个碰撞的消息在计算上不可行,并不意味着不存在两个碰撞的消息。哈希函数是把大空间上的消息压缩到小空间上,碰撞肯定存在。只是计算上是不可行的。例如,如果哈希值的长度固定为256位,显然如果顺序取 1 , 2 , , 2 256 + 1 2 256 + 1 个输入值,计算它们的哈希值,肯定能够找到两个输入值,使得它们的哈希值相同。

原像不可逆

原像不可逆,指的是知道输入值,很容易通过哈希函数计算出哈希值;但知道哈希值,没有办法计算出原来的输入值。

难题友好性

难题友好性指的是没有便捷的方法去产生一满足特殊要求的哈希值。

一个哈希函数 H 称为难题友好的,如果对于每个 n 位的输出 y ,若 k 是从一个具有较高不可预测性(高小熵)分布中选取的,不可能以小于 2 n 的时间找到一个 x ,使 H ( k | | x ) = y

为了引申出工作量证明POW的原理,考虑一个由哈希函数构成的解谜问题:已知哈希函数 H ,一个高小熵分布的值 v a l u e 以及目标范围 Y ,寻找 x ,使得 H ( v a l u e | | x ) Y

这个问题等价于需要找到一个输入值,使得输出值落在目标范围 Y 内,而 Y 往往是所有的输出值的一个子集。实际上,如果一个哈希函数 H 的输出位 n 位,那么输出值可以是任何一个 0 ~ 2 n 范围内的值。预定义的目标范围 Y 的大小决定了这个问题的求解难度。如果 Y 包含所有 n 比特的串,那么问题就简单了,但如果 Y 只包含一个元素,那么这个求解是最难的,相当于给定一个哈希值,找出其中一个原像,原像不可逆的性质说明了这个难度。事实上,由于 v a l u e 具有高小熵分布,这确保了除了随机尝试 x 值以完成搜寻那个很大的空间外,没有其他有效的途径了。

哈希函数的难题友好性构成了基于工作量证明的共识算法的基础。通过哈希运算得出的符合特定要求的哈希值,可以作为共识算法中的工作量证明。这里比特币的安全保证依赖于哈希函数的安全性,如果哈希函数被攻破,可以想象POW共识算法就失效了,不用算力达到 51 % 就可以攻击了。

小熵(min-entropy)是信息理论中衡量某个结果的可预测性的一个指标。高小熵值的是变量呈均匀分布(随机分布)。如果我们从对分布的值进行随机抽样,不会经常抽到一个固定的值。例如,如果在一个128位的数中随机选一个固定的数 n ,那么选到该数的几率是 1 / 2 128

典型哈希函数

SHA256

SHA256属于SHA(Secure Hash Algorithm,安全哈希算法)家族一员,是SHA-2算法簇中的一类,对于小于 2 64 位的消息,产生一个256位的消息摘要。

SHA-256其计算过程分为两个阶段:消息的预处理和主循环。在消息的预处理阶段,主要完成消息的填充和扩展填充,将所有输入的原始消息转换为 n 个512比特的消息块,之后对每个消息块利用SHA256压缩函数进行处理。下面讲述的是如何计算Hash值,目前还没有完全理解,列在这里是为了有个宏观的概念,大致知道是什么回事,以后需要的时候再深入学习理解。

SHA256计算步骤:

step1: 附加填充比特。对报文进行填充使报文长度 n ( 448   m o d   512 ) ,填充比特数范围是1到512,填充比特串的最高位为1,其余位为0。(448=512-64,为了下面的64位)

step2 : 附加长度值。将用64-bit表示初始报文(填充前)的位长度附加在step1的结果后(低字节位优先)。

step3: 初始化缓存。使用一个256bit的缓存来存放该哈希函数的中间值及最终结果。
缓存表示为:A=0x6A09E667 , B=0xBB67AE85 , C=0x3C6EF372 , D=0xA54FF53A,
E=0x510E527F , F=0x9B05688C , G=0x1F83D9AB , H=0x5BE0CD19

step4: 处理512bit(16个字)报文分组序列。该算法使用了六种基本逻辑函数,由64步迭代运算组成。每步都以256-bit缓存值ABCDEFGH为输入,然后更新缓存内容。每步使用一个32-bit 常数值Kt 和一个32-bit Wt。Kt是常数值,在伪代码中有它的常数值定义。Wt是分组之后的报文,512 bit=32bit*16,也就是Wt t=1,2..16由该组报文产生。Wt t=17,18,..,64由前面的Wt按递推公式计算出来。Wt递推公式在下面的伪代码有。
这里写图片描述

step5 :所有的512-bit分组处理完毕后,对于SHA-256算法最后一个分组产生的输出便是256-bit的报文摘要。
这里写图片描述

SHA256计算流程

这里面公式太多,就直接截图了。
这里写图片描述
这里写图片描述
这里写图片描述

伪代码实现

可参考https://en.wikipedia.org/wiki/SHA-2

RIPEMD160

RIPEMD (RACE Integrity Primitives Evaluation Message Digest,RACE原始完整性校验讯息摘要)是一种加密哈希函数。RIPEMD-160是以原始版RIPEMD所改进的160位元版本,而且是RIPEMD系列中最常见的版本。更多请参考:https://homes.esat.kuleuven.be/~bosselae/ripemd160.html

哈希函数在比特币中的应用

在比特币中,应用了两个密码学哈希函数,一个是SHA256,另一个是RIPEMD160,用于比特币地址的生成。下图为比特币地址(账户)的生成流程:
这里写图片描述

  1. 通过随机数发生器生成一个256bit的随机数,并使用该随机数作为账户的私钥。
  2. 比特币采用椭圆曲线签名算法(ECDSA)来对数据进行签名和验证,具体使用的是secp256k1曲线。通过ECC乘法可以计算出对应的公钥。
  3. 对公钥进行两次散列运算,得到公钥的散列值。
  4. 公钥散列值加上版本号和校验码后,进行base58编码可得到地址

Merkle树

哈希指针链

哈希指针是一种数据结构,哈希指针指示某些信息存储在何处,我们将这个指针与这些信息的密码学哈希值存储在一起。哈希指针不仅是一种检索信息的方法,同时它也是一种检查信息是否被修改过的方法。
这里写图片描述
上面的图表示了一个哈希指针,哈希指针是一个指向存储地点的指针,加上一个针对存储时信息的哈希值。

区块链就可以看作一类使用哈希指针的链表。这个链表链接一系列的区块,每个区块包含数据以及指向表中前一个区块的指针。区块链中,前一个区块指针由哈希指针所替换,因此每个区块不仅仅告诉前一个区块的位置,也提供一个哈希值去验证这个区块所包含的数据是否发生改变。
这里写图片描述

Merkle哈希树

Merkle哈希树是一类基于哈希值的二叉树或多叉树,其叶子节点上的值通常为数据块的哈希值,而非叶子节点上的值,是将该节点的所有子节点的组合结果的哈希值。
这里写图片描述
Merkle树一般用来进行完整性验证处理。在处理完整性验证的应用场景中,Merkle树会大大减少数据的传输量及计算的复杂度。

成员证明。如果想要证明一个确切的数据块是Merkle树中的一员。通常,只需要树根及这个区块和通向树根沿途的中间哈希值,就可以暂时忽略树的其他部分,这些就已经足以让我们验证到树根。
这里写图片描述

区块链中的Merkle树是二叉树,如果在树上有 n 个节点,那么就只有 l o g ( n ) 个块需要被展示。因为每一个步骤都只需要计算下一级块的哈希,所以这大概只需要 l o g ( n ) 次去证明它。所以即使这个Merkle 树包含了非常多的块,我们依旧可以在一个较短的时间内证明一个成员块。


公钥密码算法

公钥密码体制(Public-key cryptography)

公钥密码体制的两个重要原则:

  • 要求在加密算法和公钥都公开的前提下,其加密的密文必须是安全的。
  • 要求所有加密的人和掌握私人密钥的解密人,他们的计算或处理都应比较简单,但对其他不掌握秘密密钥的人,破译应是极其困难的。

公钥密码算法简介

公钥密码算法中的密钥分为公钥和私钥,用户或系统产生一对密钥,将其中的一个公开,就是公钥,另一个自己保留,就是私钥。一般情况下,通信时,发送方利用公钥对信息进行加密,接收方利用私钥对信息进行解密完成通信。当然,也可用私钥加密,公钥解密。因为加密与解密用的是两个不同的密钥,所以这种算法也叫作非对称加密算法。

公钥密码系统的安全性都是基于难题的可计算问题。如:大数分解问题;计算有限域的离散对数问题;平方剩余问题;椭圆曲线的对数问题等。基于这些问题,就有了各种公钥密码体制。后面要讲的椭圆曲线密码算法是其中之一。

椭圆曲线密码算法

椭圆曲线密码算法(Elliptic Curve Cryptography,ECC)是基于椭圆曲线数学的一种公钥密码算法,其安全性依赖于椭圆曲线离散对数问题的困难性。

下面这3篇文章详细讲述了椭圆曲线密码算法的数学原理,不过是英文版的,但是讲述的非常详细,需要掌握的相关数学概念也讲述的很清楚。
http://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/
http://andrea.corbellini.name/2015/05/23/elliptic-curve-cryptography-finite-fields-and-discrete-logarithms/
http://andrea.corbellini.name/2015/05/30/elliptic-curve-cryptography-ecdh-and-ecdsa/
下面这2篇是上面文章的翻译:
http://blog.csdn.net/mrpre/article/details/72850598
http://blog.csdn.net/mrpre/article/details/72850644
这里理论不是很完善,具体的可深入学习Douglas R. Stinson的《密码学原理与实践》。

椭圆曲线密码算法优点

  • 短的密钥长度,意味着小的带宽和存储要求。
  • 所有的用户可以选择同一基域上的不同的椭圆曲线,可使所有的用户使用同样的操作完成域运算。

椭圆曲线定义

p 是一个大于3的素数,在有限域 F p 上的椭圆曲线 y 2 = x 3 + a x + b 由一个基于同余式 y 2 = x 3 + a x + b   m o d   p 的解集 ( x , y ) F p × F p 和一个无穷远点的特定点 O 组成,这里 a , b F p 是满足 4 a 3 + 27 b 2 0   m o d   p 的常数。

下图是显示了其中一种实际的椭圆曲线:
这里写图片描述

对椭圆曲线上的点,我们可以定义一种形式的加法:如果椭圆曲线上的三个点位于同一直线上,那么它们的和为 O (无穷远点)。

根据上面的定义导出椭圆曲线上的加法运算法则如下:
P Q 时:
这里写图片描述

P = Q 时:
这里写图片描述

下面的动画解释了为什么是切线:
这里写图片描述
随着两个点越来越接近,过这两点的直线最终变成了曲线的切线

上面用几何的形式解释了椭圆曲线上的加法法则,下面是数学表达式。设 P 1 = ( x 1 , y 1 ) P 2 = ( x 2 , y 2 ) 为椭圆曲线上的两个点,加减法运算如下:
1) O = O
2) P 1 = ( x 1 , y 1 )
3) O + P 1 = P 1
4) 若 P 2 = P 1 ,则 P 1 + P 2 = O
5) 若 P 2 P 1 ,则 P 1 + P 2 = ( x 3 , y 3 ) ,其中 x 3 = m 2 x 1 x 2 y 3 = m ( x 3 x 1 ) + y 1 这里写图片描述

椭圆曲线上点群的离散对数问题

给定椭圆曲线上的点 P 和点 Q ,寻找数 k ,使得 k P = Q ,其中 k 称为 Q 的基于 P 的离散对数。

在等式 k P = P + P + + P = Q 中,已知 k 和点 P ,求点 Q 比较容易,反之已知点 Q 和点 P ,求 k 却是相当苦难的,这个问题称为椭圆曲线上点群的离散对数问题。椭圆曲线密码体制正是利用这个困难问题设计的。在实际应用中, k 作为私钥,而 Q 作为公钥。

如何计算 k P = P + P + + P = Q

用这种形式表示时,计算 k P 似乎需要 k 次加法运算。如果 k n 个二进制位,那么算法的时间复杂度将为 O ( 2 n ) ,这真不是很好。存在一些更快的算法。其中一种是“加倍(double)与相加(add)”算法。计算的原理可以用一个例子来更好地解释。取 n = 151 。它的二进制表示形式为 10010111 2 。这一二进制表示形式可以转换为一系列 2 的幂之和。

(取 k 的 每个二进制位上的数字,并用它乘以一个 2 的幂.)
用这种方法,我们可以将 k 这样写:

“加倍(double)与相加(add)”算法需要这样做:
• 取 P .
• 加倍,得到 2 P .
2 P P 相加(为了得到 2 1 P + 2 0 P ).
• 加倍 2 P ,得到 2 2 P .
• 与前一结果相加 (得到 P 相加(为了得到 2 1 P + 2 0 P ).
• 加倍 2 P ,得到 2 2 P .
• 与前一结果相加 (得到

相关文章
相关标签/搜索