区块连中的密码学--SHA256实现机制

区块连中的密码学–SHA256实现机制

摘要

本文主要介绍区块链中所使用的密码学知识,同时因为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函数的抗碰撞性特点,数字摘要可以解决确保内容未被篡改过的问题。

SHA-256

对于任意长度的消息,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 = σ 1 ( W t − 2 ) + W t − 7 + σ 0 ( W t − 15 ) + W t − 16 .   S n 表 示 循 环 右 移 n 位 , R n 表 示 右 移 n 位 σ 0 ( x ) = S 7 ( x ) ⨁ S 18 ( x ) ⨁ R 3 ( x ) σ 1 ( x ) = S 17 ( x ) ⨁ S 19 ( x ) ⨁ R 10 ( x ) 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)\\ Wt=σ1(Wt2)+Wt7+σ0(Wt15)+Wt16. SnnRnnσ0(x)=S7(x)S18(x)R3(x)σ1(x)=S17(x)S19(x)R10(x)
即最后我们得到,n个含有64个经过位移的字的块。接下来我们使用得到的字进行循环加密。对于每一个Map(H_i-1) = H_i,每一个映射包含64次加密循环,每t次加密都使用第i-1个块得到的t个字进行加密。具体加密如下图:
转自https://blog.csdn.net/u011583927/article/details/80905740

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位摘要。

附录部分为python实现SHA256加密机制和实验结果
数字签名

数字签名是密码学理论的一个重要分支,其实现过程一般是由信息的发送者通过一个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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值