Practical 7: MD5

1. Using math

import math

def left_rotate(x, n):
    x &= 0xffffffff
    return ((x << n) | (x >> (32 - n))) & 0xffffffff

def md5(message):
    data = bytearray(message.encode())
    bit_length = len(data) * 8
    data.append(0x80)
    while (len(data) % 64) != 56:
        data.append(0)
    data += bit_length.to_bytes(8, byteorder='little')

    a0 = 0x67452301
    b0 = 0xefcdab89
    c0 = 0x98badcfe
    d0 = 0x10325476

    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
    ]

    K = [int(abs(math.sin(i + 1)) * (2**32)) & 0xffffffff for i in range(64)]


    for block in range(0, len(data), 64):
        chunk = data[block:block + 64]
        M = [int.from_bytes(chunk[i:i + 4], 'little') for i in range(0, 64, 4)]

        A = a0
        B = b0
        C = c0
        D = d0


        for i in range(64):
            if i < 16:
                F = (B & C) | (~B & D)
                g = i
            elif i < 32:
                F = (D & B) | (~D & C)
                g = (5 * i + 1) % 16
            elif i < 48:
                F = B ^ C ^ D
                g = (3 * i + 5) % 16
            else:
                F = C ^ (B | ~D)
                g = (7 * i) % 16

            F = (F + A + K[i] + M[g]) & 0xffffffff
            A = D
            D = C
            C = B
            B = (B + left_rotate(F, s[i])) & 0xffffffff

        a0 = (a0 + A) & 0xffffffff
        b0 = (b0 + B) & 0xffffffff
        c0 = (c0 + C) & 0xffffffff
        d0 = (d0 + D) & 0xffffffff

    result = (a0.to_bytes(4, 'little') +
              b0.to_bytes(4, 'little') +
              c0.to_bytes(4, 'little') +
              d0.to_bytes(4, 'little'))

    return result.hex()


message = input("Enter message: ")
print("Message:", message)
print("MD5 Digest:", md5(message))


2. Using hashlib for files

Code:

import hashlib
import os

def calculate_file_md5(file_path):
    """Calculates the MD5 hash of a file by reading it in binary chunks."""
    md5_hash = hashlib.md5()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            md5_hash.update(chunk)
    return md5_hash.hexdigest()

def calculate_string_md5(text):
    """Calculates the MD5 hash of a string."""
    return hashlib.md5(text.encode('utf-8')).hexdigest()

if __name__ == "__main__":
    file_path = input("Enter file path: ").strip()
    if os.path.isfile(file_path):
        digest = calculate_file_md5(file_path)
        print(f"File: {file_path}")
        print(f"MD5 Digest: {digest}")
    else:
        print(f"Error: '{file_path}' is not a valid file.")
