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