Python sha256长度大于56时输出不正确

Python sha256长度大于56时输出不正确,python,hash,sha256,Python,Hash,Sha256,我试图学习sha256的每一步,所以我用python编写了一段代码,它使用二进制字符串而不是数学运算来完全理解它 当输入少于56个字符时,代码工作正常,但当输入等于或大于56个字符时,输出不正确: 对于exmaple,输入为: BA7816BF8F01CFEA414140DE5DAE223BDA12AEA5324SFDSEREW3RA 而不是1caa150674ab1aed030dc69f9b86dbcbc412e6e1dd20344eeaa21687acae7789 我得到了8492782cc

我试图学习sha256的每一步,所以我用python编写了一段代码,它使用二进制字符串而不是数学运算来完全理解它

当输入少于56个字符时,代码工作正常,但当输入等于或大于56个字符时,输出不正确:

对于exmaple,输入为:
BA7816BF8F01CFEA414140DE5DAE223BDA12AEA5324SFDSEREW3RA

而不是
1caa150674ab1aed030dc69f9b86dbcbc412e6e1dd20344eeaa21687acae7789

我得到了
8492782cc396d4454980c9b63f127c5730da7d838822f8f37b1c7705d2630b88

代码:

Operations.py

  class Operations:
        def add(self, data1, data2):
              x = data1
              y = data2

              carry = 0
              result = ""

              for i in range(len(data1) -1, -1, -1):
                    r = carry
                    r += 1 if x[i] == '1' else 0
                    r += 1 if y[i] == '1' else 0
                    result = ('1' if r % 2 == 1 else '0') + result
                    carry = 0 if r < 2 else 1

              if carry != 0: result = '1' + result

              return result[-len(data1):]

        def xor(self, data1, data2):
              result = ""
              for i in range(len(data1)):
                    temp1 = data1[i]
                    temp2 = data2[i]
                    if (temp1 == "0" and temp2 == "0") or (temp1 == "1" and temp2 == "1"):
                          result += "0"
                    else:
                          result += "1"

              return result

        def shiftRight(self, data, turn):
              result = "0" * turn + data
              return result[:len(data)]

        def rotateRight(self, data, turn):
              result = None
              for i in range(turn):
                    if result:
                          temp = result[-1]
                          result = (temp + result)[:len(data)]
                    else:
                          temp = data[-1]
                          result = (temp + data)[:len(data)]

              return result

Main.py

  from math import ceil
  from copy import copy
  from functions import Functions

  _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]

  _h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
        0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]

  class SHA256(Functions):
        blocks = []

        def __init__(self):
              global _k, _h            
              _k = [f'{i:b}'.zfill(32) for i in _k]
              _h = [f'{i:b}'.zfill(32) for i in _h]

        def message_to_blocks(self, message):
              chunk = 56
              data = [format(ord(x), 'b').zfill(8) for x in message]

              for i in range(ceil(len(data) / chunk)):
                    self.blocks.append(data[chunk * i:chunk * (i + 1)])

                    self.blocks[i] = ''.join(self.blocks[i])
                    length = f'{len(self.blocks[i]):b}'
                    self.blocks[i] += '1'
                    self.blocks[i] = self.blocks[i].ljust(512, '0')

                    # add length to last 64 bit
                    self.blocks[i] = self.blocks[i][:-len(length)]
                    self.blocks[i] += length

        def message_schedule(self, data):
              schedule = []
              n = 32
              # first 16 words
              schedule = [(data[i:i+n]) for i in range(0, len(data), n)]
              # generate the rest
              for i in range(16, 64):
                    temp1 = self.sigma1(schedule[-2])
                    temp2 = self.sigma0(schedule[-15])
                    result = self.add(temp1, self.add(schedule[-7], self.add(temp2, schedule[-16])))
                    schedule.append(result)

              return schedule

        def compress(self):
              for block in self.blocks:
                    temp_h = copy(_h)
                    _w = self.message_schedule(block)
                    for i in range(64):
                          T1 = [self.gamma1(_h[4]), self.choice(_h[4], _h[5], _h[6]), _h[7], _k[i], _w[i]]
                          T1 = self.add(T1[0], self.add(T1[1], self.add(T1[2], self.add(T1[3], T1[4]))))

                          T2 = [self.gamma0(_h[0]), self.majority(_h[0], _h[1], _h[2])]
                          T2 = self.add(T2[0], T2[1])
                          
                          # shift all constants down
                          _h[7] = _h[6] # h
                          _h[6] = _h[5] # g
                          _h[5] = _h[4] # f
                          _h[4] = _h[3] # e
                          _h[3] = _h[2] # d
                          _h[2] = _h[1] # c
                          _h[1] = _h[0] # b

                          # compress
                          _h[0] = self.add(T1, T2)
                          _h[4] = self.add(_h[4], T1)

                    # add with initial values
                    _h[0] = self.add(_h[0], temp_h[0])
                    _h[1] = self.add(_h[1], temp_h[1])
                    _h[2] = self.add(_h[2], temp_h[2])
                    _h[3] = self.add(_h[3], temp_h[3])
                    _h[4] = self.add(_h[4], temp_h[4])
                    _h[5] = self.add(_h[5], temp_h[5])
                    _h[6] = self.add(_h[6], temp_h[6])
                    _h[7] = self.add(_h[7], temp_h[7])

              return self.digest(_h)

        def digest(self, hashes):
              final_hash = ""
              for hash in hashes:
                    t = hex(int(hash, 2))
                    final_hash += t[2:]

              return final_hash

  a = SHA256()
  a.message_to_blocks("ba7816bf8f01cfea414140de5dae2223bda12ae1a5324sfdserew3ra")
  print(a.compress())
当输入少于56个字符时,代码工作正常,但当输入等于或大于56个字符时,输出不正确

这部分的问题在于:

length=f'{len(self.blocks[i]):b}'
self.blocks[i]+=“1”
self.blocks[i]=self.blocks[i].ljust(512,'0')
#将长度添加到最后64位
self.blocks[i]=self.blocks[i][:-len(长度)]
self.blocks[i]+=长度
错误在于零填充的计算方式与不具有64位宽度的长度相结合。实际上,您的代码用零填充最后一个消息块,使其具有512位的长度,然后用未添加的二进制长度(
111000000
)替换最后的n位,但在零填充小于64位的情况下,这将无法正常工作

其结果是代码将总消息输入处理为:

01100010011000011011100111000 0011000100110110001001100111000011100001110000111000011100011000110001100001100001100001100001100000100100100011000100110001100011000110000100100100100011000011100001110000100100110101001001011001100001001001100100110011001100110011000110001100110011000011100001110000100111000010011100001001001001001110011001100001001001001001001001001001001001110011001100001001001001001001001001001001110011001100101100001001101001100110011001100110010 001101000110011011001100100011110010111001100101110010111001011101110011001111111110010011000010000000000000000000000000000000000000000000000000000000000000000000000111000000

而不是:


01100010011000011011100111000 0011000100110110001001100111000011100001110000111000011100011000110001100001100001100001100001100000100100100011000100110001100011000110000100100100100011000011100001110000100100110101001001011001100001001001100100110011001100110011000110001100110011000011100001110000100111000010011100001001001001001110011001100001001001001001001001001001001001110011001100001001001001001001001001001001110011001100101100001001101010011001100110010 00110100011100110110011001100100 01110011011001010111001001100101 01110111001100110111001001100001 10000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000111000000

那么长度就是整个消息长度?我认为在每个块中,我们应该指定块中消息的长度。@hamidreza长度是任何处理之前原始消息的总长度(以位为单位),并且只有最后的512位块的长度在末尾。基本上,原始消息在512位块中处理,直到没有剩余消息为止,然后追加“1”,然后再加上多少个零,以使64位长度在512位边界上结束。
  from math import ceil
  from copy import copy
  from functions import Functions

  _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]

  _h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
        0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]

  class SHA256(Functions):
        blocks = []

        def __init__(self):
              global _k, _h            
              _k = [f'{i:b}'.zfill(32) for i in _k]
              _h = [f'{i:b}'.zfill(32) for i in _h]

        def message_to_blocks(self, message):
              chunk = 56
              data = [format(ord(x), 'b').zfill(8) for x in message]

              for i in range(ceil(len(data) / chunk)):
                    self.blocks.append(data[chunk * i:chunk * (i + 1)])

                    self.blocks[i] = ''.join(self.blocks[i])
                    length = f'{len(self.blocks[i]):b}'
                    self.blocks[i] += '1'
                    self.blocks[i] = self.blocks[i].ljust(512, '0')

                    # add length to last 64 bit
                    self.blocks[i] = self.blocks[i][:-len(length)]
                    self.blocks[i] += length

        def message_schedule(self, data):
              schedule = []
              n = 32
              # first 16 words
              schedule = [(data[i:i+n]) for i in range(0, len(data), n)]
              # generate the rest
              for i in range(16, 64):
                    temp1 = self.sigma1(schedule[-2])
                    temp2 = self.sigma0(schedule[-15])
                    result = self.add(temp1, self.add(schedule[-7], self.add(temp2, schedule[-16])))
                    schedule.append(result)

              return schedule

        def compress(self):
              for block in self.blocks:
                    temp_h = copy(_h)
                    _w = self.message_schedule(block)
                    for i in range(64):
                          T1 = [self.gamma1(_h[4]), self.choice(_h[4], _h[5], _h[6]), _h[7], _k[i], _w[i]]
                          T1 = self.add(T1[0], self.add(T1[1], self.add(T1[2], self.add(T1[3], T1[4]))))

                          T2 = [self.gamma0(_h[0]), self.majority(_h[0], _h[1], _h[2])]
                          T2 = self.add(T2[0], T2[1])
                          
                          # shift all constants down
                          _h[7] = _h[6] # h
                          _h[6] = _h[5] # g
                          _h[5] = _h[4] # f
                          _h[4] = _h[3] # e
                          _h[3] = _h[2] # d
                          _h[2] = _h[1] # c
                          _h[1] = _h[0] # b

                          # compress
                          _h[0] = self.add(T1, T2)
                          _h[4] = self.add(_h[4], T1)

                    # add with initial values
                    _h[0] = self.add(_h[0], temp_h[0])
                    _h[1] = self.add(_h[1], temp_h[1])
                    _h[2] = self.add(_h[2], temp_h[2])
                    _h[3] = self.add(_h[3], temp_h[3])
                    _h[4] = self.add(_h[4], temp_h[4])
                    _h[5] = self.add(_h[5], temp_h[5])
                    _h[6] = self.add(_h[6], temp_h[6])
                    _h[7] = self.add(_h[7], temp_h[7])

              return self.digest(_h)

        def digest(self, hashes):
              final_hash = ""
              for hash in hashes:
                    t = hex(int(hash, 2))
                    final_hash += t[2:]

              return final_hash

  a = SHA256()
  a.message_to_blocks("ba7816bf8f01cfea414140de5dae2223bda12ae1a5324sfdserew3ra")
  print(a.compress())