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 d := new(digest)
123 d.Reset()
124 return d
125 }
126
127 func (d *digest) Size() int { return Size }
128
129 func (d *digest) BlockSize() int { return BlockSize }
130
131 func (d *digest) Write(p []byte) (nn int, err error) {
132 nn = len(p)
133 d.len += uint64(nn)
134 if d.nx > 0 {
135 n := copy(d.x[d.nx:], p)
136 d.nx += n
137 if d.nx == chunk {
138 block(d, d.x[:])
139 d.nx = 0
140 }
141 p = p[n:]
142 }
143 if len(p) >= chunk {
144 n := len(p) &^ (chunk - 1)
145 block(d, p[:n])
146 p = p[n:]
147 }
148 if len(p) > 0 {
149 d.nx = copy(d.x[:], p)
150 }
151 return
152 }
153
154 func (d *digest) Sum(in []byte) []byte {
155
156 d0 := *d
157 hash := d0.checkSum()
158 return append(in, hash[:]...)
159 }
160
161 func (d *digest) checkSum() [Size]byte {
162 len := d.len
163
164 var tmp [64]byte
165 tmp[0] = 0x80
166 if len%64 < 56 {
167 d.Write(tmp[0 : 56-len%64])
168 } else {
169 d.Write(tmp[0 : 64+56-len%64])
170 }
171
172
173 len <<= 3
174 binary.BigEndian.PutUint64(tmp[:], len)
175 d.Write(tmp[0:8])
176
177 if d.nx != 0 {
178 panic("d.nx != 0")
179 }
180
181 var digest [Size]byte
182
183 binary.BigEndian.PutUint32(digest[0:], d.h[0])
184 binary.BigEndian.PutUint32(digest[4:], d.h[1])
185 binary.BigEndian.PutUint32(digest[8:], d.h[2])
186 binary.BigEndian.PutUint32(digest[12:], d.h[3])
187 binary.BigEndian.PutUint32(digest[16:], d.h[4])
188
189 return digest
190 }
191
192
193 func (d *digest) ConstantTimeSum(in []byte) []byte {
194 d0 := *d
195 hash := d0.constSum()
196 return append(in, hash[:]...)
197 }
198
199 func (d *digest) constSum() [Size]byte {
200 var length [8]byte
201 l := d.len << 3
202 for i := uint(0); i < 8; i++ {
203 length[i] = byte(l >> (56 - 8*i))
204 }
205
206 nx := byte(d.nx)
207 t := nx - 56
208 mask1b := byte(int8(t) >> 7)
209
210 separator := byte(0x80)
211 for i := byte(0); i < chunk; i++ {
212 mask := byte(int8(i-nx) >> 7)
213
214
215 d.x[i] = (^mask & separator) | (mask & d.x[i])
216
217
218 separator &= mask
219
220 if i >= 56 {
221
222 d.x[i] |= mask1b & length[i-56]
223 }
224 }
225
226
227 block(d, d.x[:])
228
229 var digest [Size]byte
230 for i, s := range d.h {
231 digest[i*4] = mask1b & byte(s>>24)
232 digest[i*4+1] = mask1b & byte(s>>16)
233 digest[i*4+2] = mask1b & byte(s>>8)
234 digest[i*4+3] = mask1b & byte(s)
235 }
236
237 for i := byte(0); i < chunk; i++ {
238
239 if i < 56 {
240 d.x[i] = separator
241 separator = 0
242 } else {
243 d.x[i] = length[i-56]
244 }
245 }
246
247
248 block(d, d.x[:])
249
250 for i, s := range d.h {
251 digest[i*4] |= ^mask1b & byte(s>>24)
252 digest[i*4+1] |= ^mask1b & byte(s>>16)
253 digest[i*4+2] |= ^mask1b & byte(s>>8)
254 digest[i*4+3] |= ^mask1b & byte(s)
255 }
256
257 return digest
258 }
259
260
261 func Sum(data []byte) [Size]byte {
262 var d digest
263 d.Reset()
264 d.Write(data)
265 return d.checkSum()
266 }
267
View as plain text