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