1
2
3
4
5
6
7
8
9 package sha1
10
11 import (
12 "crypto"
13 "crypto/internal/boring"
14 "errors"
15 "hash"
16 "internal/byteorder"
17 )
18
19 func init() {
20 crypto.RegisterHash(crypto.SHA1, New)
21 }
22
23
24 const Size = 20
25
26
27 const BlockSize = 64
28
29 const (
30 chunk = 64
31 init0 = 0x67452301
32 init1 = 0xEFCDAB89
33 init2 = 0x98BADCFE
34 init3 = 0x10325476
35 init4 = 0xC3D2E1F0
36 )
37
38
39 type digest struct {
40 h [5]uint32
41 x [chunk]byte
42 nx int
43 len uint64
44 }
45
46 const (
47 magic = "sha\x01"
48 marshaledSize = len(magic) + 5*4 + chunk + 8
49 )
50
51 func (d *digest) MarshalBinary() ([]byte, error) {
52 return d.AppendBinary(make([]byte, 0, marshaledSize))
53 }
54
55 func (d *digest) AppendBinary(b []byte) ([]byte, error) {
56 b = append(b, magic...)
57 b = byteorder.BeAppendUint32(b, d.h[0])
58 b = byteorder.BeAppendUint32(b, d.h[1])
59 b = byteorder.BeAppendUint32(b, d.h[2])
60 b = byteorder.BeAppendUint32(b, d.h[3])
61 b = byteorder.BeAppendUint32(b, d.h[4])
62 b = append(b, d.x[:d.nx]...)
63 b = append(b, make([]byte, len(d.x)-d.nx)...)
64 b = byteorder.BeAppendUint64(b, d.len)
65 return b, nil
66 }
67
68 func (d *digest) UnmarshalBinary(b []byte) error {
69 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
70 return errors.New("crypto/sha1: invalid hash state identifier")
71 }
72 if len(b) != marshaledSize {
73 return errors.New("crypto/sha1: invalid hash state size")
74 }
75 b = b[len(magic):]
76 b, d.h[0] = consumeUint32(b)
77 b, d.h[1] = consumeUint32(b)
78 b, d.h[2] = consumeUint32(b)
79 b, d.h[3] = consumeUint32(b)
80 b, d.h[4] = consumeUint32(b)
81 b = b[copy(d.x[:], b):]
82 b, d.len = consumeUint64(b)
83 d.nx = int(d.len % chunk)
84 return nil
85 }
86
87 func consumeUint64(b []byte) ([]byte, uint64) {
88 return b[8:], byteorder.BeUint64(b)
89 }
90
91 func consumeUint32(b []byte) ([]byte, uint32) {
92 return b[4:], byteorder.BeUint32(b)
93 }
94
95 func (d *digest) Reset() {
96 d.h[0] = init0
97 d.h[1] = init1
98 d.h[2] = init2
99 d.h[3] = init3
100 d.h[4] = init4
101 d.nx = 0
102 d.len = 0
103 }
104
105
106
107
108
109 func New() hash.Hash {
110 if boring.Enabled {
111 return boring.NewSHA1()
112 }
113 d := new(digest)
114 d.Reset()
115 return d
116 }
117
118 func (d *digest) Size() int { return Size }
119
120 func (d *digest) BlockSize() int { return BlockSize }
121
122 func (d *digest) Write(p []byte) (nn int, err error) {
123 boring.Unreachable()
124 nn = len(p)
125 d.len += uint64(nn)
126 if d.nx > 0 {
127 n := copy(d.x[d.nx:], p)
128 d.nx += n
129 if d.nx == chunk {
130 block(d, d.x[:])
131 d.nx = 0
132 }
133 p = p[n:]
134 }
135 if len(p) >= chunk {
136 n := len(p) &^ (chunk - 1)
137 block(d, p[:n])
138 p = p[n:]
139 }
140 if len(p) > 0 {
141 d.nx = copy(d.x[:], p)
142 }
143 return
144 }
145
146 func (d *digest) Sum(in []byte) []byte {
147 boring.Unreachable()
148
149 d0 := *d
150 hash := d0.checkSum()
151 return append(in, hash[:]...)
152 }
153
154 func (d *digest) checkSum() [Size]byte {
155 len := d.len
156
157 var tmp [64 + 8]byte
158 tmp[0] = 0x80
159 var t uint64
160 if len%64 < 56 {
161 t = 56 - len%64
162 } else {
163 t = 64 + 56 - len%64
164 }
165
166
167 len <<= 3
168 padlen := tmp[:t+8]
169 byteorder.BePutUint64(padlen[t:], len)
170 d.Write(padlen)
171
172 if d.nx != 0 {
173 panic("d.nx != 0")
174 }
175
176 var digest [Size]byte
177
178 byteorder.BePutUint32(digest[0:], d.h[0])
179 byteorder.BePutUint32(digest[4:], d.h[1])
180 byteorder.BePutUint32(digest[8:], d.h[2])
181 byteorder.BePutUint32(digest[12:], d.h[3])
182 byteorder.BePutUint32(digest[16:], d.h[4])
183
184 return digest
185 }
186
187
188 func (d *digest) ConstantTimeSum(in []byte) []byte {
189 d0 := *d
190 hash := d0.constSum()
191 return append(in, hash[:]...)
192 }
193
194 func (d *digest) constSum() [Size]byte {
195 var length [8]byte
196 l := d.len << 3
197 for i := uint(0); i < 8; i++ {
198 length[i] = byte(l >> (56 - 8*i))
199 }
200
201 nx := byte(d.nx)
202 t := nx - 56
203 mask1b := byte(int8(t) >> 7)
204
205 separator := byte(0x80)
206 for i := byte(0); i < chunk; i++ {
207 mask := byte(int8(i-nx) >> 7)
208
209
210 d.x[i] = (^mask & separator) | (mask & d.x[i])
211
212
213 separator &= mask
214
215 if i >= 56 {
216
217 d.x[i] |= mask1b & length[i-56]
218 }
219 }
220
221
222 block(d, d.x[:])
223
224 var digest [Size]byte
225 for i, s := range d.h {
226 digest[i*4] = mask1b & byte(s>>24)
227 digest[i*4+1] = mask1b & byte(s>>16)
228 digest[i*4+2] = mask1b & byte(s>>8)
229 digest[i*4+3] = mask1b & byte(s)
230 }
231
232 for i := byte(0); i < chunk; i++ {
233
234 if i < 56 {
235 d.x[i] = separator
236 separator = 0
237 } else {
238 d.x[i] = length[i-56]
239 }
240 }
241
242
243 block(d, d.x[:])
244
245 for i, s := range d.h {
246 digest[i*4] |= ^mask1b & byte(s>>24)
247 digest[i*4+1] |= ^mask1b & byte(s>>16)
248 digest[i*4+2] |= ^mask1b & byte(s>>8)
249 digest[i*4+3] |= ^mask1b & byte(s)
250 }
251
252 return digest
253 }
254
255
256 func Sum(data []byte) [Size]byte {
257 if boring.Enabled {
258 return boring.SHA1(data)
259 }
260 var d digest
261 d.Reset()
262 d.Write(data)
263 return d.checkSum()
264 }
265
View as plain text