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 return d.AppendBinary(make([]byte, 0, marshaledSize))
61 }
62
63 func (d *digest) AppendBinary(b []byte) ([]byte, error) {
64 b = append(b, magic...)
65 b = byteorder.BeAppendUint32(b, d.s[0])
66 b = byteorder.BeAppendUint32(b, d.s[1])
67 b = byteorder.BeAppendUint32(b, d.s[2])
68 b = byteorder.BeAppendUint32(b, d.s[3])
69 b = append(b, d.x[:d.nx]...)
70 b = append(b, make([]byte, len(d.x)-d.nx)...)
71 b = byteorder.BeAppendUint64(b, d.len)
72 return b, nil
73 }
74
75 func (d *digest) UnmarshalBinary(b []byte) error {
76 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
77 return errors.New("crypto/md5: invalid hash state identifier")
78 }
79 if len(b) != marshaledSize {
80 return errors.New("crypto/md5: invalid hash state size")
81 }
82 b = b[len(magic):]
83 b, d.s[0] = consumeUint32(b)
84 b, d.s[1] = consumeUint32(b)
85 b, d.s[2] = consumeUint32(b)
86 b, d.s[3] = consumeUint32(b)
87 b = b[copy(d.x[:], b):]
88 b, d.len = consumeUint64(b)
89 d.nx = int(d.len % BlockSize)
90 return nil
91 }
92
93 func consumeUint64(b []byte) ([]byte, uint64) {
94 return b[8:], byteorder.BeUint64(b[0:8])
95 }
96
97 func consumeUint32(b []byte) ([]byte, uint32) {
98 return b[4:], byteorder.BeUint32(b[0:4])
99 }
100
101
102
103
104
105 func New() hash.Hash {
106 d := new(digest)
107 d.Reset()
108 return d
109 }
110
111 func (d *digest) Size() int { return Size }
112
113 func (d *digest) BlockSize() int { return BlockSize }
114
115 func (d *digest) Write(p []byte) (nn int, err error) {
116
117
118
119 nn = len(p)
120 d.len += uint64(nn)
121 if d.nx > 0 {
122 n := copy(d.x[d.nx:], p)
123 d.nx += n
124 if d.nx == BlockSize {
125 if haveAsm {
126 block(d, d.x[:])
127 } else {
128 blockGeneric(d, d.x[:])
129 }
130 d.nx = 0
131 }
132 p = p[n:]
133 }
134 if len(p) >= BlockSize {
135 n := len(p) &^ (BlockSize - 1)
136 if haveAsm {
137 block(d, p[:n])
138 } else {
139 blockGeneric(d, p[:n])
140 }
141 p = p[n:]
142 }
143 if len(p) > 0 {
144 d.nx = copy(d.x[:], p)
145 }
146 return
147 }
148
149 func (d *digest) Sum(in []byte) []byte {
150
151 d0 := *d
152 hash := d0.checkSum()
153 return append(in, hash[:]...)
154 }
155
156 func (d *digest) checkSum() [Size]byte {
157
158
159
160
161
162 tmp := [1 + 63 + 8]byte{0x80}
163 pad := (55 - d.len) % 64
164 byteorder.LePutUint64(tmp[1+pad:], d.len<<3)
165 d.Write(tmp[:1+pad+8])
166
167
168
169 if d.nx != 0 {
170 panic("d.nx != 0")
171 }
172
173 var digest [Size]byte
174 byteorder.LePutUint32(digest[0:], d.s[0])
175 byteorder.LePutUint32(digest[4:], d.s[1])
176 byteorder.LePutUint32(digest[8:], d.s[2])
177 byteorder.LePutUint32(digest[12:], d.s[3])
178 return digest
179 }
180
181
182 func Sum(data []byte) [Size]byte {
183 var d digest
184 d.Reset()
185 d.Write(data)
186 return d.checkSum()
187 }
188
View as plain text