MD5密码

【题目】

1) 实现MD5 Hash函数算法,具体要求:

A.     实现MD5算法的消息压缩过程,任选一个大小为10M的word文档,并计算其Hash值(注意,计算的是包括文件头等在内的完整文件的Hash函数值,而不仅仅是文件内容的Hash函数值);

【实现代码】

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on Wed Jan  3 19:32:17 2018

@author: HP
"""

from time import clock

#初始变量  小端字节序:书上A = 0x01234567 这是内存中的顺序,并不是说A的值为0x01234567
#在程序中应该把A赋值为0x67452301
A = '0x67452301'  
B = '0xefcdab89'  
C = '0x98badcfe'  
D = '0x10325476'  

#步函数
F = lambda x,y,z:((x&y)|((~x)&z))  
G = lambda x,y,z:((x&z)|(y&(~z)))  
H = lambda x,y,z:(x^y^z)  
I = lambda x,y,z:(y^(x|(~z)))  

#循环左移函数(x循环左移n位)
L = lambda x,n:(((x<<n)|(x>>(32-n)))&(0xffffffff))  

#每轮16步循环左移的位数
s1 = (7,12,17,22)*4  
s2 = (5,9,14,20)*4  
s3 = (4,11,16,23)*4  
s4 = (6,10,15,21)*4  

#每轮16步M子组的排序
m_1 = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)  
m_2 = (1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12)  
m_3 = (5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2)  
m_4 = (0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9)  

#4轮64步的T表
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']
     
#翻转十六进制数的顺序:'0x01234567' => '0x67452301'   
def reverse_hex(hex_str):  
    hex_str = hex_str[2:]  
    hex_str_list = []  
    for i in range(0,len(hex_str),2):  
        hex_str_list.append(hex_str[i:i+2])  
    hex_str_list.reverse()  
    hex_str_result = '0x' + ''.join(hex_str_list)  
    return hex_str_result 
  
#md5类
class MD5(object):
    
    def __init__(self, plaintext):
        self.plist = ["0x"+hex(x)[2:].rjust(2, '0') for x in plaintext]
        self.plength = len(self.plist)*8
        print(self.plength)
        self.__fill()
    
    def __fill(self):
        #先填充一个10000000
        self.plist.append('0x80')
        
        #然后填充00000000直到剩下64位也就是8字节
        while (len(self.plist)+8)%64 != 0:
            self.plist.append('0x00')
        
        #用消息长度(位)填满最后8字节
        #举例长度为8, 我们填充的应该是倒置的0x0800000000000000
        #只有这样在内存中的顺序才是0x000000000000000008, 而不是直接填充0x000000000000000008
        hex_len = hex(self.plength)[2:]
        hex_len = '0x' + hex_len.rjust(16, '0')
        hex_len = reverse_hex(hex_len)[2:]
        for i in range(0, len(hex_len), 2):
            self.plist.append('0x' + hex_len[i:i+2])
        print(self.plist)
        
    #生成每轮的16个M子分组
    def genM16(self, order, z):  
        #起始坐标
        start = 64*z
        result = []
        for i in range(start, start+64, 4):
            result.append("0x" + "".join((self.plist[i] + self.plist[i+1] + self.plist[i+2] + self.plist[i+3]).split('0x')[1:]))
        result = list(map(lambda x: result[x], order))
        return list(map(reverse_hex, result))
       
    #对每轮的16步进行加密
    def fun(self, fun_list, sfunc, m, s, n): 
        for i in range(16):
            #模2^32次方加
            xx = int(fun_list[0], 16) + sfunc(int(fun_list[1], 16), int(fun_list[2], 16), int(fun_list[3], 16)) + int(m[i], 16) + int(T[16*n+i], 16)
            xx = xx&0xffffffff
            
            #循环左移s[i]位
            xx = L(xx, s[i])
            
            #加B
            xx = (xx + int(fun_list[1], 16))&0xffffffff

            fun_list[0] = hex(xx)
            
            #列表右移一位
            x = fun_list.pop()
            fun_list.insert(0, x)
            print(fun_list)
            
        return fun_list
        
    def encrypt(self):
        abcd_list = [A, B, C, D]
        for i in range(0, len(self.plist)//64):
            #把寄存器初始值存下来
            AA, BB, CC, DD = abcd_list
            
            #生成该组明文四轮的M列表
            m_list1 = self.genM16(m_1, i)
            m_list2 = self.genM16(m_2, i)   
            m_list3 = self.genM16(m_3, i)
            m_list4 = self.genM16(m_4, i)   
            
            #进行4轮加密
            abcd_list = self.fun(abcd_list, F, m_list1, s1, 0)
            print("------------------------------------------")
            abcd_list = self.fun(abcd_list, G, m_list2, s2, 1)  
            print("------------------------------------------")
            abcd_list = self.fun(abcd_list, H, m_list3, s3, 2)
            print("------------------------------------------")
            abcd_list = self.fun(abcd_list, I, m_list4, s4, 3)
            print("------------------------------------------")
            
            #和初始值相加得到该组明文加密结果
            output_a = hex((int(AA, 16) + int(abcd_list[0], 16))&0xffffffff)
            output_b = hex((int(BB, 16) + int(abcd_list[1], 16))&0xffffffff)    
            output_c = hex((int(CC, 16) + int(abcd_list[2], 16))&0xffffffff)
            output_d = hex((int(DD, 16) + int(abcd_list[3], 16))&0xffffffff) 
            
            abcd_list = [output_a, output_b, output_c, output_d]  
            
            print(abcd_list)
        return abcd_list
    
    #将加密函数得到的结果进行反转合并显示出来
    def show_result(self, abcd_list): 
        result = ""
        for x in abcd_list:
            result += reverse_hex(x)[2:]
        return result
        
if __name__=="__main__":
    print("__________开始md5加密______________")
    #计时
    #读文件
    fname = input("please enter filename: ")
    start = clock()
    f = open(fname, 'rb')
    plaintext = f.read()
    f.close()
    #加密
    md5 = MD5(plaintext)
    ciphertext = md5.show_result(md5.encrypt())
    #将密文写入文件
    f = open(fname, 'w')
    f.write(ciphertext)
    f.close()
    print("__________加密结束______________")
    print("密文:%s" %ciphertext)
    print("加密时长是:%.2f" %(clock()-start))
    #print(md5.show_result(md5.encrypt()))


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值