1
2
3
4
5
6
7
8
9
10
11 package sha512
12
13 import (
14 "crypto"
15 "crypto/internal/boring"
16 "encoding/binary"
17 "errors"
18 "hash"
19 )
20
21 func init() {
22 crypto.RegisterHash(crypto.SHA384, New384)
23 crypto.RegisterHash(crypto.SHA512, New)
24 crypto.RegisterHash(crypto.SHA512_224, New512_224)
25 crypto.RegisterHash(crypto.SHA512_256, New512_256)
26 }
27
28 const (
29
30 Size = 64
31
32
33 Size224 = 28
34
35
36 Size256 = 32
37
38
39 Size384 = 48
40
41
42
43 BlockSize = 128
44 )
45
46 const (
47 chunk = 128
48 init0 = 0x6a09e667f3bcc908
49 init1 = 0xbb67ae8584caa73b
50 init2 = 0x3c6ef372fe94f82b
51 init3 = 0xa54ff53a5f1d36f1
52 init4 = 0x510e527fade682d1
53 init5 = 0x9b05688c2b3e6c1f
54 init6 = 0x1f83d9abfb41bd6b
55 init7 = 0x5be0cd19137e2179
56 init0_224 = 0x8c3d37c819544da2
57 init1_224 = 0x73e1996689dcd4d6
58 init2_224 = 0x1dfab7ae32ff9c82
59 init3_224 = 0x679dd514582f9fcf
60 init4_224 = 0x0f6d2b697bd44da8
61 init5_224 = 0x77e36f7304c48942
62 init6_224 = 0x3f9d85a86a1d36c8
63 init7_224 = 0x1112e6ad91d692a1
64 init0_256 = 0x22312194fc2bf72c
65 init1_256 = 0x9f555fa3c84c64c2
66 init2_256 = 0x2393b86b6f53b151
67 init3_256 = 0x963877195940eabd
68 init4_256 = 0x96283ee2a88effe3
69 init5_256 = 0xbe5e1e2553863992
70 init6_256 = 0x2b0199fc2c85b8aa
71 init7_256 = 0x0eb72ddc81c52ca2
72 init0_384 = 0xcbbb9d5dc1059ed8
73 init1_384 = 0x629a292a367cd507
74 init2_384 = 0x9159015a3070dd17
75 init3_384 = 0x152fecd8f70e5939
76 init4_384 = 0x67332667ffc00b31
77 init5_384 = 0x8eb44a8768581511
78 init6_384 = 0xdb0c2e0d64f98fa7
79 init7_384 = 0x47b5481dbefa4fa4
80 )
81
82
83 type digest struct {
84 h [8]uint64
85 x [chunk]byte
86 nx int
87 len uint64
88 function crypto.Hash
89 }
90
91 func (d *digest) Reset() {
92 switch d.function {
93 case crypto.SHA384:
94 d.h[0] = init0_384
95 d.h[1] = init1_384
96 d.h[2] = init2_384
97 d.h[3] = init3_384
98 d.h[4] = init4_384
99 d.h[5] = init5_384
100 d.h[6] = init6_384
101 d.h[7] = init7_384
102 case crypto.SHA512_224:
103 d.h[0] = init0_224
104 d.h[1] = init1_224
105 d.h[2] = init2_224
106 d.h[3] = init3_224
107 d.h[4] = init4_224
108 d.h[5] = init5_224
109 d.h[6] = init6_224
110 d.h[7] = init7_224
111 case crypto.SHA512_256:
112 d.h[0] = init0_256
113 d.h[1] = init1_256
114 d.h[2] = init2_256
115 d.h[3] = init3_256
116 d.h[4] = init4_256
117 d.h[5] = init5_256
118 d.h[6] = init6_256
119 d.h[7] = init7_256
120 default:
121 d.h[0] = init0
122 d.h[1] = init1
123 d.h[2] = init2
124 d.h[3] = init3
125 d.h[4] = init4
126 d.h[5] = init5
127 d.h[6] = init6
128 d.h[7] = init7
129 }
130 d.nx = 0
131 d.len = 0
132 }
133
134 const (
135 magic384 = "sha\x04"
136 magic512_224 = "sha\x05"
137 magic512_256 = "sha\x06"
138 magic512 = "sha\x07"
139 marshaledSize = len(magic512) + 8*8 + chunk + 8
140 )
141
142 func (d *digest) MarshalBinary() ([]byte, error) {
143 b := make([]byte, 0, marshaledSize)
144 switch d.function {
145 case crypto.SHA384:
146 b = append(b, magic384...)
147 case crypto.SHA512_224:
148 b = append(b, magic512_224...)
149 case crypto.SHA512_256:
150 b = append(b, magic512_256...)
151 case crypto.SHA512:
152 b = append(b, magic512...)
153 default:
154 return nil, errors.New("crypto/sha512: invalid hash function")
155 }
156 b = binary.BigEndian.AppendUint64(b, d.h[0])
157 b = binary.BigEndian.AppendUint64(b, d.h[1])
158 b = binary.BigEndian.AppendUint64(b, d.h[2])
159 b = binary.BigEndian.AppendUint64(b, d.h[3])
160 b = binary.BigEndian.AppendUint64(b, d.h[4])
161 b = binary.BigEndian.AppendUint64(b, d.h[5])
162 b = binary.BigEndian.AppendUint64(b, d.h[6])
163 b = binary.BigEndian.AppendUint64(b, d.h[7])
164 b = append(b, d.x[:d.nx]...)
165 b = b[:len(b)+len(d.x)-d.nx]
166 b = binary.BigEndian.AppendUint64(b, d.len)
167 return b, nil
168 }
169
170 func (d *digest) UnmarshalBinary(b []byte) error {
171 if len(b) < len(magic512) {
172 return errors.New("crypto/sha512: invalid hash state identifier")
173 }
174 switch {
175 case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384:
176 case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224:
177 case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256:
178 case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512:
179 default:
180 return errors.New("crypto/sha512: invalid hash state identifier")
181 }
182 if len(b) != marshaledSize {
183 return errors.New("crypto/sha512: invalid hash state size")
184 }
185 b = b[len(magic512):]
186 b, d.h[0] = consumeUint64(b)
187 b, d.h[1] = consumeUint64(b)
188 b, d.h[2] = consumeUint64(b)
189 b, d.h[3] = consumeUint64(b)
190 b, d.h[4] = consumeUint64(b)
191 b, d.h[5] = consumeUint64(b)
192 b, d.h[6] = consumeUint64(b)
193 b, d.h[7] = consumeUint64(b)
194 b = b[copy(d.x[:], b):]
195 b, d.len = consumeUint64(b)
196 d.nx = int(d.len % chunk)
197 return nil
198 }
199
200 func consumeUint64(b []byte) ([]byte, uint64) {
201 _ = b[7]
202 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
203 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
204 return b[8:], x
205 }
206
207
208 func New() hash.Hash {
209 if boring.Enabled {
210 return boring.NewSHA512()
211 }
212 d := &digest{function: crypto.SHA512}
213 d.Reset()
214 return d
215 }
216
217
218 func New512_224() hash.Hash {
219 d := &digest{function: crypto.SHA512_224}
220 d.Reset()
221 return d
222 }
223
224
225 func New512_256() hash.Hash {
226 d := &digest{function: crypto.SHA512_256}
227 d.Reset()
228 return d
229 }
230
231
232 func New384() hash.Hash {
233 if boring.Enabled {
234 return boring.NewSHA384()
235 }
236 d := &digest{function: crypto.SHA384}
237 d.Reset()
238 return d
239 }
240
241 func (d *digest) Size() int {
242 switch d.function {
243 case crypto.SHA512_224:
244 return Size224
245 case crypto.SHA512_256:
246 return Size256
247 case crypto.SHA384:
248 return Size384
249 default:
250 return Size
251 }
252 }
253
254 func (d *digest) BlockSize() int { return BlockSize }
255
256 func (d *digest) Write(p []byte) (nn int, err error) {
257 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
258 boring.Unreachable()
259 }
260 nn = len(p)
261 d.len += uint64(nn)
262 if d.nx > 0 {
263 n := copy(d.x[d.nx:], p)
264 d.nx += n
265 if d.nx == chunk {
266 block(d, d.x[:])
267 d.nx = 0
268 }
269 p = p[n:]
270 }
271 if len(p) >= chunk {
272 n := len(p) &^ (chunk - 1)
273 block(d, p[:n])
274 p = p[n:]
275 }
276 if len(p) > 0 {
277 d.nx = copy(d.x[:], p)
278 }
279 return
280 }
281
282 func (d *digest) Sum(in []byte) []byte {
283 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
284 boring.Unreachable()
285 }
286
287 d0 := new(digest)
288 *d0 = *d
289 hash := d0.checkSum()
290 switch d0.function {
291 case crypto.SHA384:
292 return append(in, hash[:Size384]...)
293 case crypto.SHA512_224:
294 return append(in, hash[:Size224]...)
295 case crypto.SHA512_256:
296 return append(in, hash[:Size256]...)
297 default:
298 return append(in, hash[:]...)
299 }
300 }
301
302 func (d *digest) checkSum() [Size]byte {
303
304 len := d.len
305 var tmp [128 + 16]byte
306 tmp[0] = 0x80
307 var t uint64
308 if len%128 < 112 {
309 t = 112 - len%128
310 } else {
311 t = 128 + 112 - len%128
312 }
313
314
315 len <<= 3
316 padlen := tmp[:t+16]
317
318
319
320 binary.BigEndian.PutUint64(padlen[t+8:], len)
321 d.Write(padlen)
322
323 if d.nx != 0 {
324 panic("d.nx != 0")
325 }
326
327 var digest [Size]byte
328 binary.BigEndian.PutUint64(digest[0:], d.h[0])
329 binary.BigEndian.PutUint64(digest[8:], d.h[1])
330 binary.BigEndian.PutUint64(digest[16:], d.h[2])
331 binary.BigEndian.PutUint64(digest[24:], d.h[3])
332 binary.BigEndian.PutUint64(digest[32:], d.h[4])
333 binary.BigEndian.PutUint64(digest[40:], d.h[5])
334 if d.function != crypto.SHA384 {
335 binary.BigEndian.PutUint64(digest[48:], d.h[6])
336 binary.BigEndian.PutUint64(digest[56:], d.h[7])
337 }
338
339 return digest
340 }
341
342
343 func Sum512(data []byte) [Size]byte {
344 if boring.Enabled {
345 return boring.SHA512(data)
346 }
347 d := digest{function: crypto.SHA512}
348 d.Reset()
349 d.Write(data)
350 return d.checkSum()
351 }
352
353
354 func Sum384(data []byte) [Size384]byte {
355 if boring.Enabled {
356 return boring.SHA384(data)
357 }
358 d := digest{function: crypto.SHA384}
359 d.Reset()
360 d.Write(data)
361 sum := d.checkSum()
362 ap := (*[Size384]byte)(sum[:])
363 return *ap
364 }
365
366
367 func Sum512_224(data []byte) [Size224]byte {
368 d := digest{function: crypto.SHA512_224}
369 d.Reset()
370 d.Write(data)
371 sum := d.checkSum()
372 ap := (*[Size224]byte)(sum[:])
373 return *ap
374 }
375
376
377 func Sum512_256(data []byte) [Size256]byte {
378 d := digest{function: crypto.SHA512_256}
379 d.Reset()
380 d.Write(data)
381 sum := d.checkSum()
382 ap := (*[Size256]byte)(sum[:])
383 return *ap
384 }
385
View as plain text