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