新建 md5.go 文件,代码如下:
package main
import(
"fmt"
"crypto/md5"
"encoding/hex"
)
func main(){
data := []byte("hello world")
s := fmt.Sprintf("%x", md5.Sum(data))
fmt.Println(s)
// 也可以用这种方式
h := md5.New()
h.Write(data)
s = hex.EncodeToString(h.Sum(nil))
fmt.Println(s)
}
--------
运行结果
go run md5.go
5eb63bbbe01eeed093cb22bb8f5acdc3
5eb63bbbe01eeed093cb22bb8f5acdc3
**
md5 实现原理
**
1.对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
2.记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
3.装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301,B=0XEFCDAB89,C=0X98BADCFE,D=0X10325476)
4.四轮循环运算:循环的次数是分组的个数(N+1)
1.将每一512字节细分成16个小组,每个小组64位(8个字节)
2.先认识四个线性函数(&是与,|是或,^是异或)
F(X,Y,Z)=(Y ^ Z) & X) ^ Z
G(X,Y,Z)=((X ^ Y) & Z) ^ Y
H(X,Y,Z)=X ^ Y ^ Z
I(X,Y,Z)=Y ^ (X | ^Z)
完整代码
package main
import(
"fmt"
"unsafe"
)
const Size = 16
const (
chunk = 64
init0 = 0x67452301
init1 = 0xEFCDAB89
init2 = 0x98BADCFE
init3 = 0x10325476
)
// digest represents the partial evaluation of a checksum.
type digest struct {
s [4]uint32
x [chunk]byte
nx int
len uint64
}
func (d *digest) Reset() {
d.s[0] = init0
d.s[1] = init1
d.s[2] = init2
d.s[3] = init3
d.nx = 0
d.len = 0
}
func (d *digest) Write(p []byte) (nn int, err error) {
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
n := copy(d.x[d.nx:], p)
d.nx += n
if d.nx == chunk {
blockGeneric(d, d.x[:])
d.nx = 0
}
p = p[n:]
}
if len(p) >= chunk {
n := len(p) &^ (chunk - 1)
blockGeneric(d, p[:n])
p = p[n:]
}
if len(p) > 0 {
d.nx = copy(d.x[:], p)
}
fmt.Printf("%v\n",d)
return
}
func (d *digest) checkSum() [Size]byte {
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len
var tmp [64]byte
tmp[0] = 0x80
if len%64 < 56 {
d.Write(tmp[0 : 56-len%64])
fmt.Printf("%v",d)
} else {
d.Write(tmp[0 : 64+56-len%64])
}
// Length in bits.
len <<= 3
for i := uint(0); i < 8; i++ {
tmp[i] = byte(len >> (8 * i))
}
d.Write(tmp[0:8])
if d.nx != 0 {
panic("d.nx != 0")
}
var digest [Size]byte
for i, s := range d.s {
digest[i*4] = byte(s)
digest[i*4+1] = byte(s >> 8)
digest[i*4+2] = byte(s >> 16)
digest[i*4+3] = byte(s >> 24)
}
return digest
}
fu