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