]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha1/sha1.go
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
[gostls13.git] / src / crypto / sha1 / sha1.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
6 //
7 // SHA-1 is cryptographically broken and should not be used for secure
8 // applications.
9 package sha1
10
11 import (
12         "crypto"
13         "errors"
14         "hash"
15 )
16
17 func init() {
18         crypto.RegisterHash(crypto.SHA1, New)
19 }
20
21 // The size of a SHA-1 checksum in bytes.
22 const Size = 20
23
24 // The blocksize of SHA-1 in bytes.
25 const BlockSize = 64
26
27 const (
28         chunk = 64
29         init0 = 0x67452301
30         init1 = 0xEFCDAB89
31         init2 = 0x98BADCFE
32         init3 = 0x10325476
33         init4 = 0xC3D2E1F0
34 )
35
36 // digest represents the partial evaluation of a checksum.
37 type digest struct {
38         h   [5]uint32
39         x   [chunk]byte
40         nx  int
41         len uint64
42 }
43
44 const (
45         magic         = "sha\x01"
46         marshaledSize = len(magic) + 5*4 + chunk + 8
47 )
48
49 func (d *digest) MarshalBinary() ([]byte, error) {
50         b := make([]byte, 0, marshaledSize)
51         b = append(b, magic...)
52         b = appendUint32(b, d.h[0])
53         b = appendUint32(b, d.h[1])
54         b = appendUint32(b, d.h[2])
55         b = appendUint32(b, d.h[3])
56         b = appendUint32(b, d.h[4])
57         b = append(b, d.x[:]...)
58         b = appendUint64(b, d.len)
59         return b, nil
60 }
61
62 func (d *digest) UnmarshalBinary(b []byte) error {
63         if len(b) < len(magic) || string(b[:len(magic)]) != magic {
64                 return errors.New("crypto/sha1: invalid hash state identifier")
65         }
66         if len(b) != marshaledSize {
67                 return errors.New("crypto/sha1: invalid hash state size")
68         }
69         b = b[len(magic):]
70         b, d.h[0] = consumeUint32(b)
71         b, d.h[1] = consumeUint32(b)
72         b, d.h[2] = consumeUint32(b)
73         b, d.h[3] = consumeUint32(b)
74         b, d.h[4] = consumeUint32(b)
75         b = b[copy(d.x[:], b):]
76         b, d.len = consumeUint64(b)
77         d.nx = int(d.len) % chunk
78         return nil
79 }
80
81 func appendUint64(b []byte, x uint64) []byte {
82         var a [8]byte
83         putUint64(a[:], x)
84         return append(b, a[:]...)
85 }
86
87 func appendUint32(b []byte, x uint32) []byte {
88         var a [4]byte
89         putUint32(a[:], x)
90         return append(b, a[:]...)
91 }
92
93 func consumeUint64(b []byte) ([]byte, uint64) {
94         _ = b[7]
95         x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
96                 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
97         return b[8:], x
98 }
99
100 func consumeUint32(b []byte) ([]byte, uint32) {
101         _ = b[3]
102         x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
103         return b[4:], x
104 }
105
106 func (d *digest) Reset() {
107         d.h[0] = init0
108         d.h[1] = init1
109         d.h[2] = init2
110         d.h[3] = init3
111         d.h[4] = init4
112         d.nx = 0
113         d.len = 0
114 }
115
116 // New returns a new hash.Hash computing the SHA1 checksum. The Hash also
117 // implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
118 // marshal and unmarshal the internal state of the hash.
119 func New() hash.Hash {
120         if boringEnabled {
121                 return boringNewSHA1()
122         }
123         d := new(digest)
124         d.Reset()
125         return d
126 }
127
128 func (d *digest) Size() int { return Size }
129
130 func (d *digest) BlockSize() int { return BlockSize }
131
132 func (d *digest) Write(p []byte) (nn int, err error) {
133         boringUnreachable()
134         nn = len(p)
135         d.len += uint64(nn)
136         if d.nx > 0 {
137                 n := copy(d.x[d.nx:], p)
138                 d.nx += n
139                 if d.nx == chunk {
140                         block(d, d.x[:])
141                         d.nx = 0
142                 }
143                 p = p[n:]
144         }
145         if len(p) >= chunk {
146                 n := len(p) &^ (chunk - 1)
147                 block(d, p[:n])
148                 p = p[n:]
149         }
150         if len(p) > 0 {
151                 d.nx = copy(d.x[:], p)
152         }
153         return
154 }
155
156 func (d0 *digest) Sum(in []byte) []byte {
157         boringUnreachable()
158         // Make a copy of d0 so that caller can keep writing and summing.
159         d := *d0
160         hash := d.checkSum()
161         return append(in, hash[:]...)
162 }
163
164 func (d *digest) checkSum() [Size]byte {
165         len := d.len
166         // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
167         var tmp [64]byte
168         tmp[0] = 0x80
169         if len%64 < 56 {
170                 d.Write(tmp[0 : 56-len%64])
171         } else {
172                 d.Write(tmp[0 : 64+56-len%64])
173         }
174
175         // Length in bits.
176         len <<= 3
177         putUint64(tmp[:], len)
178         d.Write(tmp[0:8])
179
180         if d.nx != 0 {
181                 panic("d.nx != 0")
182         }
183
184         var digest [Size]byte
185
186         putUint32(digest[0:], d.h[0])
187         putUint32(digest[4:], d.h[1])
188         putUint32(digest[8:], d.h[2])
189         putUint32(digest[12:], d.h[3])
190         putUint32(digest[16:], d.h[4])
191
192         return digest
193 }
194
195 // ConstantTimeSum computes the same result of Sum() but in constant time
196 func (d0 *digest) ConstantTimeSum(in []byte) []byte {
197         d := *d0
198         hash := d.constSum()
199         return append(in, hash[:]...)
200 }
201
202 func (d *digest) constSum() [Size]byte {
203         var length [8]byte
204         l := d.len << 3
205         for i := uint(0); i < 8; i++ {
206                 length[i] = byte(l >> (56 - 8*i))
207         }
208
209         nx := byte(d.nx)
210         t := nx - 56                 // if nx < 56 then the MSB of t is one
211         mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough
212
213         separator := byte(0x80) // gets reset to 0x00 once used
214         for i := byte(0); i < chunk; i++ {
215                 mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data
216
217                 // if we reached the end of the data, replace with 0x80 or 0x00
218                 d.x[i] = (^mask & separator) | (mask & d.x[i])
219
220                 // zero the separator once used
221                 separator &= mask
222
223                 if i >= 56 {
224                         // we might have to write the length here if all fit in one block
225                         d.x[i] |= mask1b & length[i-56]
226                 }
227         }
228
229         // compress, and only keep the digest if all fit in one block
230         block(d, d.x[:])
231
232         var digest [Size]byte
233         for i, s := range d.h {
234                 digest[i*4] = mask1b & byte(s>>24)
235                 digest[i*4+1] = mask1b & byte(s>>16)
236                 digest[i*4+2] = mask1b & byte(s>>8)
237                 digest[i*4+3] = mask1b & byte(s)
238         }
239
240         for i := byte(0); i < chunk; i++ {
241                 // second block, it's always past the end of data, might start with 0x80
242                 if i < 56 {
243                         d.x[i] = separator
244                         separator = 0
245                 } else {
246                         d.x[i] = length[i-56]
247                 }
248         }
249
250         // compress, and only keep the digest if we actually needed the second block
251         block(d, d.x[:])
252
253         for i, s := range d.h {
254                 digest[i*4] |= ^mask1b & byte(s>>24)
255                 digest[i*4+1] |= ^mask1b & byte(s>>16)
256                 digest[i*4+2] |= ^mask1b & byte(s>>8)
257                 digest[i*4+3] |= ^mask1b & byte(s)
258         }
259
260         return digest
261 }
262
263 // Sum returns the SHA-1 checksum of the data.
264 func Sum(data []byte) [Size]byte {
265         if boringEnabled {
266                 h := New()
267                 h.Write(data)
268                 var ret [Size]byte
269                 h.Sum(ret[:0])
270                 return ret
271         }
272         var d digest
273         d.Reset()
274         d.Write(data)
275         return d.checkSum()
276 }
277
278 func putUint64(x []byte, s uint64) {
279         _ = x[7]
280         x[0] = byte(s >> 56)
281         x[1] = byte(s >> 48)
282         x[2] = byte(s >> 40)
283         x[3] = byte(s >> 32)
284         x[4] = byte(s >> 24)
285         x[5] = byte(s >> 16)
286         x[6] = byte(s >> 8)
287         x[7] = byte(s)
288 }
289
290 func putUint32(x []byte, s uint32) {
291         _ = x[3]
292         x[0] = byte(s >> 24)
293         x[1] = byte(s >> 16)
294         x[2] = byte(s >> 8)
295         x[3] = byte(s)
296 }