本文主要介绍区块链中所使用的密码学知识,同时因为Hash函数是区块链中重要的一环,因此也使用python3对SHA256进行了实现。
关于区块链的定义,广义来讲:区块链技术是 利用块链式数据结构 来验证与存储数据、 利用分布式 节点公式算法来生成和更新数据、 利用密码学 的方式保证数据传输和访问的安全、 利用由自动化脚本代码 组成的智能合约来编程和操作数据的一种全新的分布式基础架构与计算范式。狭义来讲:区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构,并以密码学方式保证的不可篡改和不可伪造的分布式账本。我们对此做一个总结,可以发现区块链中有四项不可缺的核心技术,分别是分布式存储、共识机制、密码学原理和智能合约。本文将主要从密码学的角度来解析区块链技术。
中本聪(Satoshi Nakamoto)的《比特币:一种点对点的电子现金系统》(Bitcoin: A Peer-to-PeerElectronic Cash System)中提到的交易过程:一枚电子货币是这样的 一串数字签名 ,每一位所有者通过对前一次交易和下一位拥有者的公钥签署一个随机Hash的数字签名, 即每一个区块里都包含两个hash值,一个是上个区块的Hash值,另一个是当前区块的Hash值 ,并将这个签名附加在这枚电子货币的末尾,电子货币就发送给了下一位所有者。而收款人通过对签名进行校验,就能够验证该链条的所有者。这里就涉及了非对称加密算法以及数字签名技术。比特币系统当中,Hash和签名是结合起来用的,一般是对一个massage取哈希,再对这个哈希值签名。 只要Hash值里面任何内容有改动,Hash值都会变,比如现在有100个区块,有人改了第53个,那么54到100的区块也都要跟着变动,也就是说54到100的区块的拥有者要去做改动,而且必须得到超过50%的区块拥有者的同意,大家才会把你改动的信息同步下来。
比特币系统中的账户管理:在日常生活中,如果想要开一个账户,我们需要带上证件去银行办理开户手续,这就是中心化系统的账户管理方式。比特币是去中心化的,没有类似于银行的机构。用户自己可以决定是否开户,不需要任何人批准。开户的过程是在本地创立一个公钥,私钥的对,这个公私钥对就代表了一个账户。
非对称密码学由一对不同的公钥和私钥对组成,如果用公钥对数据进行加密则只能用对应的私钥才能进行解密,反之如果用私钥进行加密,那么只有用对应的公钥去进行解密。目前常见的非对称密码算法有RSA算法、ECC、Diffie-Hellman算法等。大多数区块链平台采用ECC算法和RSA算法来进行数字签名。
在比特币系统中,创立账号只需要一对公私钥,公钥可以理解为银行账户,而私钥则是账户的密码,密码是只有你自己知道的,别人给你转账时只需要知道你的公钥。假设这样一个场景:某一天,小A转了10个比特币给小B,然后广播到区块链上,那其他人怎么知道这笔交易确实是小A操作的呢,会不会是有其他人冒名顶替?这时候就需要用到公私钥了,为了解决这个问题,小A需要在发布交易的时候用自己的私钥对这笔交易进行签名,其他人收到交易的信息之后用小A的公钥验证这笔交易签名的正确性,来确定这笔交易就是小A操作的。
Hash算法是非常基础也非常重要的计算机算法,它能将任意长度的二进制明文串映射为较短的二进制串即Hash值,并且不同的明文很难映射为相同的Hash值。
Hash值在应用中又常被称为指纹或摘要。Hash算法的核心思想也经常被应用到基于内容的编址或命名算法中。目前常用的哈希函数为SHA256。一个优秀的Hash算法将能实现如下功能:
正向快速:给定明文和Hash算法,在有限时间和有限资源内能计算得到Hash值;
逆向困难:给定(若干)Hash值,在有限时间内很难(基本不可能)逆推出明文;
输入敏感:原始输入信息发生任何改变,新产生的Hash值都应该出现很大不同;
冲突避免:很难找到两段内容不同的明文,使得它们的Hash值一致(发生碰撞)。
比特币挖矿的过程就是基于逆向困难的原理。挖矿实际上就是找一个随机数nonce,它和区块块头中的信息合在一起作为输入取哈希,使得得出的哈希满足某一个条件。由于只能一个一个随机数去试,因此挖矿的过程才能用来作为工作量证明(proof of work)。虽然挖矿的过程需要很大的工作量才能找到符合条件的nonce,但是一旦有一个人找到了这个nonce,将它公布出去后,其他人要验证它是否符合要求很容易的,只需要进行一次哈希运算就可以了,这一性质叫做difficult to solve,but easy to verify 。SHA256算法可以很好的满足区块连的要求。
Hash算法并不是一种加密算法,不能用于对信息的保护。但Hash算法常用于对口令的保存上。例如用户登录网站需要通过用户名和密码来进行验证。如果网站后台直接保存用户的口令明文,一旦数据库发生泄露后果不堪设想。利用Hash的特性,后台可以仅保存口令的Hash值,这样每次比对Hash值一致,则说明输入的口令正确。即便数据库泄露了,也无法从Hash值还原回口令,只有进行穷举测试。
数字摘要是对数字内容进行Hash运算,获取唯一的摘要值来指代原始完整的数字内容。数字摘要是Hash算法最重要的一个用途。利用Hash函数的抗碰撞性特点,数字摘要可以解决确保内容未被篡改过的问题。
对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示
SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。 信息的预处理分为两个步骤:附加填充比特和附加长度
填充比特:在报文末尾进行填充,使报文长度在对512取模以后的余数是448,先补第一个比特为1,然后都补0,直到长度满足对512取模后余数是448。需要注意的是,信息必须进行填充,也就是说,即使长度已经满足对512取模后余数是448,补位也必须要进行,这时要填充512个比特。余数为448的原因是,附加长度部分会附加上一个64bit的数据,用来表示原始报文长度,448+64=512,因此余数选择448可以刚好拼凑成一个完整的块。
附加长度:将原始数据的长度信息补到已经进行了填充操作的消息后面。 因此,通过SHA256计算的消息长度必须要小于2的64次方
首先将消息分解成512bit大小的块,若消息M可以被分解成n个块,那么整个算法也就需要迭代n次,最后的结果就是256bit的数字摘要。一个256-bit的摘要的初始值H_0,经过第一个数据块进行运算,得到H_1,即完成了第一次迭代,H_1经过第二个数据块进行运算得到H2,以此类推依次处理,最后得到H_n,H_n即为最终的256-bit消息摘要,表达为式子则为: Map(H_i-1) = H_i。期中每一个H被划分为8个小块,因为SHA256算法中的最小运算单元为字,即32bit。H_0的初始值则为前八个质数的平方根的小数部分取前32bit得来。
对于每一块,首先我们要构造64个字,块的大小为512比特,可以分解为16个32bit的字,记为w[0], w[1], … w[15],前16个字直接由消息的第i个块分解来得到。其余字如下迭代生成:
W_t = \sigma_1(W_{t-2}) + W_{t-7} + \sigma_0(W_{t-15}) + W_{t-16}. \ S^n表示循环右移n位,R^n表示右移n位\\ \sigma_0(x)=S^7(x)\bigoplus S^{18}(x)\bigoplus R^3(x)\\ \sigma_1(x) = S^{17}(x)\bigoplus S^{19}(x)\bigoplus R^{10}(x)\\
W
t
=
σ
1
(
W
t
−
2
)
+
W
t
−
7
+
σ
0
(
W
t
−
1
5
)
+
W
t
−
1
6
.
S
n
表
示
循
环
右
移
n
位
,
R
n
表
示
右
移
n
位
σ
0
(
x
)
=
S
7
(
x
)
⨁
S
1
8
(
x
)
⨁
R
3
(
x
)
σ
1
(
x
)
=
S
1
7
(
x
)
⨁
S
1
9
(
x
)
⨁
R
1
0
(
x
)
即最后我们得到,n个含有64个经过位移的字的块。接下来我们使用得到的字进行循环加密。对于每一个Map(H_i-1) = H_i,每一个映射包含64次加密循环,每t次加密都使用第i-1个块得到的t个字进行加密。具体加密如下图:
ABCEDFGH的初始值为H_0,即A = 0x6a09e667, B = 0xbb67ae85, C = 0x3c6ef372, D = 0xa54ff53a, E = 0x510e527f, F = 0x9b05688c, G = 0x1f83d9ab,H = 0x5be0cd19. :
KaTeX parse error: Undefined control sequence: \and at position 95: …Ch(x,y,z) = (x \̲a̲n̲d̲ ̲y) \bigoplus(\o…
最后一次循环将8个字拼接起来,即是第i块对应的Hash。一共做n次得到最后的256位摘要。
数字签名是密码学理论的一个重要分支,其实现过程一般是由信息的发送者通过一个Hash函数对要传送的信息进行Hash计算之后产生其他人无法伪造的一段数字,同时接收者用发送者的公钥对所接收到的用私钥加密的消息进行解密后,从而来保证消息的完整性和真实性的一种算法。 自此,区块链的安全性完全依赖于数字签名技术的安全性,即ECC算法和RSA算法等基于三类数学问题的难解性:大整数分解问题、离散对数问题以及椭圆曲线问题。限于当今计算机能力的限制,目前还没有能完全攻克他们的算法,所以 当前来说 是较为安全的。
一个典型的场景是,Alice通过信道发给Bob一个文件,Bob如何获知所收到的文件即为Alice发出的原始版本?Alice可以先对文件内容进行摘要,然后用自己的私钥对摘要进行签名,之后同时将文件和签名都发给Bob。Bob收到文件和签名后,用Alice的公钥来解密签名,得到数字摘要,与收到文件进行摘要后的结果进行比对。如果一致,说明该文件确实是Alice发过来的(别人无法拥有Alice的私钥),并且文件内容没有被修改过(摘要结果一致)。[4]
对于非对称加密算法和数字签名来说,很重要的一点就是公钥的分发。理论上任何人可以公开获取到对方的公钥。然而这个公钥有没有可能是伪造的呢?传输过程中有没有可能被篡改掉呢?一旦公钥自身出了问题,则整个建立在其上的安全体系的安全性将不复存在。
数字证书机制正是为了解决这个问题,它就像日常生活中的一个证书一样,可以证明所记录信息的合法性。比如证明某个公钥是某个实体(如组织或个人)的,并且确保一旦内容被篡改能被探测出来,从而实现对用户公钥的安全分发。根据所保护公钥的用途,可以分为加密数字证书和签名验证数字证书。前者往往用于保护用于加密信息的公钥;后者则保护用于进行解密签名进行身份验证的公钥。两种类型的公钥也可以同时放在同一证书中。
一般情况下,证书需要由证书认证机构(Certification Authority,CA)来进行签发和背书。权威的证书认证机构包括DigiCert、GlobalSign、VeriSign等。用户也可以自行搭建本地CA系统,在私有网络中进行使用。
import math h_0 = 0x6a09e667 h_1 = 0xbb67ae85 h_2 = 0x3c6ef372 h_3 = 0xa54ff53a h_4 = 0x510e527f h_5 = 0x9b05688c h_6 = 0x1f83d9ab h_7 = 0x5be0cd19 K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2] H0 = [h_0, h_1, h_2, h_3, h_4, h_5, h_6, h_7] def preprocessing(m=None): if m is None: M = input('please input the message\n') else: M = m # 1byte=8bit,L为M字符串长度 L = 8 * len(M) m=0 for ch in M:#遍历字符串M m = m * (2 ** 8) + ord(ch) # print(hex(m))#此时16进制的int类型m就是原始数据 #补位,使明文总长度为448(mod512)位 n = 1 if L % 512 < 448: m = m * 2 + 1 #补位 # 添加填充位 m = m * 2 ** (447 - L % 512) # 添加长度 m = m * 2 ** 64 + L else: m = m * 2 + 1 #补位 # 添加填充位 m = m * 2 ** (512 - L % 512 + 448) # 添加长度 m = m * 2 ** 64 + L n = math.ceil((L + 64 + 512 - L % 512 + 448) / 512) return bin(m), n def S(w, n): w_t = w.copy() for i in range(0, len(w)): index = (i + n) % len(w) w[index] = w_t[i] return w def R(w, n): w_t = w.copy() for i in range(0, len(w)): if i < n: w[i] = '0' else: w[i] = w_t[i - n] return w def XOR(w1, w2): w = w1.copy() for i in range(0, len(w)): if w1[i] != w2[i]: w[i] = '1' else: w[i] = '0' return w def AND(w1, w2): w = w1.copy() for i in range(0, len(w)): if w1[i] == w2[i] and w1[i] == '1': w[i] = '1' else: w[i] = '0' return w def inverse(w): for i in range(0, len(w)): if w[i] == '1': w[i] = '0' else: w[i] = '1' return w def sigma1(w): w = XOR(XOR(S(w, 17), S(w, 19)), R(w, 10)) return w def sigma0(w): w = XOR(XOR(S(w, 7), S(w, 18)), R(w, 3)) return w def Ch( x, y, z): return XOR(AND(x, y), AND(inverse(x), z)) def Ma(x, y, z): return XOR(XOR(AND(x, y), AND(x, z)), AND(y, z)) def add(w1, w2): c = 0 w = w1.copy() for i in range(0, len(w)): sum = int(w1[len(w) - 1 - i]) + int(w2[len(w) - 1 - i]) + c if sum == 0: w[len(w) - 1 - i] = '0' c = 0 if sum == 1: w[len(w) - 1 - i] = '1' c = 0 if sum == 2: w[len(w) - 1 - i] = '0' c = 1 if sum == 3: w[len(w) - 1 - i] = '1' c = 1 return w def make_64words(message): W = [0] * 64 m = [] #将message从01字符串转化为01字符串list,方便后续做循环移位操作 for i in range(0, len(message)): m.append(message[i]) message = m for i in range(0, 16): W[i] = message[i*16:(i+1)*16] for t in range(16, 64): W[t] = add(add(sigma1(W[t-2]), W[t-7]), add(sigma0(W[t-15]), W[t-16])) return W def list_to_int(W): w = '0b' for w_t in W: w += w_t return int(w,2) def int_to_list(H): H = bin(H) t = [] for i in range(2, len(H)): t.append(H[i]) return t def mod2_32(x, y): return (x+y)%math.pow(2, 32) def encryption(W, H_init=H0): H_new = H_init.copy() H_i = H_init.copy() for i in range(0, 64): C = (H_i[4] & H_i[5]) ^ (~H_i[5] & H_i[6]) t = mod2_32(list_to_int(W[i]), K[i]) r1 = mod2_32(mod2_32(C, H_i[7]),t) S1 = list_to_int(sigma1(int_to_list(H_i[4]))) r2 = mod2_32(r1, S1) M = (H_i[0] & H_i[1]) ^ (H_i[0] ^ H_i[2]) ^ (H_i[1] ^ H_i[2]) r3 = mod2_32(M, r2) S0 = list_to_int(sigma0(int_to_list(H_i[1]))) H_new[0] = int(mod2_32(S0, r3)) H_new[1] = int(H_i[0]) H_new[2] = int(H_i[1]) H_new[3] = int(mod2_32(H_i[2], r2)) H_new[4] = int(H_i[3]) H_new[5] = int(H_i[4]) H_new[6] = int(H_i[5]) H_new[7] = int(H_i[6]) H_i = H_new return H_i def SHA256(m=None): message, n = preprocessing(m) #第一个512bit块 W = make_64words(message[2+0:2+512])#去掉字符串中0b H_i = encryption(W) #对H_i进行迭代 for i in range(1, n): W = make_64words(message[2+i*512:2+(i+1)*512]) H_i = encryption(W, H_i) H = '' for h in H_i: for i in range(0, 32 - len(bin(h)[2:])): H += '0' H += bin(h)[2:] print("The Hash value:" + hex(int(H,2))) if __name__ == '__main__': SHA256()
输入:明天我就要回家了,记得要叫我起床啊
返回:0xde3f42d7de3f42d7de3f42d78a69a6f18a69a6f18a69a6f18a69a6f18a69a6f1
输入:I’ve seen the world. Done it all, Had my cake now返回:0x5aeb5ad05aeb5ad05aeb5ad0835d5b8f835d5b8f835d5b8f835d5b8f835d5b8f
Reference
[1]meizi57, 《带你揭开区块链中密码学的神秘面纱》,2018-06-13 https://blog.csdn.net/zhaowulingwang/article/details/80677881
[2]小震同学,《区块链学习笔记—比特币中用到的密码学原理》,2019-08-03,https://blog.csdn.net/Curry_On/article/details/98374825
[3]中本聪,《比特币:一种点对点的电子现金系统》
[4]RonTech,《区块链-密码学与安全技术》,2017-11-29 https://blog.csdn.net/zyhlwzy/article/details/78667632
[5]随煜而安《SHA256算法原理详解》,2018-07-03 https://blog.csdn.net/u011583927/article/details/80905740
区块连中的密码学–SHA256实现机制摘要本文主要介绍区块链中所使用的密码学知识,同时因为Hash函数是区块链中重要的一环,因此也使用python3对SHA256进行了实现。一、什么是区块链关于区块链的定义,广义来讲:区块链技术是利用块链式数据结构来验证与存储数据、利用分布式节点公式算法来生成和更新数据、利用密码学的方式保证数据传输和访问的安全、利用由自动化脚本代码组成的智能合约来编程和操... SHA256是SHA-2下细分出的一种算法 SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。 SHA-2下又可再分为六个不同的算法标准 包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/2...区块链是随着比特币等数字加密货币的日益普及而逐渐兴起的一种全新技术,它提供了一种去中心化的、无需信任积累的信用 建立范式,目前已经引起金融行业、科研机构、政府部门和投资公司的高度重视与广泛关注。区块链技术通过建立一个共同维护且不可被篡改的数据库来记录过去的 所有交易记录和历史数据,所有的数据都是分布式存储且公开透明的。在这种技术下,任何互不相识的网络用户都可以通过合约、点对点记账、数字加密...一、区块链本质上是一个对等网络(peer-to-peer)的分布式账本数据库。 二、区块链本身其实是一串链接的数据区块,其链接指针是采用密码学哈希算法对区块头进行处理所产生的区块头哈希值。 三、基本概念 1、 数据区块: 比特币的交易会保存在数据区块中,大约每10分钟会产生一个区块,每个数据区块一般包括区块头(Header)和区块体(Body)两部分。 区块...由于研究需要,我们计算了SHA-256和AES-256的计算时间开销,下面将代码贴在下方。 需要注意的是,我们使用System.nanoTime()方法,获取的时间戳的单位是纳秒。此外,我们循环计算了1000次求其平均值,由于第一次的时间开销明显过大,我们将其抛弃。 SHA-256 import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.Arrays; public cla最近,在项目中,需要计算文件的hash值来对文件进行最终校验,在C#中,MD5、SHA256都是直接可用的。下面以MD5为例, 一般来说,计算文件hash值时,是加载一个文件,然后来读取并计算,如下: MD5 md = MD5.Create(); buffer = Encoding.ASCII.GetBytes("abc");//这里abc表示从文件中读取的内容 md.TransformBl...对称加密算法(Symmetric Cryptography)简单的说就是:我有一个密钥,我把密钥告诉我要通信的人。 然后我用这个密钥将明文信息加密成密文,发送给接收人,接收人收到信息后,使用我提供的密钥将密文解密成明文。对称加密的优点: - 高速度 - 使用长密钥时的难破解性缺点: - 密钥的数量 - 密钥传输的不安全性 - 我们来简单算一算,假如公司有n个员工,每两个员工之间通信的密钥学习视频来自:北京大学计算机系肖臻区块链学习视频 02 BTC密码学原理 1.比特币加密算法一共有两类:非对称加密算法(椭圆曲线加密算法)和哈希算法(SHA256,RIMPED160算法)。 公钥和私钥(encyption key)由椭圆曲线加密算法生成,私钥可推出公钥而反之不能。 【重点】: 有了私钥,你就可以对文本签名。别人拿了你的公钥就可以根据签名认证你是否拥有私钥。这就是证明你拥有存款的办法。 为了安全起见,公钥应该隐藏起来。所以对公钥进行哈希加密,生成公钥哈希值然后计算哈希值的比特币地址: 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,使其只能在输入相应的密钥之后才能显示出原容,本篇会介绍各种加密算法。 第一类(SHA算法):根据明文签名进行加密得到密文,而密文不能被反推出来,而这种在银行用得很多,例如下图 SHA hash独有得算法,算法可以有多种,根据每个人来算出来 第二类(DES AES):明文得到密文,通过密文;然后服务端得到密文进行反推出来,一把钥匙 第三类(RSA):叫做RSA算法加密,公钥..1. 前言 SHA系列算法是一种密码散列函数,由美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。现在已经被破解。 我们本文主要研究SHA256算法。 2. 什么是SHA ? SHA算法的名称是安全散列算法,英文名称是Secure Hash Algorithm。 SHA算法分为很多版本。可以分为SHA-1和SHA-2两大类。其中SHA-2的子版...1、算法概述 数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法或散列算法。 1.1 CRC8、CRC16、CRC32 CRC(Cyclic Redundancy Check,循环冗余校验)算法出现时间较长,应用也十分广泛,尤其是通讯领域,现在应转载来自于 《基于FPGA的SHA-256算法实现》和 http://www.cnblogs.com/tofixer/p/3498048.html SHA-256 算法输入报文的最大长度不超过2^64 bit,输入按512-bit 分组进行处理,产生 的输出是一个256-bit 的报文摘要。该算法处理包括以下几步: STEP1:附加填充比特。对报文进行填充使报文长度与448 模5