密码学课程设计-Hash函数-MD5

  1. 1 概述
  2. 2 算法原理与设计思路
    1. 2.1 附加填充位
    2. 2.2 初始化链接变量
    3. 2.3 分组处理
    4. 2.4 步函数
  3. 3 关键算法分析
  4. 4 运行结果
  5. 5 密码安全性分析

1 概述

MD5算法是美国麻省理工学院著名密码学家Rivest设计的,MD(Message Digest)是消息摘要的意思。Rivest于1992年想IETF提交的RFC1321中对MD5作了详尽的阐述。MD5是在MD2、MD3和MD4基础上发展而来的,尤其在MD4上增加了Safety-Belts,所以,MD5又被称为是“系有安全带的MD4”,它虽然比MD4要慢一些,但更为安全。

2 算法原理与设计思路

MD5的加密过程可分为附加填充位、初始化链接变量、分组处理和步函数四个部分,下面依次介绍这四个过程。

2.1 附加填充位

填充一个“1”和若干个“0”使消息长度模512与448同余,然后再将原始消息长度以64比特表示附加在填充结果的后面,从而使得消息长度恰好为512比特的整数倍。

2.2 初始化链接变量

MD5使用4个32位的寄存器A、B、C和D,最开始存放4个固定的32位的整数参数,即初始链接变量,这些参数用于第1轮迭代
A=0x01234567,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210

MD5运算过程

2.3 分组处理

分组处理

2.4 步函数

步函数

3 关键算法分析

关键算法分析

4 运行结果

完整代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import math

# Initial Variable A, B, C, D
IV_A = 0x67452301
IV_B = 0xefcdab89
IV_C = 0x98badcfe
IV_D = 0x10325476

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

# Loop Left Shift
L = lambda x, n:(((x << n) | (x >> (32 - n))) & (0xffffffff))

# 每次循环左移的位数
Shi = ((7, 12, 17, 22) * 4,
(5, 9, 14, 20) * 4,
(4, 11, 16, 23) * 4,
(6, 10, 15, 21) * 4)

# 每次 M[i](消息分片)次序。
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 LittleEndian(s, Hex):
l = len(s)
ans = ""
if Hex == False:
i = l - 8
while i >= 0:
ans += s[i:i + 8]
i -= 8
else:
i = l-2
while i >= 0:
ans += s[i:i + 2]
i -= 2
return ans

# 将字符串转成二进制字符串
def str2Bin(m):
return "".join('{:08b}'.format(ord(x)) for x in m)

# 模2的32次方加
def addMod2_32(a, b):
return (a + b) % (2 ** 32)

# 产生常数T[i],常数有可能超过32位,需要&0xffffffff操作
# 返回的是十进制的数。
def T(i):
result = (int(4294967296 * abs(math.sin(i)))) & 0xffffffff
return result

def MD5(m):
## str to binstr
m = str2Bin(m)
lm = len(m)
## Padding
lm_mod = lm % 512
### 若原始消息长度刚好满足模512与448同余
### 则还需要填充512位
if lm_mod == 448:
FillLength = 512
elif lm_mod > 448:
FillLength = 512 + 448 - lm_mod
else:
FillLength = 448 - lm_mod
m += '1' + (FillLength - 1) * '0'
# Padding length
length = LittleEndian(bin(lm % (2 ** 64))[2:].zfill(64), False)
m += length
lm = len(m)
## Generate Initial Variable(IV)
A, B, C, D = IV_A, IV_B, IV_C, IV_D
for i in range(0, lm, 512):
Y = m[i:i + 512]
for j in range(4): # 共4轮
for k in range(16): # 每轮16个步骤
# A, B, C, D Backup
AA, BB, CC, DD = A, B, C, D
## Nonlinear function
if j == 0:
t = F(B, C, D)
elif j == 1:
t = G(B, C, D)
elif j == 2:
t = H(B, C, D)
else:
t = I(B, C, D)
T_i = T(16 * j + k + 1)
M_j = LittleEndian(Y[M[j][k] * 32:M[j][k] * 32 + 32], False)
A, C, D = DD, BB, CC
B = addMod2_32(AA, t)
B = addMod2_32(B, int(M_j, 2))
B = addMod2_32(B, T_i)
B = L(B, Shi[j][k])
B = addMod2_32(B, BB)
ans1 = LittleEndian(hex(addMod2_32(A, IV_A))[2:-1], True).zfill(8)
ans2 = LittleEndian(hex(addMod2_32(B, IV_B))[2:-1], True).zfill(8)
ans3 = LittleEndian(hex(addMod2_32(C, IV_C))[2:-1], True).zfill(8)
ans4 = LittleEndian(hex(addMod2_32(D, IV_D))[2:-1], True).zfill(8)
return ans1 + ans2 + ans3 + ans4

def main():
m = input("请输入明文: ")
ans = MD5(m)
print("明文加密后的密文是:\n" + MD5(m) + " (Lowercase)\n" + ans.upper() + " (Uppercase)")

if __name__ == '__main__':
main()

运行效果如下图:

运行效果

5 密码安全性分析

密码安全性分析


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏