MD5密码实验——Python实现(完整解析版)

更新:

感谢评论区的两位大佬指出错误,特此感谢,现已改进代码
在这里插入图片描述
在这里插入图片描述

1.第一次修改
之前的错误在于没有考虑最高位是0的情况
造成某些字符串的MD5加密结果与实际不符
所以对代码作出如下部分修改
原先代码
在这里插入图片描述

现在代码
在这里插入图片描述
2.第二次修改

代码中的group_processing方法只处理了第一个分组,而没有进行迭代处理。

MD5算法是迭代型杂凑函数,每个分组的处理结果会影响下一个分组的计算。在代码中,init_A、init_B、init_C、init_D是初始的寄存器值,应该在处理每个分组之前更新为上一个分组处理后的结果。但是在代码中,这些初始值没有被更新,导致处理后续分组时出错。

要修复这个问题,可以在group_processing方法中添加适当的代码来更新init_A、init_B、init_C、init_D,以便迭代处理每个分组。
具体做法是,在每次迭代结束后将当前的A、B、C、D值赋给init_A、init_B、init_C、init_D,以便下一个分组使用。

原先的代码

    def group_processing(self):
        M = []
        for i in range(0, 512, 32):
            num = ""
            # 获取每一段的标准十六进制形式
            for j in range(0, len(self.ciphertext[i:i+32]), 4):
                temp = self.ciphertext[i:i+32][j:j + 4]
                temp = hex(int(temp, 2))
                num += temp[2]
            # 对十六进制进行小端排序
            num_tmp = ""
            for j in range(8, 0, -2):
                temp = num[j-2:j]
                num_tmp += temp

            num = ""
            for i in range(len(num_tmp)):
                num += int2bin(int(num_tmp[i], 16), 4)
            M.append(num)

修改之后

def group_processing(self):
    M = []
    for i in range(0, len(self.ciphertext), 512):
        # 获取当前分组
        current_group = self.ciphertext[i:i+512]

        # 处理当前分组...
        # ...

        # 更新 init_A、init_B、init_C、init_D
        self.init_A = self.A
        self.init_B = self.B
        self.init_C = self.C
        self.init_D = self.D

        for j in range(0, 512, 32):
            num = ""
            # 获取每一段的标准十六进制形式
            for k in range(0, len(current_group[j:j+32]), 4):
                temp = current_group[j:j+32][k:k+4]
                temp = hex(int(temp, 2))
                num += temp[2]
            # 对十六进制进行小端排序
            num_tmp = ""
            for k in range(8, 0, -2):
                temp = num[k-2:k]
                num_tmp += temp

            num = ""
            for k in range(len(num_tmp)):
                num += int2bin(int(num_tmp[k], 16), 4)
            M.append(num)


前言

实验目的
1)初步了解哈希算法
2)掌握哈希算法MD5的实现


提示:以下是本篇文章正文内容,下面案例可供参考

实验环境

计算机语言:Python
开发环境:Pycharm

实验内容

编程实现MD5算法。

实验操作步骤

编写MD5类
在这里插入图片描述
初始化配置各参数

1.初始化四个缓冲区

在这里插入图片描述
在这里插入图片描述

2.设置常数表、位移位数等参数

在这里插入图片描述
在这里插入图片描述

3.增加填充

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.分组处理

在这里插入图片描述
在这里插入图片描述
分为四个分组,FF,GG,HH,II
每组对消息message的不同单位进行加密

在这里插入图片描述在这里插入图片描述
分组处理,每次循环移动四位
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.输出处理

在这里插入图片描述
在这里插入图片描述

实验结果

1.明文:12345678
密文:25d55ad23a80aa4f464c76d713c07ad
在这里插入图片描述
与在线加密结果一致
在这里插入图片描述

2.明文:hello world
密文:5eb63bbbe01eeed093cb22bb8f5acdc3
在这里插入图片描述
与在线加密结果一致
在这里插入图片描述

实验心得

本次实验是MD5算法的编写,通过本次python代码编写实现了加密功能,编写的思路从MD5算法原理出发,通过初始化缓冲区、附加填充位、分组进行加密等步骤,构造类来实现功能,相较于RSA,MD5是不可逆算法,应该会更加安全一些,但我查阅资料后发现并非如此,在线的MD5库可以解密数量巨大的MD5密文,只有在“加盐”过后才会使得破解难度大大增加。

实验代码

MD5-Python.py

# -*- codeding = uft-8 -*-

def int2bin(n, count=24):
    return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])

class MD5(object):
    # 初始化密文
    def __init__(self, message):
        self.message = message
        self.ciphertext = ""

        self.A = 0x67452301
        self.B = 0xEFCDAB89
        self.C = 0x98BADCFE
        self.D = 0x10325476
        self.init_A = 0x67452301
        self.init_B = 0xEFCDAB89
        self.init_C = 0x98BADCFE
        self.init_D = 0x10325476
        '''
        self.A = 0x01234567
        self.B = 0x89ABCDEF
        self.C = 0xFEDCBA98
        self.D = 0x76543210
         '''
        #设置常数表T
        self.T = [0xD76AA478,0xE8C7B756,0x242070DB,0xC1BDCEEE,0xF57C0FAF,0x4787C62A,0xA8304613,0xFD469501,
                    0x698098D8,0x8B44F7AF,0xFFFF5BB1,0x895CD7BE,0x6B901122,0xFD987193,0xA679438E,0x49B40821,
                    0xF61E2562,0xC040B340,0x265E5A51,0xE9B6C7AA,0xD62F105D,0x02441453,0xD8A1E681,0xE7D3FBC8,
                    0x21E1CDE6,0xC33707D6,0xF4D50D87,0x455A14ED,0xA9E3E905,0xFCEFA3F8,0x676F02D9,0x8D2A4C8A,
                    0xFFFA3942,0x8771F681,0x6D9D6122,0xFDE5380C,0xA4BEEA44,0x4BDECFA9,0xF6BB4B60,0xBEBFBC70,
                    0x289B7EC6,0xEAA127FA,0xD4EF3085,0x04881D05,0xD9D4D039,0xE6DB99E5,0x1FA27CF8,0xC4AC5665,
                    0xF4292244,0x432AFF97,0xAB9423A7,0xFC93A039,0x655B59C3,0x8F0CCC92,0xFFEFF47D,0x85845DD1,
                    0x6FA87E4F,0xFE2CE6E0,0xA3014314,0x4E0811A1,0xF7537E82,0xBD3AF235,0x2AD7D2BB,0xEB86D391]
        #循环左移位数
        self.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]
        self.m = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
                    1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
                    5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
                    0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9]



    # 附加填充位
    def fill_text(self):
        for i in range(len(self.message)):
            c = int2bin(ord(self.message[i]), 8)
            self.ciphertext += c

        if (len(self.ciphertext)%512 != 448):
            if ((len(self.ciphertext)+1)%512 != 448):
                self.ciphertext += '1'
            while (len(self.ciphertext)%512 != 448):
                self.ciphertext += '0'

        length = len(self.message)*8
        if (length <= 255):
            length = int2bin(length, 8)
        else:
            length = int2bin(length, 16)
            temp = length[8:12]+length[12:16]+length[0:4]+length[4:8]
            length = temp

        self.ciphertext += length
        while (len(self.ciphertext)%512 != 0):
            self.ciphertext += '0'

    # 分组处理(迭代压缩)
    def circuit_shift(self, x, amount):
        x &= 0xFFFFFFFF
        return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF

    def change_pos(self):
        a = self.A
        b = self.B
        c = self.C
        d = self.D
        self.A = d
        self.B = a
        self.C = b
        self.D = c

    def FF(self, mj, s, ti):
        mj = int(mj, 2)
        temp = self.F(self.B, self.C, self.D) + self.A + mj + ti
        temp = self.circuit_shift(temp, s)
        self.A = (self.B + temp)%pow(2, 32)
        self.change_pos()

    def GG(self, mj, s, ti):
        mj = int(mj, 2)
        temp = self.G(self.B, self.C, self.D) + self.A + mj + ti
        temp = self.circuit_shift(temp, s)
        self.A = (self.B + temp)%pow(2, 32)
        self.change_pos()

    def HH(self, mj, s, ti):
        mj = int(mj, 2)
        temp = self.H(self.B, self.C, self.D) + self.A + mj + ti
        temp = self.circuit_shift(temp, s)
        self.A = (self.B + temp)%pow(2, 32)
        self.change_pos()

    def II(self, mj, s, ti):
        mj = int(mj, 2)
        temp = self.I(self.B, self.C, self.D) + self.A + mj + ti
        temp = self.circuit_shift(temp, s)
        self.A = (self.B + temp)%pow(2, 32)
        self.change_pos()


    def F(self, X, Y, Z):
        return (X & Y) | ((~X) & Z)
    def G(self, X, Y, Z):
        return (X & Z) | (Y & (~Z))
    def H(self, X, Y, Z):
        return X ^ Y ^ Z
    def I(self, X, Y, Z):
        return Y ^ (X | (~Z))

    def group_processing(self):
        M = []
        for i in range(0, len(self.ciphertext), 512):
            # 获取当前分组
            current_group = self.ciphertext[i:i+512]

            # 处理当前分组...
            # ...

            # 更新 init_A、init_B、init_C、init_D
            self.init_A = self.A
            self.init_B = self.B
            self.init_C = self.C
            self.init_D = self.D

            for j in range(0, 512, 32):
                num = ""
                # 获取每一段的标准十六进制形式
                for k in range(0, len(current_group[j:j+32]), 4):
                    temp = current_group[j:j+32][k:k+4]
                    temp = hex(int(temp, 2))
                    num += temp[2]
                # 对十六进制进行小端排序
                num_tmp = ""
                for k in range(8, 0, -2):
                    temp = num[k-2:k]
                    num_tmp += temp

                num = ""
                for k in range(len(num_tmp)):
                    num += int2bin(int(num_tmp[k], 16), 4)
                M.append(num)
        #print(M)



        for j in range(0, 16, 4):
            self.FF(M[self.m[j]], self.s[j], self.T[j])
            self.FF(M[self.m[j+1]], self.s[j+1], self.T[j+1])
            self.FF(M[self.m[j+2]], self.s[j+2], self.T[j+2])
            self.FF(M[self.m[j+3]], self.s[j+3], self.T[j+3])

        for j in range(0, 16, 4):
            self.GG(M[self.m[16+j]], self.s[16+j], self.T[16+j])
            self.GG(M[self.m[16+j+1]], self.s[16+j+1], self.T[16+j+1])
            self.GG(M[self.m[16+j+2]], self.s[16+j+2], self.T[16+j+2])
            self.GG(M[self.m[16+j+3]], self.s[16+j+3], self.T[16+j+3])


        for j in range(0, 16, 4):
            self.HH(M[self.m[32+j]], self.s[32+j], self.T[32+j])
            self.HH(M[self.m[32+j+1]], self.s[32+j+1], self.T[32+j+1])
            self.HH(M[self.m[32+j+2]], self.s[32+j+2], self.T[32+j+2])
            self.HH(M[self.m[32+j+3]], self.s[32+j+3], self.T[32+j+3])


        for j in range(0, 16, 4):
            self.II(M[self.m[48+j]], self.s[48+j], self.T[48+j])
            self.II(M[self.m[48+j+1]], self.s[48+j+1], self.T[48+j+1])
            self.II(M[self.m[48+j+2]], self.s[48+j+2], self.T[48+j+2])
            self.II(M[self.m[48+j+3]], self.s[48+j+3], self.T[48+j+3])

        self.A = (self.A+self.init_A)%pow(2, 32)
        self.B = (self.B+self.init_B)%pow(2, 32)
        self.C = (self.C+self.init_C)%pow(2, 32)
        self.D = (self.D+self.init_D)%pow(2, 32)

        """
        print("A:{}".format(hex(self.A)))
        print("B:{}".format(hex(self.B)))
        print("C:{}".format(hex(self.C)))
        print("D:{}".format(hex(self.D)))
        """


        answer = ""
        for register in [self.A, self.B, self.C, self.D]:
            if len(hex(register))!=10:
                str1 = list(hex(register))
                str1.insert(2,'0')
                str2 = ''.join(str1)
                register = str2[2:]
            else:
                register = hex(register)[2:]
            for i in range(8, 0, -2):
                answer += str(register[i-2:i])

        return answer



message = input("输入要加密的字符串:")
MD5 = MD5(message)
MD5.fill_text()
result = MD5.group_processing()
print("32位小写MD5加密:{}".format(result))



  • 35
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值