SHA-256哈希函数实现

SHA-256算法

算法简介

  • 对于长度小于2^64位的消息,SHA256会产生一个160位的消息摘要。
  • 当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。
  • 在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。
  • 是对SHA1函数的扩展

功能实现

  • 加密文件
  • 加密字符串
  • 检验哈希值

全部代码

# -*-coding:utf-8-*-
"""
File Name: SHA-256算法.py

Program IDE: PyCharm

Create Time: 2021-10-04 14:13

Create By Author: 陆依依

"""

# 检验正确性
import hashlib		


# 字符串转为2进制
def Encode(string):
    return ''.join([(8 - len(bin(ord(s)).replace('0b', ''))) * '0' + bin(ord(s)).replace('0b', '') for s in string])


# 填充消息
def Padding(message):
    # 将字节转为字符
    message = ''.join([chr(message[i]) for i in range(len(message))])
    l = len(message) * 8 % 512
    if l + 1 > 448:
        k = 512 - (l + 1 - 448)
    else:
        k = 448 - l - 1
    a = bin(len(message) * 8).replace('0b', '')
    b = '0' * (64 - len(a)) + a
    c = ''
    for i in range(0, 64, 8):           # 后64bit
        c = c + chr(int(b[i: i+8], 2))
    message = message + chr(128) + chr(0) * int(k / 8) + c
    return message


# 循环右移t位
def ROTR(t, num):
    temp = (32 - len(bin(num).replace('0b', ''))) * '0' + bin(num).replace('0b', '')
    return int(temp[32-t:] + temp[:32-t], 2)


# 右移t位
def SHR(t, num):
    temp = (32 - len(bin(num).replace('0b', ''))) * '0' + bin(num).replace('0b', '')
    return int(temp[:32-t], 2)


# 逻辑函数
def FF(t, x, y=0, z=0):
    if t == 1:
        return (x & y) ^ (~x & z)
    elif t == 2:
        return (x & y) ^ (x & z) ^ (y & z)
    elif t == 3:
        return ROTR(2, x) ^ ROTR(13, x) ^ ROTR(22, x)
    elif t == 4:
        return ROTR(6, x) ^ ROTR(11, x) ^ ROTR(25, x)
    elif t == 5:
        return ROTR(7, x) ^ ROTR(18, x) ^ SHR(3, x)
    elif t == 6:
        return ROTR(17, x) ^ ROTR(19, x) ^ SHR(10, x)


# 加密
def Encrypt(message):
    message = Padding(message)

    # 初始化变量
    H0 = int('6A09E667', 16)
    H1 = int('BB67AE85', 16)
    H2 = int('3C6EF372', 16)
    H3 = int('A54FF53A', 16)
    H4 = int('510E527F', 16)
    H5 = int('9B05688C', 16)
    H6 = int('1F83D9AB', 16)
    H7 = int('5BE0CD19', 16)

    # 常量
    K = [int('428a2f98', 16), int('71374491', 16), int('b5c0fbcf', 16), int('e9b5dba5', 16),
         int('3956c25b', 16), int('59f111f1', 16), int('923f82a4', 16), int('ab1c5ed5', 16),
         int('d807aa98', 16), int('12835b01', 16), int('243185be', 16), int('550c7dc3', 16),
         int('72be5d74', 16), int('80deb1fe', 16), int('9bdc06a7', 16), int('c19bf174', 16),
         int('e49b69c1', 16), int('efbe4786', 16), int('0fc19dc6', 16), int('240ca1cc', 16),
         int('2de92c6f', 16), int('4a7484aa', 16), int('5cb0a9dc', 16), int('76f988da', 16),
         int('983e5152', 16), int('a831c66d', 16), int('b00327c8', 16), int('bf597fc7', 16),
         int('c6e00bf3', 16), int('d5a79147', 16), int('06ca6351', 16), int('14292967', 16),
         int('27b70a85', 16), int('2e1b2138', 16), int('4d2c6dfc', 16), int('53380d13', 16),
         int('650a7354', 16), int('766a0abb', 16), int('81c2c92e', 16), int('92722c85', 16),
         int('a2bfe8a1', 16), int('a81a664b', 16), int('c24b8b70', 16), int('c76c51a3', 16),
         int('d192e819', 16), int('d6990624', 16), int('f40e3585', 16), int('106aa070', 16),
         int('19a4c116', 16), int('1e376c08', 16), int('2748774c', 16), int('34b0bcb5', 16),
         int('391c0cb3', 16), int('4ed8aa4a', 16), int('5b9cca4f', 16), int('682e6ff3', 16),
         int('748f82ee', 16), int('78a5636f', 16), int('84c87814', 16), int('8cc70208', 16),
         int('90befffa', 16), int('a4506ceb', 16), int('bef9a3f7', 16), int('c67178f2', 16)]

    # 分块处理
    for i in range(0, len(message), 64):
        temp = Encode(message[i:i + 64])

        W = [int(temp[j:j + 32], 2) for j in range(0, 512, 32)]
        for j in range(16, 64):
            W.append((FF(6, W[j-2]) + W[j-7] + FF(5, W[j-15]) + W[j-16]) % (2**32))

        # 寄存器
        A = H0
        B = H1
        C = H2
        D = H3
        E = H4
        F = H5
        G = H6
        H = H7

        for j in range(0, 64):
            T1 = (H + FF(4, E) + FF(1, E, F, G) + K[j] + W[j]) % (2**32)
            T2 = (FF(3, A) + FF(2, A, B, C)) % (2**32)
            H = G
            G = F
            F = E
            E = (D + T1) % (2**32)
            D = C
            C = B
            B = A
            A = (T1 + T2) % (2**32)

        H0 = (H0 + A) % (2**32)
        H1 = (H1 + B) % (2**32)
        H2 = (H2 + C) % (2**32)
        H3 = (H3 + D) % (2**32)
        H4 = (H4 + E) % (2**32)
        H5 = (H5 + F) % (2**32)
        H6 = (H6 + G) % (2**32)
        H7 = (H7 + H) % (2**32)

    return str((8 - len(str(hex(H0)).replace('0x', ''))) * '0' + str(hex(H0)).replace('0x', '') +
               (8 - len(str(hex(H1)).replace('0x', ''))) * '0' + str(hex(H1)).replace('0x', '') +
               (8 - len(str(hex(H2)).replace('0x', ''))) * '0' + str(hex(H2)).replace('0x', '') +
               (8 - len(str(hex(H3)).replace('0x', ''))) * '0' + str(hex(H3)).replace('0x', '') +
               (8 - len(str(hex(H4)).replace('0x', ''))) * '0' + str(hex(H4)).replace('0x', '') +
               (8 - len(str(hex(H5)).replace('0x', ''))) * '0' + str(hex(H5)).replace('0x', '') +
               (8 - len(str(hex(H6)).replace('0x', ''))) * '0' + str(hex(H6)).replace('0x', '') +
               (8 - len(str(hex(H7)).replace('0x', ''))) * '0' + str(hex(H7)).replace('0x', ''))


# demo
if __name__ == "__main__":
    while(True):
        path = ''     # 默认文件路径
        choose = int(input('请选择加密对象:1)文件  2)非文件\t'))
        if choose == 2:
            message = input('请输入待加密内容:').encode('utf-8')
        else:
            path = input('请输入完整文件路径:')
            message = open(path, 'rb').readlines()
            temp = message[0]
            for i in range(1, len(message)):
                temp = temp + message[i]
            message = temp

        print('手动实现:' + Encrypt(message))
        print('调库检验:' + hashlib.sha256(message).hexdigest())
        print('hash是否相等?\t' + str(hashlib.sha256(message).hexdigest() == Encrypt(message)))

实验结果

运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值