├── LICENSE ├── MD5算法.py └── test.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Gengarrr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MD5算法.py: -------------------------------------------------------------------------------- 1 | def int2bin(n, count=24): 2 | """returns the binary of integer n, using count number of digits""" 3 | return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)]) 4 | 5 | class MD5(object): 6 | # 初始化密文 7 | def __init__(self, message): 8 | self.message = message 9 | self.ciphertext = "" 10 | 11 | self.A = 0x67452301 12 | self.B = 0xEFCDAB89 13 | self.C = 0x98BADCFE 14 | self.D = 0x10325476 15 | self.init_A = 0x67452301 16 | self.init_B = 0xEFCDAB89 17 | self.init_C = 0x98BADCFE 18 | self.init_D = 0x10325476 19 | ''' 20 | self.A = 0x01234567 21 | self.B = 0x89ABCDEF 22 | self.C = 0xFEDCBA98 23 | self.D = 0x76543210 24 | ''' 25 | 26 | self.T = [0xD76AA478,0xE8C7B756,0x242070DB,0xC1BDCEEE,0xF57C0FAF,0x4787C62A,0xA8304613,0xFD469501, 27 | 0x698098D8,0x8B44F7AF,0xFFFF5BB1,0x895CD7BE,0x6B901122,0xFD987193,0xA679438E,0x49B40821, 28 | 0xF61E2562,0xC040B340,0x265E5A51,0xE9B6C7AA,0xD62F105D,0x02441453,0xD8A1E681,0xE7D3FBC8, 29 | 0x21E1CDE6,0xC33707D6,0xF4D50D87,0x455A14ED,0xA9E3E905,0xFCEFA3F8,0x676F02D9,0x8D2A4C8A, 30 | 0xFFFA3942,0x8771F681,0x6D9D6122,0xFDE5380C,0xA4BEEA44,0x4BDECFA9,0xF6BB4B60,0xBEBFBC70, 31 | 0x289B7EC6,0xEAA127FA,0xD4EF3085,0x04881D05,0xD9D4D039,0xE6DB99E5,0x1FA27CF8,0xC4AC5665, 32 | 0xF4292244,0x432AFF97,0xAB9423A7,0xFC93A039,0x655B59C3,0x8F0CCC92,0xFFEFF47D,0x85845DD1, 33 | 0x6FA87E4F,0xFE2CE6E0,0xA3014314,0x4E0811A1,0xF7537E82,0xBD3AF235,0x2AD7D2BB,0xEB86D391] 34 | self.s = [7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, 35 | 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 36 | 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, 37 | 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21] 38 | self.m = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 39 | 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, 40 | 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, 41 | 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9] 42 | 43 | 44 | 45 | # 附加填充位 46 | def fill_text(self): 47 | for i in range(len(self.message)): 48 | c = int2bin(ord(self.message[i]), 8) 49 | self.ciphertext += c 50 | 51 | if (len(self.ciphertext)%512 != 448): 52 | if ((len(self.ciphertext)+1)%512 != 448): 53 | self.ciphertext += '1' 54 | while (len(self.ciphertext)%512 != 448): 55 | self.ciphertext += '0' 56 | 57 | length = len(self.message)*8 58 | if (length <= 255): 59 | length = int2bin(length, 8) 60 | else: 61 | length = int2bin(length, 16) 62 | temp = length[8:12]+length[12:16]+length[0:4]+length[4:8] 63 | length = temp 64 | 65 | self.ciphertext += length 66 | while (len(self.ciphertext)%512 != 0): 67 | self.ciphertext += '0' 68 | 69 | # 分组处理(迭代压缩) 70 | def circuit_shift(self, x, amount): 71 | x &= 0xFFFFFFFF 72 | return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF 73 | 74 | def change_pos(self): 75 | a = self.A 76 | b = self.B 77 | c = self.C 78 | d = self.D 79 | self.A = d 80 | self.B = a 81 | self.C = b 82 | self.D = c 83 | 84 | def FF(self, mj, s, ti): 85 | mj = int(mj, 2) 86 | temp = self.F(self.B, self.C, self.D) + self.A + mj + ti 87 | temp = self.circuit_shift(temp, s) 88 | self.A = (self.B + temp)%pow(2, 32) 89 | self.change_pos() 90 | 91 | def GG(self, mj, s, ti): 92 | mj = int(mj, 2) 93 | temp = self.G(self.B, self.C, self.D) + self.A + mj + ti 94 | temp = self.circuit_shift(temp, s) 95 | self.A = (self.B + temp)%pow(2, 32) 96 | self.change_pos() 97 | 98 | def HH(self, mj, s, ti): 99 | mj = int(mj, 2) 100 | temp = self.H(self.B, self.C, self.D) + self.A + mj + ti 101 | temp = self.circuit_shift(temp, s) 102 | self.A = (self.B + temp)%pow(2, 32) 103 | self.change_pos() 104 | 105 | def II(self, mj, s, ti): 106 | mj = int(mj, 2) 107 | temp = self.I(self.B, self.C, self.D) + self.A + mj + ti 108 | temp = self.circuit_shift(temp, s) 109 | self.A = (self.B + temp)%pow(2, 32) 110 | self.change_pos() 111 | 112 | 113 | def F(self, X, Y, Z): 114 | return (X & Y) | ((~X) & Z) 115 | def G(self, X, Y, Z): 116 | return (X & Z) | (Y & (~Z)) 117 | def H(self, X, Y, Z): 118 | return X ^ Y ^ Z 119 | def I(self, X, Y, Z): 120 | return Y ^ (X | (~Z)) 121 | 122 | def group_processing(self): 123 | M = [] 124 | for i in range(0, 512, 32): 125 | num = "" 126 | # 获取每一段的标准十六进制形式 127 | for j in range(0, len(self.ciphertext[i:i+32]), 4): 128 | temp = self.ciphertext[i:i+32][j:j + 4] 129 | temp = hex(int(temp, 2)) 130 | num += temp[2] 131 | # 对十六进制进行小端排序 132 | num_tmp = "" 133 | for j in range(8, 0, -2): 134 | temp = num[j-2:j] 135 | num_tmp += temp 136 | 137 | num = "" 138 | for i in range(len(num_tmp)): 139 | num += int2bin(int(num_tmp[i], 16), 4) 140 | M.append(num) 141 | 142 | #print(M) 143 | 144 | 145 | 146 | for j in range(0, 16, 4): 147 | self.FF(M[self.m[j]], self.s[j], self.T[j]) 148 | self.FF(M[self.m[j+1]], self.s[j+1], self.T[j+1]) 149 | self.FF(M[self.m[j+2]], self.s[j+2], self.T[j+2]) 150 | self.FF(M[self.m[j+3]], self.s[j+3], self.T[j+3]) 151 | 152 | for j in range(0, 16, 4): 153 | self.GG(M[self.m[16+j]], self.s[16+j], self.T[16+j]) 154 | self.GG(M[self.m[16+j+1]], self.s[16+j+1], self.T[16+j+1]) 155 | self.GG(M[self.m[16+j+2]], self.s[16+j+2], self.T[16+j+2]) 156 | self.GG(M[self.m[16+j+3]], self.s[16+j+3], self.T[16+j+3]) 157 | 158 | 159 | for j in range(0, 16, 4): 160 | self.HH(M[self.m[32+j]], self.s[32+j], self.T[32+j]) 161 | self.HH(M[self.m[32+j+1]], self.s[32+j+1], self.T[32+j+1]) 162 | self.HH(M[self.m[32+j+2]], self.s[32+j+2], self.T[32+j+2]) 163 | self.HH(M[self.m[32+j+3]], self.s[32+j+3], self.T[32+j+3]) 164 | 165 | 166 | for j in range(0, 16, 4): 167 | self.II(M[self.m[48+j]], self.s[48+j], self.T[48+j]) 168 | self.II(M[self.m[48+j+1]], self.s[48+j+1], self.T[48+j+1]) 169 | self.II(M[self.m[48+j+2]], self.s[48+j+2], self.T[48+j+2]) 170 | self.II(M[self.m[48+j+3]], self.s[48+j+3], self.T[48+j+3]) 171 | 172 | self.A = (self.A+self.init_A)%pow(2, 32) 173 | self.B = (self.B+self.init_B)%pow(2, 32) 174 | self.C = (self.C+self.init_C)%pow(2, 32) 175 | self.D = (self.D+self.init_D)%pow(2, 32) 176 | ''' 177 | print("A:{}".format(hex(self.A))) 178 | print("B:{}".format(hex(self.B))) 179 | print("C:{}".format(hex(self.C))) 180 | print("D:{}".format(hex(self.D))) 181 | ''' 182 | answer = "" 183 | for register in [self.A, self.B, self.C, self.D]: 184 | register = hex(register)[2:] 185 | for i in range(8, 0, -2): 186 | answer += str(register[i-2:i]) 187 | 188 | return answer 189 | 190 | 191 | 192 | 193 | 194 | #MD5 = MD5("iscbupt") 195 | #MD5 = MD5("Beijing University of Posts and Telecommunications") 196 | #MD5 = MD5("njupt.information security") 197 | message = input("输入要加密的字符串:") 198 | MD5 = MD5(message) 199 | MD5.fill_text() 200 | result = MD5.group_processing() 201 | print("32位小写MD5加密:{}".format(result)) 202 | -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GengarSix2/MD5_py/1645b24b84fe3c1e86f924798ebfb3ea2ab1e183/test.txt --------------------------------------------------------------------------------