1
2
3
4
5
6
7
8
9
10
11 package md5
12
13 import (
14 "crypto"
15 "errors"
16 "hash"
17 "internal/byteorder"
18 )
19
20 func init() {
21 crypto.RegisterHash(crypto.MD5, New)
22 }
23
24
25 const Size = 16
26
27
28 const BlockSize = 64
29
30 const (
31 init0 = 0x67452301
32 init1 = 0xEFCDAB89
33 init2 = 0x98BADCFE
34 init3 = 0x10325476
35 )
36
37
38 type digest struct {
39 s [4]uint32
40 x [BlockSize]byte
41 nx int
42 len uint64
43 }
44
45 func (d *digest) Reset() {
46 d.s[0] = init0
47 d.s[1] = init1
48 d.s[2] = init2
49 d.s[3] = init3
50 d.nx = 0
51 d.len = 0
52 }
53
54 const (
55 magic = "md5\x01"
56 marshaledSize = len(magic) + 4*4 + BlockSize + 8
57 )
58
59 func (d *digest) MarshalBinary() ([]byte, error) {
60 b := make([]byte, 0, marshaledSize)
61 b = append(b, magic...)
62 b = byteorder.BeAppendUint32(b, d.s[0])
63 b = byteorder.BeAppendUint32(b, d.s[1])
64 b = byteorder.BeAppendUint32(b, d.s[2])
65 b = byteorder.BeAppendUint32(b, d.s[3])
66 b = append(b, d.x[:d.nx]...)
67 b = b[:len(b)+len(d.x)-d.nx]
68 b = byteorder.BeAppendUint64(b, d.len)
69 return b, nil
70 }
71
72 func (d *digest) UnmarshalBinary(b []byte) error {
73 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
74 return errors.New("crypto/md5: invalid hash state identifier")
75 }
76 if len(b) != marshaledSize {
77 return errors.New("crypto/md5: invalid hash state size")
78 }
79 b = b[len(magic):]
80 b, d.s[0] = consumeUint32(b)
81 b, d.s[1] = consumeUint32(b)
82 b, d.s[2] = consumeUint32(b)
83 b, d.s[3] = consumeUint32(b)
84 b = b[copy(d.x[:], b):]
85 b, d.len = consumeUint64(b)
86 d.nx = int(d.len % BlockSize)
87 return nil
88 }
89
90 func consumeUint64(b []byte) ([]byte, uint64) {
91 return b[8:], byteorder.BeUint64(b[0:8])
92 }
93
94 func consumeUint32(b []byte) ([]byte, uint32) {
95 return b[4:], byteorder.BeUint32(b[0:4])
96 }
97
98
99
100
101 func New() hash.Hash {
102 d := new(digest)
103 d.Reset()
104 return d
105 }
106
107 func (d *digest) Size() int { return Size }
108
109 func (d *digest) BlockSize() int { return BlockSize }
110
111 func (d *digest) Write(p []byte) (nn int, err error) {
112
113
114
115 nn = len(p)
116 d.len += uint64(nn)
117 if d.nx > 0 {
118 n := copy(d.x[d.nx:], p)
119 d.nx += n
120 if d.nx == BlockSize {
121 if haveAsm {
122 block(d, d.x[:])
123 } else {
124 blockGeneric(d, d.x[:])
125 }
126 d.nx = 0
127 }
128 p = p[n:]
129 }
130 if len(p) >= BlockSize {
131 n := len(p) &^ (BlockSize - 1)
132 if haveAsm {
133 block(d, p[:n])
134 } else {
135 blockGeneric(d, p[:n])
136 }
137 p = p[n:]
138 }
139 if len(p) > 0 {
140 d.nx = copy(d.x[:], p)
141 }
142 return
143 }
144
145 func (d *digest) Sum(in []byte) []byte {
146
147 d0 := *d
148 hash := d0.checkSum()
149 return append(in, hash[:]...)
150 }
151
152 func (d *digest) checkSum() [Size]byte {
153
154
155
156
157
158 tmp := [1 + 63 + 8]byte{0x80}
159 pad := (55 - d.len) % 64
160 byteorder.LePutUint64(tmp[1+pad:], d.len<<3)
161 d.Write(tmp[:1+pad+8])
162
163
164
165 if d.nx != 0 {
166 panic("d.nx != 0")
167 }
168
169 var digest [Size]byte
170 byteorder.LePutUint32(digest[0:], d.s[0])
171 byteorder.LePutUint32(digest[4:], d.s[1])
172 byteorder.LePutUint32(digest[8:], d.s[2])
173 byteorder.LePutUint32(digest[12:], d.s[3])
174 return digest
175 }
176
177
178 func Sum(data []byte) [Size]byte {
179 var d digest
180 d.Reset()
181 d.Write(data)
182 return d.checkSum()
183 }
184
View as plain text