什么是MD5?
MD5消息摘要算法(Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值,用于确保信息传输完整一致。MD5有MD4、MD3、MD2改进而来,主要增强算法复杂度和不可逆性。MD5广泛使用在为文件传输提供一定的可靠性方面。例如:服务器预先提供一个MD5校验和,用户下载完文件之后,用MD5算法计算下载文件的MD5校验和,然后通过检查这两个检验和是否一致,就能判断下载的文件是否出错。
MD5算法介绍
MD5算法处理不定长的输入信息,得到定长的128位输出。MD5将输入信息以512位进行分组,且每一分组又被划分为16个32位子分组,经过一系列处理之后算法的输出得到4个32位的输出,将此四个输出拼接起来就可以获得最终的加密结果。
下面介绍算法的主要步骤:
kk mod 512!=448pkL
A = 0x67452301
B = 0xEFCDAB89
C = 0x98BADCFE
D = 0x10325476
| wordA | 01 | 23 | 45 | 67 |
|---|---|---|---|---|
| workB | 89 | AB | CD | EF |
| wordC | FE | DC | BA | 09 |
| wordD | 76 | 54 | 32 | 10 |
Little-Endian
将低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,相反Big-Endian将高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。存储结构与CPU体系结构和语言编译器有关。PowerPC系列采用Big Endian方式存储数据,而Intel x86系列则采用Little-Endian方式存储。
TT[]X[]
迭代运算如下:
dtemp := d
d = c
c = b
b = b + ((a+轮函数(b,c,d)+X[k]+T[i] <<< s))
a = dtemp
轮函数定义如下:
| 轮次 | Function g | g(b,c,d) |
|---|---|---|
| 1 | F(b,c,d) | (b & c) | (~b & d) |
| 2 | G(b,c,d) | (b & d) | (c & ~d) |
| 3 | H[b,c,d) | (b ^ c ^ d) |
| 4 | I(b,c,d) | c ^ (b | ~d) |
a,b,c,dX[k]T[i]<<
X[k]X[k]
- 第一轮循环:k = i (0~15)
顺序使用X[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15] - 第二轮循环:k=(1+5i) mod 16 (16~31)
顺序使用X[1, 6,11, 0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12] - 第三轮循环:k=(5+3i) mod 16(32~47)
顺序使用X[5, 8,11,14, 1, 4, 7,10,13, 0, 3, 6, 9,12,15, 2] - 第四轮循环:k=7i mod 16(48~63)
顺序使用X[0, 7,14, 5,12, 3,10, 1, 8,15, 6,13, 4,11, 2, 9]
T
var T = []uint32{
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,
}
各次迭代运算采用的做循环移位s的值:
// 向左位移数
var s = []uint32{
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,
}
算法实现
// 下方函数为MD5加密算法的核心,迭代加密步骤
func trans(text string) {
// 将512-bit消息划分为16组
X := div_group(text)
var f, k uint32
// result存储最初的A,B,C,D
a := result[0]
b := result[1]
c := result[2]
d := result[3]
for i := uint32(0); i < uint32(64); i++ {
if i < 16 {
f = F(b, c, d)
k = i
} else if i < 32 {
f = G(b, c, d)
k = (5*i + 1) % 16
} else if i < 48 {
f = H(b, c, d)
k = (3*i + 5) % 16
} else {
f = I(b, c, d)
k = (7 * i) % 16
}
dtemp := d
d = c
c = b
b = b + (shift(a+f+T[i]+X[k], s[i]))
a = dtemp
}
result[0] = result[0] + a
result[1] = result[1] + b
result[2] = result[2] + c
result[3] = result[3] + d
}
加密结果如下:
// 下方三组数据来自wiki
The quick brown fox jumps over the lazy dog: 9e107d9d372bb6826bd81d3542a419d6
The quick brown fox jumps over the lazy cog: 1055d3e698d289f2af8663725127bd4b
: d41d8cd98f00b204e9800998ecf8427e //空字符串加密结果
完整代码详见Github