1
2
3
4
5
6
7
8
9
10
11 package sha512
12
13 import (
14 "crypto"
15 "crypto/internal/boring"
16 "errors"
17 "hash"
18 "internal/byteorder"
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 = byteorder.BeAppendUint64(b, d.h[0])
157 b = byteorder.BeAppendUint64(b, d.h[1])
158 b = byteorder.BeAppendUint64(b, d.h[2])
159 b = byteorder.BeAppendUint64(b, d.h[3])
160 b = byteorder.BeAppendUint64(b, d.h[4])
161 b = byteorder.BeAppendUint64(b, d.h[5])
162 b = byteorder.BeAppendUint64(b, d.h[6])
163 b = byteorder.BeAppendUint64(b, d.h[7])
164 b = append(b, d.x[:d.nx]...)
165 b = b[:len(b)+len(d.x)-d.nx]
166 b = byteorder.BeAppendUint64(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 return b[8:], byteorder.BeUint64(b)
202 }
203
204
205 func New() hash.Hash {
206 if boring.Enabled {
207 return boring.NewSHA512()
208 }
209 d := &digest{function: crypto.SHA512}
210 d.Reset()
211 return d
212 }
213
214
215 func New512_224() hash.Hash {
216 d := &digest{function: crypto.SHA512_224}
217 d.Reset()
218 return d
219 }
220
221
222 func New512_256() hash.Hash {
223 d := &digest{function: crypto.SHA512_256}
224 d.Reset()
225 return d
226 }
227
228
229 func New384() hash.Hash {
230 if boring.Enabled {
231 return boring.NewSHA384()
232 }
233 d := &digest{function: crypto.SHA384}
234 d.Reset()
235 return d
236 }
237
238 func (d *digest) Size() int {
239 switch d.function {
240 case crypto.SHA512_224:
241 return Size224
242 case crypto.SHA512_256:
243 return Size256
244 case crypto.SHA384:
245 return Size384
246 default:
247 return Size
248 }
249 }
250
251 func (d *digest) BlockSize() int { return BlockSize }
252
253 func (d *digest) Write(p []byte) (nn int, err error) {
254 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
255 boring.Unreachable()
256 }
257 nn = len(p)
258 d.len += uint64(nn)
259 if d.nx > 0 {
260 n := copy(d.x[d.nx:], p)
261 d.nx += n
262 if d.nx == chunk {
263 block(d, d.x[:])
264 d.nx = 0
265 }
266 p = p[n:]
267 }
268 if len(p) >= chunk {
269 n := len(p) &^ (chunk - 1)
270 block(d, p[:n])
271 p = p[n:]
272 }
273 if len(p) > 0 {
274 d.nx = copy(d.x[:], p)
275 }
276 return
277 }
278
279 func (d *digest) Sum(in []byte) []byte {
280 if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
281 boring.Unreachable()
282 }
283
284 d0 := new(digest)
285 *d0 = *d
286 hash := d0.checkSum()
287 switch d0.function {
288 case crypto.SHA384:
289 return append(in, hash[:Size384]...)
290 case crypto.SHA512_224:
291 return append(in, hash[:Size224]...)
292 case crypto.SHA512_256:
293 return append(in, hash[:Size256]...)
294 default:
295 return append(in, hash[:]...)
296 }
297 }
298
299 func (d *digest) checkSum() [Size]byte {
300
301 len := d.len
302 var tmp [128 + 16]byte
303 tmp[0] = 0x80
304 var t uint64
305 if len%128 < 112 {
306 t = 112 - len%128
307 } else {
308 t = 128 + 112 - len%128
309 }
310
311
312 len <<= 3
313 padlen := tmp[:t+16]
314
315
316
317 byteorder.BePutUint64(padlen[t+8:], len)
318 d.Write(padlen)
319
320 if d.nx != 0 {
321 panic("d.nx != 0")
322 }
323
324 var digest [Size]byte
325 byteorder.BePutUint64(digest[0:], d.h[0])
326 byteorder.BePutUint64(digest[8:], d.h[1])
327 byteorder.BePutUint64(digest[16:], d.h[2])
328 byteorder.BePutUint64(digest[24:], d.h[3])
329 byteorder.BePutUint64(digest[32:], d.h[4])
330 byteorder.BePutUint64(digest[40:], d.h[5])
331 if d.function != crypto.SHA384 {
332 byteorder.BePutUint64(digest[48:], d.h[6])
333 byteorder.BePutUint64(digest[56:], d.h[7])
334 }
335
336 return digest
337 }
338
339
340 func Sum512(data []byte) [Size]byte {
341 if boring.Enabled {
342 return boring.SHA512(data)
343 }
344 d := digest{function: crypto.SHA512}
345 d.Reset()
346 d.Write(data)
347 return d.checkSum()
348 }
349
350
351 func Sum384(data []byte) [Size384]byte {
352 if boring.Enabled {
353 return boring.SHA384(data)
354 }
355 d := digest{function: crypto.SHA384}
356 d.Reset()
357 d.Write(data)
358 sum := d.checkSum()
359 ap := (*[Size384]byte)(sum[:])
360 return *ap
361 }
362
363
364 func Sum512_224(data []byte) [Size224]byte {
365 d := digest{function: crypto.SHA512_224}
366 d.Reset()
367 d.Write(data)
368 sum := d.checkSum()
369 ap := (*[Size224]byte)(sum[:])
370 return *ap
371 }
372
373
374 func Sum512_256(data []byte) [Size256]byte {
375 d := digest{function: crypto.SHA512_256}
376 d.Reset()
377 d.Write(data)
378 sum := d.checkSum()
379 ap := (*[Size256]byte)(sum[:])
380 return *ap
381 }
382
View as plain text