]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha1/sha1.go
[dev.boringcrypto] misc/boring: add go1.9.2b4 release
[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         "hash"
14 )
15
16 func init() {
17         crypto.RegisterHash(crypto.SHA1, New)
18 }
19
20 // The size of a SHA-1 checksum in bytes.
21 const Size = 20
22
23 // The blocksize of SHA-1 in bytes.
24 const BlockSize = 64
25
26 const (
27         chunk = 64
28         init0 = 0x67452301
29         init1 = 0xEFCDAB89
30         init2 = 0x98BADCFE
31         init3 = 0x10325476
32         init4 = 0xC3D2E1F0
33 )
34
35 // digest represents the partial evaluation of a checksum.
36 type digest struct {
37         h   [5]uint32
38         x   [chunk]byte
39         nx  int
40         len uint64
41 }
42
43 func (d *digest) Reset() {
44         d.h[0] = init0
45         d.h[1] = init1
46         d.h[2] = init2
47         d.h[3] = init3
48         d.h[4] = init4
49         d.nx = 0
50         d.len = 0
51 }
52
53 // New returns a new hash.Hash computing the SHA1 checksum.
54 func New() hash.Hash {
55         if boringEnabled {
56                 return boringNewSHA1()
57         }
58         d := new(digest)
59         d.Reset()
60         return d
61 }
62
63 func (d *digest) Size() int { return Size }
64
65 func (d *digest) BlockSize() int { return BlockSize }
66
67 func (d *digest) Write(p []byte) (nn int, err error) {
68         boringUnreachable()
69         nn = len(p)
70         d.len += uint64(nn)
71         if d.nx > 0 {
72                 n := copy(d.x[d.nx:], p)
73                 d.nx += n
74                 if d.nx == chunk {
75                         block(d, d.x[:])
76                         d.nx = 0
77                 }
78                 p = p[n:]
79         }
80         if len(p) >= chunk {
81                 n := len(p) &^ (chunk - 1)
82                 block(d, p[:n])
83                 p = p[n:]
84         }
85         if len(p) > 0 {
86                 d.nx = copy(d.x[:], p)
87         }
88         return
89 }
90
91 func (d0 *digest) Sum(in []byte) []byte {
92         boringUnreachable()
93         // Make a copy of d0 so that caller can keep writing and summing.
94         d := *d0
95         hash := d.checkSum()
96         return append(in, hash[:]...)
97 }
98
99 func (d *digest) checkSum() [Size]byte {
100         len := d.len
101         // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
102         var tmp [64]byte
103         tmp[0] = 0x80
104         if len%64 < 56 {
105                 d.Write(tmp[0 : 56-len%64])
106         } else {
107                 d.Write(tmp[0 : 64+56-len%64])
108         }
109
110         // Length in bits.
111         len <<= 3
112         for i := uint(0); i < 8; i++ {
113                 tmp[i] = byte(len >> (56 - 8*i))
114         }
115         d.Write(tmp[0:8])
116
117         if d.nx != 0 {
118                 panic("d.nx != 0")
119         }
120
121         var digest [Size]byte
122         for i, s := range d.h {
123                 digest[i*4] = byte(s >> 24)
124                 digest[i*4+1] = byte(s >> 16)
125                 digest[i*4+2] = byte(s >> 8)
126                 digest[i*4+3] = byte(s)
127         }
128
129         return digest
130 }
131
132 // ConstantTimeSum computes the same result of Sum() but in constant time
133 func (d0 *digest) ConstantTimeSum(in []byte) []byte {
134         d := *d0
135         hash := d.constSum()
136         return append(in, hash[:]...)
137 }
138
139 func (d *digest) constSum() [Size]byte {
140         var length [8]byte
141         l := d.len << 3
142         for i := uint(0); i < 8; i++ {
143                 length[i] = byte(l >> (56 - 8*i))
144         }
145
146         nx := byte(d.nx)
147         t := nx - 56                 // if nx < 56 then the MSB of t is one
148         mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough
149
150         separator := byte(0x80) // gets reset to 0x00 once used
151         for i := byte(0); i < chunk; i++ {
152                 mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data
153
154                 // if we reached the end of the data, replace with 0x80 or 0x00
155                 d.x[i] = (^mask & separator) | (mask & d.x[i])
156
157                 // zero the separator once used
158                 separator &= mask
159
160                 if i >= 56 {
161                         // we might have to write the length here if all fit in one block
162                         d.x[i] |= mask1b & length[i-56]
163                 }
164         }
165
166         // compress, and only keep the digest if all fit in one block
167         block(d, d.x[:])
168
169         var digest [Size]byte
170         for i, s := range d.h {
171                 digest[i*4] = mask1b & byte(s>>24)
172                 digest[i*4+1] = mask1b & byte(s>>16)
173                 digest[i*4+2] = mask1b & byte(s>>8)
174                 digest[i*4+3] = mask1b & byte(s)
175         }
176
177         for i := byte(0); i < chunk; i++ {
178                 // second block, it's always past the end of data, might start with 0x80
179                 if i < 56 {
180                         d.x[i] = separator
181                         separator = 0
182                 } else {
183                         d.x[i] = length[i-56]
184                 }
185         }
186
187         // compress, and only keep the digest if we actually needed the second block
188         block(d, d.x[:])
189
190         for i, s := range d.h {
191                 digest[i*4] |= ^mask1b & byte(s>>24)
192                 digest[i*4+1] |= ^mask1b & byte(s>>16)
193                 digest[i*4+2] |= ^mask1b & byte(s>>8)
194                 digest[i*4+3] |= ^mask1b & byte(s)
195         }
196
197         return digest
198 }
199
200 // Sum returns the SHA-1 checksum of the data.
201 func Sum(data []byte) [Size]byte {
202         if boringEnabled {
203                 h := New()
204                 h.Write(data)
205                 var ret [Size]byte
206                 h.Sum(ret[:0])
207                 return ret
208         }
209         var d digest
210         d.Reset()
211         d.Write(data)
212         return d.checkSum()
213 }