这个MD5实现有什么问题?

huangapple go评论75阅读模式
英文:

What is wrong with this md5 implementation

问题

以下是有关此MD5实现的问题的翻译:

  • 我尝试了一切可能的方法来使其工作,但结果与文章中给出的伪代码不符。这是因为不同的编码系统吗?
  • 任何帮助将不胜感激。

链接:https://en.wikipedia.org/wiki/MD5#Algorithm

#这段代码与https://en.wikipedia.org/wiki/MD5#Algorithm中的伪代码一一对应
#-------------全局变量开始 ----------------------#
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
    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
英文:

What is wrong with this md5 implementation

I tried all the possible thing to get it working but wrong result compared to the pseudocode given in article.
Does this is because of different encoding System.
Any Help Would be appreciated.

https://en.wikipedia.org/wiki/MD5#Algorithm

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

Output:

171e495fea830541b8542c338e388a97

Expected Output

9e107d9d372bb6826bd81d3542a419d6

答案1

得分: 1

你的填充方式不正确,以下这些行:

text += b'\x00' * (512 - (len(text) * 8 % 512))
text = text + length.to_bytes(8, 'little')

应该改成:

text += b'\x00' * (56 - (len(text) % 64))
text = text + (length * 8).to_bytes(8, 'little')

解释:

看起来你混淆了位和字节的值。你的消息是以字节为单位的,这意味着 len(text) 表示的是字节长度。因此,在计算需要填充的量时,我们需要使用字节值。

同样,在下一行中,由于 length 是字节值,所以在附加它之前,我们需要将它转换为位值(根据规范)。

英文:

You are padding incorrectly, the lines:

text += (b'\x00' * (512 - (len(text) * 8 % 512)))
text = text + length.to_bytes(8, 'little')

should instead be:

text += b'\x00' * (56 - (len(text) % 64))
text = text + (length * 8).to_bytes(8, 'little')

Explanation:

It seems you are getting confused between bit and byte values. Your message is in bytes which means
len(text) is the message length in bytes. Consequently, when calculating the amount to pad we need to use byte values.

Similarly on the next line since length is a byte value we need to convert it to a bit value before appending it (according to the spec).

huangapple
  • 本文由 发表于 2023年5月25日 00:02:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325456.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定