md5信息摘要算法实现(python 和 go版本)
纯手写实现的md5信息摘要算法
https://github.com/kittysmith5/dgst/blob/main/md5
python3版本代码
#!/usr/bin/python3
# _*_ encoding: utf-8 _*_
"""
@File : my_md5.py
@Time : 9:07 PM
@Author : Barry Johnson
@Version: 1.0
@Contact: *******@***.com
@License: None
@Desc : None
"""
T = (0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391)
SFF = (7, 12, 17, 22)
SGG = (5, 9, 14, 20)
SHH = (4, 11, 16, 23)
SII = (6, 10, 15, 21)
def f(x, y, z):
return x & y | ~x & z
def g(x, y, z):
return x & z | y & ~z
def h(x, y, z):
return x ^ y ^ z
def i(x, y, z):
return y ^ (x | ~z)
def rol(num, count):
#
# num需要是32位的
"""
坑!!!
:param num:
:param count:
:return:
"""
b = (num & 0xffffffff) << count
return (b & 0xffffffff) + (b >> 32)
# return (num << count) | (num >> 32 - count)
def ff(a, b, c, d, mj, s, ti):
"""
返回值不需要控制长度 超过32位也可以
:param a:
:param b:
:param c:
:param d:
:param mj:
:param s:
:param ti:
:return:
"""
return b + rol((a + f(b, c, d) + mj + ti), s)
def gg(a, b, c, d, mj, s, ti):
return b + rol((a + g(b, c, d) + mj + ti), s)
def hh(a, b, c, d, mj, s, ti):
return b + rol((a + h(b, c, d) + mj + ti), s)
def ii(a, b, c, d, mj, s, ti):
return b + rol((a + i(b, c, d) + mj + ti), s)
def plain2bit(plain: str):
"""
三个部分,原文需要小端序就是 0xabce f012 ---> 0x12f0 cdab
中间的补充码和前面原文一起小端序 8bit小端序
最后的长度需要单独处理,前后32位进行交换即可
:param plain:
:return:
"""
bit_lis = []
bit_str = ""
bit_lis_32 = []
for char in plain:
bit_str += f"{int(str(bin(ord(char))).replace('0b', '')):08}"
# 补位 使总长度除以512的余数为448 512->64B 一个ascii码 8位->1个B
rmd = len(bit_str) % 512
if rmd == 448:
bit_str += '1' + '0' * 511
else:
bit_str += '1' + '0' * (448 - rmd - 1)
# 后64位补充长度信息 采用小端序
# len 是比特的数量,不是字符串的数量
len2_str = f"{int(str(bin(len(plain) * 8)).replace('0b', '')):064}"
bit_str += len2_str
for j in range(int(len(bit_str) / 512)):
bit_lis.append(bit_str[j * 512:(j + 1) * 512])
for block in bit_lis:
bit_lis_32_item = []
for j in range(int(512 / 32)):
hex_str = hex(int(block[j * 32:(j + 1) * 32], 2))
bit_lis_32_item.append(int(reverse_hex(hex_str.replace("0x", '')), 16))
bit_lis_32.append(bit_lis_32_item)
# 最后64位是32位小端序
bit_lis_32[-1][-1] = int(len2_str[0:32], 2)
bit_lis_32[-1][-2] = int(len2_str[32:64], 2)
print(bit_lis_32)
return bit_lis_32
def reverse_hex(hex_str: str):
hex_str = hex_str.replace('0x', '')
hex_str_list = []
for j in range(len(hex_str)):
hex_str = "0" * (8 - len(hex_str)) + hex_str
for j in range(0, 8, 2):
hex_str_list.append(hex_str[j: j + 2])
hex_str_list.reverse()
hex_str = "".join(hex_str_list)
return hex_str
def main_loop(plain):
lis = plain2bit(plain)
A = 0x67452301
B = 0xefcdab89
C = 0x98badcfe
D = 0x10325476
for item in lis:
a = A
b = B
c = C
d = D
# Round 1 ---> 1
a = ff(a, b, c, d, mj=item[0], s=SFF[0], ti=T[0])
d = ff(d, a, b, c, mj=item[1], s=SFF[1], ti=T[1])
c = ff(c, d, a, b, mj=item[2], s=SFF[2], ti=T[2])
b = ff(b, c, d, a, mj=item[3], s=SFF[3], ti=T[3])
a = ff(a, b, c, d, mj=item[4], s=SFF[0], ti=T[4])
d = ff(d, a, b, c, mj=item[5], s=SFF[1], ti=T[5])
c = ff(c, d, a, b, mj=item[6], s=SFF[2], ti=T[6])
b = ff(b, c, d, a, mj=item[7], s=SFF[3], ti=T[7])
a = ff(a, b, c, d, mj=item[8], s=SFF[0], ti=T[8])
d = ff(d, a, b, c, mj=item[9], s=SFF[1], ti=T[9])
c = ff(c, d, a, b, mj=item[10], s=SFF[2], ti=T[10])
b = ff(b, c, d, a, mj=item[11], s=SFF[3], ti=T[11])
a = ff(a, b, c, d, mj=item[12], s=SFF[0], ti=T[12])
d = ff(d, a, b, c, mj=item[13], s=SFF[1], ti=T[13])
c = ff(c, d, a, b, mj=item[14], s=SFF[2], ti=T[14])
b = ff(b, c, d, a, mj=item[15], s=SFF[3], ti=T[15])
# Round 2 ---> 5
a = gg(a, b, c, d, mj=item[1], s=SGG[0], ti=T[0 + 16])
d = gg(d, a, b, c, mj=item[6], s=SGG[1], ti=T[1 + 16])
c = gg(c, d, a, b, mj=item[11], s=SGG[2], ti=T[2 + 16])
b = gg(b, c, d, a, mj=item[0], s=SGG[3], ti=T[3 + 16])
a = gg(a, b, c, d, mj=item[5], s=SGG[0], ti=T[4 + 16])
d = gg(d, a, b, c, mj=item[10], s=SGG[1], ti=T[5 + 16])
c = gg(c, d, a, b, mj=item[15], s=SGG[2], ti=T[6 + 16])
b = gg(b, c, d, a, mj=item[4], s=SGG[3], ti=T[7 + 16])
a = gg(a, b, c, d, mj=item[9], s=SGG[0], ti=T[8 + 16])
d = gg(d, a, b, c, mj=item[14], s=SGG[1], ti=T[9 + 16])
c = gg(c, d, a, b, mj=item[3], s=SGG[2], ti=T[10 + 16])
b = gg(b, c, d, a, mj=item[8], s=SGG[3], ti=T[11 + 16])
a = gg(a, b, c, d, mj=item[13], s=SGG[0], ti=T[12 + 16])
d = gg(d, a, b, c, mj=item[2], s=SGG[1], ti=T[13 + 16])
c = gg(c, d, a, b, mj=item[7], s=SGG[2], ti=T[14 + 16])
b = gg(b, c, d, a, mj=item[12], s=SGG[3], ti=T[15 + 16])
# Round 3 --->3
a = hh(a, b, c, d, mj=item[5], s=SHH[0], ti=T[0 + 16 * 2])
d = hh(d, a, b, c, mj=item[8], s=SHH[1], ti=T[1 + 16 * 2])
c = hh(c, d, a, b, mj=item[11], s=SHH[2], ti=T[2 + 16 * 2])
b = hh(b, c, d, a, mj=item[14], s=SHH[3], ti=T[3 + 16 * 2])
a = hh(a, b, c, d, mj=item[1], s=SHH[0], ti=T[4 + 16 * 2])
d = hh(d, a, b, c, mj=item[4], s=SHH[1], ti=T[5 + 16 * 2])
c = hh(c, d, a, b, mj=item[7], s=SHH[2], ti=T[6 + 16 * 2])
b = hh(b, c, d, a, mj=item[10], s=SHH[3], ti=T[7 + 16 * 2])
a = hh(a, b, c, d, mj=item[13], s=SHH[0], ti=T[8 + 16 * 2])
d = hh(d, a, b, c, mj=item[0], s=SHH[1], ti=T[9 + 16 * 2])
c = hh(c, d, a, b, mj=item[3], s=SHH[2], ti=T[10 + 16 * 2])
b = hh(b, c, d, a, mj=item[6], s=SHH[3], ti=T[11 + 16 * 2])
a = hh(a, b, c, d, mj=item[9], s=SHH[0], ti=T[12 + 16 * 2])
d = hh(d, a, b, c, mj=item[12], s=SHH[1], ti=T[13 + 16 * 2])
c = hh(c, d, a, b, mj=item[15], s=SHH[2], ti=T[14 + 16 * 2])
b = hh(b, c, d, a, mj=item[2], s=SHH[3], ti=T[15 + 16 * 2])
# Round 4 --->7
a = ii(a, b, c, d, mj=item[0], s=SII[0], ti=T[0 + 16 * 3])
d = ii(d, a, b, c, mj=item[7], s=SII[1], ti=T[1 + 16 * 3])
c = ii(c, d, a, b, mj=item[14], s=SII[2], ti=T[2 + 16 * 3])
b = ii(b, c, d, a, mj=item[5], s=SII[3], ti=T[3 + 16 * 3])
a = ii(a, b, c, d, mj=item[12], s=SII[0], ti=T[4 + 16 * 3])
d = ii(d, a, b, c, mj=item[3], s=SII[1], ti=T[5 + 16 * 3])
c = ii(c, d, a, b, mj=item[10], s=SII[2], ti=T[6 + 16 * 3])
b = ii(b, c, d, a, mj=item[1], s=SII[3], ti=T[7 + 16 * 3])
a = ii(a, b, c, d, mj=item[8], s=SII[0], ti=T[8 + 16 * 3])
d = ii(d, a, b, c, mj=item[15], s=SII[1], ti=T[9 + 16 * 3])
c = ii(c, d, a, b, mj=item[6], s=SII[2], ti=T[10 + 16 * 3])
b = ii(b, c, d, a, mj=item[13], s=SII[3], ti=T[11 + 16 * 3])
a = ii(a, b, c, d, mj=item[4], s=SII[0], ti=T[12 + 16 * 3])
d = ii(d, a, b, c, mj=item[11], s=SII[1], ti=T[13 + 16 * 3])
c = ii(c, d, a, b, mj=item[2], s=SII[2], ti=T[14 + 16 * 3])
b = ii(b, c, d, a, mj=item[9], s=SII[3], ti=T[15 + 16 * 3])
A = (a + A) & 0xffffffff
B = (b + B) & 0xffffffff
C = (c + C) & 0xffffffff
D = (d + D) & 0xffffffff
result = reverse_hex(hex(A)) + reverse_hex(hex(B)) + reverse_hex(hex(C)) + reverse_hex(hex(D))
return result
def md5_encrypt(plain_txt):
return main_loop(plain_txt)
golang 1.8代码
package main
import (
"fmt"
"strconv"
)
const Int32Max = 0xffffffff
var T = [64]int{
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
}
var SFF = [4]int{7, 12, 17, 22}
var SGG = [4]int{5, 9, 14, 20}
var SHH = [4]int{4, 11, 16, 23}
var SII = [4]int{6, 10, 15, 21}
func f(x, y, z int) int {
return x&y | ^x&z
}
func g(x, y, z int) int {
return x&z | y&^z
}
func h(x, y, z int) int {
return x ^ y ^ z
}
func i(x, y, z int) int {
return y ^ (x | ^z)
}
func rol(num, count int) int {
b := (num & Int32Max) << count
return (b & Int32Max) + (b >> 32)
}
func ff(a, b, c, d, mj, s, ti int) int {
return b + rol(a+f(b, c, d)+mj+ti, s)
}
func gg(a, b, c, d, mj, s, ti int) int {
return b + rol(a+g(b, c, d)+mj+ti, s)
}
func hh(a, b, c, d, mj, s, ti int) int {
return b + rol(a+h(b, c, d)+mj+ti, s)
}
func ii(a, b, c, d, mj, s, ti int) int {
return b + rol(a+i(b, c, d)+mj+ti, s)
}
func dec2bitStr(dec, bitLen int) string {
s := ""
for dec > 0 {
rem := dec % 2
dec = dec / 2
s = strconv.Itoa(rem) + s
}
initLen := len(s)
for i := 0; i < bitLen-initLen; i++ {
s = "0" + s
}
return s
}
func bitStr2dec(bitStr string) int {
intVal := 0
for i := 0; i < len(bitStr); i++ {
if bitStr[len(bitStr)-i-1] == 49 {
intVal += nonNegIntPow(2, i)
}
}
return intVal
}
func nonNegIntPow(base, power int) int {
result := 1
for i := 0; i < power; i++ {
result *= base
}
return result
}
func littleEndian(str string) string {
if len(str) < 32 {
count := 32 - len(str)
for i := 0; i < count; i++ {
str = "0" + str
}
}
newStr := str[24:32] + str[16:24] + str[8:16] + str[0:8]
return newStr
}
func plain2bit(plain string) [][]int {
bitStr := ""
bitStrSlice := make([]string, 0)
bitStr32 := make([][]int, 0)
for _, c := range plain {
bitStr += dec2bitStr(int(c), 8)
}
rmd := len(bitStr) % 512
if rmd == 448 {
bitStr += "1"
for i := 0; i < 511; i++ {
bitStr += "0"
}
} else {
bitStr += "1"
for i := 0; i < 448-rmd-1; i++ {
bitStr += "0"
}
}
lenBitStr := dec2bitStr(len(plain)*8, 64)
bitStr += lenBitStr
for i := 0; i < len(bitStr)/512; i++ {
bitStrSlice = append(bitStrSlice, bitStr[i*512:(i+1)*512])
}
bitStr32Item := make([]int, 16)
for i := 0; i < len(bitStrSlice); i++ {
for j := 0; j < 16; j++ {
bitStr32Item[j] = bitStr2dec(littleEndian(bitStrSlice[i][j*32 : (j+1)*32]))
}
bitStr32 = append(bitStr32, bitStr32Item)
}
bitStr32[len(bitStr32)-1][len(bitStr32[len(bitStr32)-1])-2] = bitStr2dec(lenBitStr[32:64])
bitStr32[len(bitStr32)-1][len(bitStr32[len(bitStr32)-1])-1] = bitStr2dec(lenBitStr[0:32])
return bitStr32
}
func md5Loop(plain string) string {
A := 0x67452301
B := 0xefcdab89
C := 0x98badcfe
D := 0x10325476
bitStr32Arr := plain2bit(plain)
for _, item := range bitStr32Arr {
a := A
b := B
c := C
d := D
a = ff(a, b, c, d, item[0], SFF[0], T[0])
d = ff(d, a, b, c, item[1], SFF[1], T[1])
c = ff(c, d, a, b, item[2], SFF[2], T[2])
b = ff(b, c, d, a, item[3], SFF[3], T[3])
a = ff(a, b, c, d, item[4], SFF[0], T[4])
d = ff(d, a, b, c, item[5], SFF[1], T[5])
c = ff(c, d, a, b, item[6], SFF[2], T[6])
b = ff(b, c, d, a, item[7], SFF[3], T[7])
a = ff(a, b, c, d, item[8], SFF[0], T[8])
d = ff(d, a, b, c, item[9], SFF[1], T[9])
c = ff(c, d, a, b, item[10], SFF[2], T[10])
b = ff(b, c, d, a, item[11], SFF[3], T[11])
a = ff(a, b, c, d, item[12], SFF[0], T[12])
d = ff(d, a, b, c, item[13], SFF[1], T[13])
c = ff(c, d, a, b, item[14], SFF[2], T[14])
b = ff(b, c, d, a, item[15], SFF[3], T[15])
a = gg(a, b, c, d, item[1], SGG[0], T[0+16])
d = gg(d, a, b, c, item[6], SGG[1], T[1+16])
c = gg(c, d, a, b, item[11], SGG[2], T[2+16])
b = gg(b, c, d, a, item[0], SGG[3], T[3+16])
a = gg(a, b, c, d, item[5], SGG[0], T[4+16])
d = gg(d, a, b, c, item[10], SGG[1], T[5+16])
c = gg(c, d, a, b, item[15], SGG[2], T[6+16])
b = gg(b, c, d, a, item[4], SGG[3], T[7+16])
a = gg(a, b, c, d, item[9], SGG[0], T[8+16])
d = gg(d, a, b, c, item[14], SGG[1], T[9+16])
c = gg(c, d, a, b, item[3], SGG[2], T[10+16])
b = gg(b, c, d, a, item[8], SGG[3], T[11+16])
a = gg(a, b, c, d, item[13], SGG[0], T[12+16])
d = gg(d, a, b, c, item[2], SGG[1], T[13+16])
c = gg(c, d, a, b, item[7], SGG[2], T[14+16])
b = gg(b, c, d, a, item[12], SGG[3], T[15+16])
a = hh(a, b, c, d, item[5], SHH[0], T[0+16*2])
d = hh(d, a, b, c, item[8], SHH[1], T[1+16*2])
c = hh(c, d, a, b, item[11], SHH[2], T[2+16*2])
b = hh(b, c, d, a, item[14], SHH[3], T[3+16*2])
a = hh(a, b, c, d, item[1], SHH[0], T[4+16*2])
d = hh(d, a, b, c, item[4], SHH[1], T[5+16*2])
c = hh(c, d, a, b, item[7], SHH[2], T[6+16*2])
b = hh(b, c, d, a, item[10], SHH[3], T[7+16*2])
a = hh(a, b, c, d, item[13], SHH[0], T[8+16*2])
d = hh(d, a, b, c, item[0], SHH[1], T[9+16*2])
c = hh(c, d, a, b, item[3], SHH[2], T[10+16*2])
b = hh(b, c, d, a, item[6], SHH[3], T[11+16*2])
a = hh(a, b, c, d, item[9], SHH[0], T[12+16*2])
d = hh(d, a, b, c, item[12], SHH[1], T[13+16*2])
c = hh(c, d, a, b, item[15], SHH[2], T[14+16*2])
b = hh(b, c, d, a, item[2], SHH[3], T[15+16*2])
a = ii(a, b, c, d, item[0], SII[0], T[0+16*3])
d = ii(d, a, b, c, item[7], SII[1], T[1+16*3])
c = ii(c, d, a, b, item[14], SII[2], T[2+16*3])
b = ii(b, c, d, a, item[5], SII[3], T[3+16*3])
a = ii(a, b, c, d, item[12], SII[0], T[4+16*3])
d = ii(d, a, b, c, item[3], SII[1], T[5+16*3])
c = ii(c, d, a, b, item[10], SII[2], T[6+16*3])
b = ii(b, c, d, a, item[1], SII[3], T[7+16*3])
a = ii(a, b, c, d, item[8], SII[0], T[8+16*3])
d = ii(d, a, b, c, item[15], SII[1], T[9+16*3])
c = ii(c, d, a, b, item[6], SII[2], T[10+16*3])
b = ii(b, c, d, a, item[13], SII[3], T[11+16*3])
a = ii(a, b, c, d, item[4], SII[0], T[12+16*3])
d = ii(d, a, b, c, item[11], SII[1], T[13+16*3])
c = ii(c, d, a, b, item[2], SII[2], T[14+16*3])
b = ii(b, c, d, a, item[9], SII[3], T[15+16*3])
A = (a + A) & Int32Max
B = (b + B) & Int32Max
C = (c + C) & Int32Max
D = (d + D) & Int32Max
}
aBinStr := littleEndian(dec2bitStr(A, 32))
bBinStr := littleEndian(dec2bitStr(B, 32))
cBinStr := littleEndian(dec2bitStr(C, 32))
dBinStr := littleEndian(dec2bitStr(D, 32))
md5BinStr := aBinStr + bBinStr + cBinStr + dBinStr
md5HexStr := strBin2Hex(md5BinStr)
return md5HexStr
}
func strBin2Hex(str string) string {
hexStr := ""
bin2hex := map[string]string{
"0000": "0", "0001": "1", "0010": "2", "0011": "3",
"0100": "4", "0101": "5", "0110": "6", "0111": "7",
"1000": "8", "1001": "9", "1010": "a", "1011": "b",
"1100": "c", "1101": "d", "1110": "e", "1111": "f",
}
for i := 0; i < len(str)/4; i++ {
hexStr += bin2hex[str[i*4:(i+1)*4]]
}
return hexStr
}
func main() {
str := ""
fmt.Print("Please input a string to md5 encrypt: ")
_, err := fmt.Scanln(&str)
if err != nil {
return
}
res := md5Loop(str)
fmt.Println(res)
}