You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MD5实现代码输出与预期不符,请求排查问题原因

MD5实现结果不符问题

我按照维基百科的MD5算法伪代码实现了一一对应的Python版本,但输出结果与预期不符。我尝试了所有可能的方法修复,但结果仍不正确。请问这是否是由于编码系统不同导致的?恳请提供帮助。

代码实现

#This Code has one to one correspondance with https://en.wikipedia.org/wiki/MD5#Algorithm psuedocode
#-------------Globals Start ----------------------#
from math import sin , floor 
import math
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 = [floor(abs(math.sin(i + 1)) * (2 ** 32)) & 0xFFFFFFFF for i in range(64)]

rotate = lambda x,n:((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
#-------------Globals End------------------------#
    
def md5(text):
    a0 = 0x67452301
    b0 = 0xefcdab89
    c0 = 0x98badcfe
    d0 = 0x10325476
    length  = len(text)
    text = text + b'\x80'
    text += (b'\x00' * (512 - (len(text) * 8 % 512)))
    text = text +  length.to_bytes(8, 'little')
    for i in range(0, len(text), 64):
        chunk = text[i:i+64]
        M = [int.from_bytes(chunk[j:j+4], 'little') for j in range(0, 64, 4)]
        A = a0
        B = b0
        C = c0
        D = d0
        for j in range(64):
            if 0 <= j <= 15:
                F = (B & C) | ((~B) & D)
                g = j
            elif 16 <= j <= 31:
                F = (D & B) | ((~D) & C)
                g = ((5 * j) + 1) % 16
            elif 32 <= j <= 47:
                F = B ^ C ^ D
                g = ((3 * j) + 5) % 16
            elif 48 <= j <= 63:
                F = C ^ (B | (~D))
                g = (7 * j) % 16

            F = (F + A + K[j] + M[g]) & 0xFFFFFFFF
            A, D, C, B = D, C, B, (B + rotate(F, S[j])) & 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()
text = 'The quick brown fox jumps over the lazy dog'.encode("utf-8")
print(md5(text))

输出对比

  • 实际输出:
171e495fea830541b8542c338e388a97
  • 预期输出:
9e107d9d372bb6826bd81d3542a419d6

问题分析与修复

问题不是编码系统导致的,而是代码中的填充逻辑错误和寄存器更新顺序错误导致结果不符,具体修正点如下:

1. 填充逻辑错误

MD5的填充规则要求:在原始数据后添加0x80,再添加若干0x00,使得总长度(以比特为单位)模512等于448,最后添加原始数据长度的64位小端表示。

你的代码中填充0x00的计算方式错误,直接将比特数当作字节数使用,正确的计算应该是先算出需要填充的比特数,再转换为字节数:

# 替换错误的填充代码
original_length_bits = len(text) * 8
text += b'\x80'
pad_bits = (448 - ((original_length_bits + 8) % 512)) % 512
text += b'\x00' * (pad_bits // 8)
text += original_length_bits.to_bytes(8, 'little')

2. 寄存器更新顺序错误

维基百科伪代码中寄存器的更新顺序是先保存原始D的值,再依次更新D、C、B,最后将原始D赋值给A。你的代码中并行赋值的顺序错误,导致A被错误覆盖,正确的更新逻辑应为:

# 替换错误的寄存器赋值代码
temp = D
D = C
C = B
B = (B + rotate(F, S[j])) & 0xFFFFFFFF
A = temp

修正后的完整代码

from math import sin, floor
import math

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 = [floor(abs(math.sin(i + 1)) * (2 ** 32)) & 0xFFFFFFFF for i in range(64)]

rotate = lambda x, n: ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF

def md5(text):
    a0 = 0x67452301
    b0 = 0xefcdab89
    c0 = 0x98badcfe
    d0 = 0x10325476
    original_length_bits = len(text) * 8

    # 填充第一步:添加0x80
    text += b'\x80'

    # 填充第二步:添加0,使总长度模512等于448位
    pad_bits = (448 - ((original_length_bits + 8) % 512)) % 512
    text += b'\x00' * (pad_bits // 8)

    # 填充第三步:添加原始长度的64位小端表示
    text += original_length_bits.to_bytes(8, 'little')

    for i in range(0, len(text), 64):
        chunk = text[i:i+64]
        M = [int.from_bytes(chunk[j:j+4], 'little') for j in range(0, 64, 4)]
        A = a0
        B = b0
        C = c0
        D = d0

        for j in range(64):
            if 0 <= j <= 15:
                F = (B & C) | ((~B) & D)
                g = j
            elif 16 <= j <= 31:
                F = (D & B) | ((~D) & C)
                g = ((5 * j) + 1) % 16
            elif 32 <= j <= 47:
                F = B ^ C ^ D
                g = ((3 * j) + 5) % 16
            elif 48 <= j <= 63:
                F = C ^ (B | (~D))
                g = (7 * j) % 16

            F = (F + A + K[j] + M[g]) & 0xFFFFFFFF
            # 修正寄存器更新顺序
            temp = D
            D = C
            C = B
            B = (B + rotate(F, S[j])) & 0xFFFFFFFF
            A = temp

        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()

text = 'The quick brown fox jumps over the lazy dog'.encode("utf-8")
print(md5(text))  # 输出:9e107d9d372bb6826bd81d3542a419d6

验证结果

修正后的代码运行后,输出与预期完全一致。

内容的提问来源于stack exchange,提问作者Shadab Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:39:55