Программа Python MD5 выдает неверный результат - PullRequest
0 голосов
/ 01 марта 2019

Я работал над созданием собственной хэш-программы md5 на python.Первоначально я использовал интерактивную колоду слайдов , а затем преобразовал некоторый псевдокод со страницы википедии .

Для работы с битами я использовал библиотеку python bitarray и структуруразбить биты на целые числа.

Когда я запускаю код в пустом файле, он дает отличный результат от правильного.Я надеюсь, что кто-то может помочь мне понять это.

Код ниже:

#!/usr/bin/env python3
from bitarray import bitarray
import math
import struct

with open('./hash_str.txt', 'r') as open_file:
    hash_str = open_file.read()

#  The following stuff is preprocessing padding
result = []
for x in hash_str:
    result.append(format(ord(x), '08b'))
a = ''.join(result)
orig_len = len(a)# % (2**64)
if orig_len % 512 != 448:
    a = a+'1'
    while len(a) % 512 != 448:
        a = a + '0'

b = bitarray(format(orig_len, '064b'))

a = bitarray(a) + b

wordA = bitarray()
wordA.frombytes(bytes.fromhex('01234567'))
wordB = bitarray()
wordB.frombytes(bytes.fromhex('89abcdef'))
wordC = bitarray()
wordC.frombytes(bytes.fromhex('fedcba98'))
wordD = bitarray()
wordD.frombytes(bytes.fromhex('76543210'))

K = [math.floor(abs(math.sin(i + 1)) * 2**32) for i in range(64)] # checked
s = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
     5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
     4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
     6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]

def F(B, C, D):
    return (B & C) | (~B & D)

def G(B, C, D):
    return (B & D) | (C & ~D)

def H(B, C, D):
    return B ^ C ^ D

def I(B, C, D):
    return C ^ (B | ~D)

def remover(bitstr, tolen=32):
    return bitstr[len(bitstr)-tolen:]

# Breaking everything up into words
for bigbyte in range(int(a.length() / 512)):
    prechunk = a[bigbyte*512: (bigbyte+1)*512]
    chunk = []
    for tzt in range(16):
        chunk.append(prechunk[tzt*32: (tzt+1)*32])

    tmpA = wordA
    tmpB = wordB
    tmpC = wordC
    tmpD = wordD

    # Main Loop
    for round in range(64):
        print('round', round)
        if round >= 0 and round <= 15:
            cycler = F(tmpB, tmpC, tmpD)
            sp_round = round
        elif round >= 16 and round <= 31:
            cycler = G(tmpB, tmpC, tmpD)
            sp_round = (5*round + 1) % 16
        elif round >= 32 and round <= 47:
            cycler = H(tmpB, tmpC, tmpD)
            sp_round = (3*round + 5) % 16
        elif round >= 48 and round <= 63:
            cycler = I(tmpB, tmpC, tmpD)
            sp_round = (7*round) % 16
        topad = [cycler.length(), tmpA.length()]
        cycler = bitarray(remover(format(struct.unpack("<L", cycler.tobytes())[0] + struct.unpack("<L", tmpA.tobytes())[0] + K[round] + struct.unpack("<L", chunk[sp_round].tobytes())[0], '0'+str(max(topad))+'b')))
        tmpA = tmpD
        tmpD = tmpC
        tmpC = tmpB
        current = struct.unpack("<L", cycler.tobytes())[0]
        toadd = (current << s[round]) | (current >> ((len(bin(current)[2:])*8) - s[round]))
        tmpB = bitarray(remover(format(struct.unpack("<L", tmpB.tobytes())[0] + toadd, '0'+str(max([tmpB.length(), cycler.length()]))+'b')))

    topad = [wordA.length(), tmpA.length()]
    wordA = bitarray(remover(format(struct.unpack("<L", wordA.tobytes())[0] + struct.unpack("<L", tmpA.tobytes())[0], '0'+str(max(topad))+'b')))
    topad = [wordB.length(), tmpB.length()]
    wordB = bitarray(remover(format(struct.unpack("<L", wordB.tobytes())[0] + struct.unpack("<L", tmpB.tobytes())[0], '0'+str(max(topad))+'b')))
    topad = [wordC.length(), tmpC.length()]
    wordC = bitarray(remover(format(struct.unpack("<L", wordC.tobytes())[0] + struct.unpack("<L", tmpC.tobytes())[0], '0'+str(max(topad))+'b')))
    topad = [wordD.length(), tmpD.length()]
    wordD = bitarray(remover(format(struct.unpack("<L", wordD.tobytes())[0] + struct.unpack("<L", tmpD.tobytes())[0], '0'+str(max(topad))+'b')))

final = wordA+wordB+wordC+wordD
print(final.tobytes().hex())
...