栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python: SHA256算法的实现和消息的哈希散列值计算

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python: SHA256算法的实现和消息的哈希散列值计算

目录
  • 1 SHA256
  • 2 实现原理
    • 2.1 消息预处理
    • 2.2 使用的常量和循环移位函数
    • 2.3 主循环
  • 3 结果
  • 4 对中文编码


1 SHA256

SHA256是SHA-2下的一个子算法,与之类似的还有SHA224、SHA384、SHA512,算法原理基本一致。

哈希算法通过对消息进行计算,生成一定长度的数据,称作消息摘要。SHA256能生成64*8=512 bits的消息摘要,每一个数据都可以当做一条消息的索引,这样能代表的数据就有2^512=13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096种可能,这个消息量已经足够大了。

另外,我们知道,能用一个摘要(索引)代表一条消息的前提是:没有其他消息的摘要与另一条不同消息的摘要相同,如果相同,称作碰撞。算法过于简单则会很容易发生碰撞,也就容易被破解。


2 实现原理

一些原理和伪代码可以参考这篇文章

2.1 消息预处理

消息预处理成长度是512bits的倍数。首先需要对消息进行至少一次的填充,先在消息后附加8比特的b10000000,然后填充0至长度模512余448。再填充64bits的长度,这样总长度就是512的倍数了。
计算长度时直接让长度值左移3位快速计算乘上8,也就是消息的比特长度。使用chr把int型数据转成比特对于的字符,注意和str的区别。

def msgProcess(m):
    # 附加长度
    str_l = chr(len(m)<<3)
    # 填充到模512为448
    # 至少进行一次填充
    m += 'x80'
    m += 'x00' * ((55 - len(m)) % 64)
    str_l = 'x00' * (9 - len(str_l)) + str_l
    m += str_l
    return m
2.2 使用的常量和循环移位函数

循环右移时为了保证数据在32bits内,需要取与。

#预定义常量
_H0 = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
      0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
_HashConstant = [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]


def shiftRight(a, x, bitnum=32):
    return ((a >> x)|(a << (bitnum - x))) & (2 ** bitnum - 1)
2.3 主循环

流程是将预处理好的消息分成512bits的数据块处理,更新ABCDEFGH的值,在对数据进行操作后,每次加法都应与11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111取与使得消息大小受限制。

def mySHA256(message):
    H = _H0.copy() # 使用列表的复制,不要修改常量的值
    message = msgProcess(message)
    for i in range(0, len(message), 64):
        msg = message[i:i+64]
        W = []
        for j in range(0,64,4):
            cut = msg[j:j+4]
            W.append(ord(cut[0])*(256**3)+ord(cut[1])*(256**2)+ord(cut[2])*256+ord(cut[3]))
        W = W + ([0]*48)
        for j in range(16,64):
            s0 = shiftRight(W[j-15],7) ^ shiftRight(W[j-15],18) ^ (W[j-15]>>3)
            s1 = shiftRight(W[j-2],17) ^ shiftRight(W[j-2],19) ^ (W[j-2]>>10)
            W[j] = (W[j-16] + s0 + W[j-7] + s1) & (2**32-1)
        a,b,c,d,e,f,g,h = H
        for i in range(64):
            s0 = (shiftRight(a, 2) ^ shiftRight(a, 13) ^ shiftRight(a, 22)) & ((2**32)-1)
            maj = ((a & b) ^ (a & c) ^ (b & c)) & ((2**32)-1)
            t2 = (s0 + maj) & ((2**32)-1)
            s1 = (shiftRight(e,6) ^ shiftRight(e,11) ^ shiftRight(e,25)) & ((2**32)-1)
            ch = ((e & f) ^ (~e & g)) & ((2**32)-1)
            t1 = (h + s1 + ch + _HashConstant[i] + W[i]) & ((2**32)-1)
            a,b,c,d,e,f,g,h = (t1+t2) & ((2**32)-1), a,b,c,(d+t1) & ((2**32)-1),e,f,g
        temp = [a,b,c,d,e,f,g,h]
        for i in range(8):
            H[i] += temp[i]
            H[i] = H[i] & ((2**32)-1)

    #转字符串,可能未满8位十六进制,补0
    en = [str(hex(it))[2:] for it in H]
    for i in range(8):
        it = en[i]
        if len(it)<8:
            en[i] = '0'*(8-len(it))+it

    return ''.join(en)
3 结果
if __name__ == '__main__':
    msg = ['121a s;f3','121a s;f3'*10]
    for it in msg:
        print('消息:   ', it)
        print('散列值: ', mySHA256(it))


然后发现中文的计算和一些标准还是有些不同的。

4 对中文编码

使用gbk对含有中文的消息编码,编码后是bytes型数据,编写bytes和str互转的函数

def byte2str(b):
    s = ''
    for i in b:
        i = hex(i)[2:]
        s += str(i)
    return s

def str2byte(s):
    b = b''
    b = bytearray()
    ind = 0
    while ind < len(s):
        b.append(int(s[ind:ind+2],16))
        ind += 2
    return bytes(b)

此外,还有一个重点是,其实python库里有sha256算法…,它是hashlib库下的sha256函数,将两个对比一下结果

import hashlib
if __name__ == '__main__':
    msg = ['message','message'*16,'message'*17]
    for it in msg:
        it = it.encode('gbk')
        it = byte2str(it)
        print('消息:     ', it)
        print('散列值:   ', mySHA256(it))
        print('库函数结果:',hashlib.sha256(it.encode('utf-8')).hexdigest(),'n')

结果一致

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/280776.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号