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