]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/sha512/sha512.go
crypto/x509/pkix: remove references to fmt.Stringer in String method docs
[gostls13.git] / src / crypto / sha512 / sha512.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 sha512 implements the SHA-384, SHA-512, SHA-512/224, and SHA-512/256
6 // hash algorithms as defined in FIPS 180-4.
7 //
8 // All the hash.Hash implementations returned by this package also
9 // implement encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
10 // marshal and unmarshal the internal state of the hash.
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         // Size is the size, in bytes, of a SHA-512 checksum.
28         Size = 64
29
30         // Size224 is the size, in bytes, of a SHA-512/224 checksum.
31         Size224 = 28
32
33         // Size256 is the size, in bytes, of a SHA-512/256 checksum.
34         Size256 = 32
35
36         // Size384 is the size, in bytes, of a SHA-384 checksum.
37         Size384 = 48
38
39         // BlockSize is the block size, in bytes, of the SHA-512/224,
40         // SHA-512/256, SHA-384 and SHA-512 hash functions.
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 // digest represents the partial evaluation of a checksum.
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[:]...)
163         b = appendUint64(b, d.len)
164         return b, nil
165 }
166
167 func (d *digest) UnmarshalBinary(b []byte) error {
168         if len(b) < len(magic512) {
169                 return errors.New("crypto/sha512: invalid hash state identifier")
170         }
171         switch {
172         case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384:
173         case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224:
174         case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256:
175         case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512:
176         default:
177                 return errors.New("crypto/sha512: invalid hash state identifier")
178         }
179         if len(b) != marshaledSize {
180                 return errors.New("crypto/sha512: invalid hash state size")
181         }
182         b = b[len(magic512):]
183         b, d.h[0] = consumeUint64(b)
184         b, d.h[1] = consumeUint64(b)
185         b, d.h[2] = consumeUint64(b)
186         b, d.h[3] = consumeUint64(b)
187         b, d.h[4] = consumeUint64(b)
188         b, d.h[5] = consumeUint64(b)
189         b, d.h[6] = consumeUint64(b)
190         b, d.h[7] = consumeUint64(b)
191         b = b[copy(d.x[:], b):]
192         b, d.len = consumeUint64(b)
193         d.nx = int(d.len) % chunk
194         return nil
195 }
196
197 func appendUint64(b []byte, x uint64) []byte {
198         a := [8]byte{
199                 byte(x >> 56),
200                 byte(x >> 48),
201                 byte(x >> 40),
202                 byte(x >> 32),
203                 byte(x >> 24),
204                 byte(x >> 16),
205                 byte(x >> 8),
206                 byte(x),
207         }
208         return append(b, a[:]...)
209 }
210
211 func consumeUint64(b []byte) ([]byte, uint64) {
212         _ = b[7]
213         x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
214                 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
215         return b[8:], x
216 }
217
218 // New returns a new hash.Hash computing the SHA-512 checksum.
219 func New() hash.Hash {
220         d := &digest{function: crypto.SHA512}
221         d.Reset()
222         return d
223 }
224
225 // New512_224 returns a new hash.Hash computing the SHA-512/224 checksum.
226 func New512_224() hash.Hash {
227         d := &digest{function: crypto.SHA512_224}
228         d.Reset()
229         return d
230 }
231
232 // New512_256 returns a new hash.Hash computing the SHA-512/256 checksum.
233 func New512_256() hash.Hash {
234         d := &digest{function: crypto.SHA512_256}
235         d.Reset()
236         return d
237 }
238
239 // New384 returns a new hash.Hash computing the SHA-384 checksum.
240 func New384() hash.Hash {
241         d := &digest{function: crypto.SHA384}
242         d.Reset()
243         return d
244 }
245
246 func (d *digest) Size() int {
247         switch d.function {
248         case crypto.SHA512_224:
249                 return Size224
250         case crypto.SHA512_256:
251                 return Size256
252         case crypto.SHA384:
253                 return Size384
254         default:
255                 return Size
256         }
257 }
258
259 func (d *digest) BlockSize() int { return BlockSize }
260
261 func (d *digest) Write(p []byte) (nn int, err error) {
262         nn = len(p)
263         d.len += uint64(nn)
264         if d.nx > 0 {
265                 n := copy(d.x[d.nx:], p)
266                 d.nx += n
267                 if d.nx == chunk {
268                         block(d, d.x[:])
269                         d.nx = 0
270                 }
271                 p = p[n:]
272         }
273         if len(p) >= chunk {
274                 n := len(p) &^ (chunk - 1)
275                 block(d, p[:n])
276                 p = p[n:]
277         }
278         if len(p) > 0 {
279                 d.nx = copy(d.x[:], p)
280         }
281         return
282 }
283
284 func (d0 *digest) Sum(in []byte) []byte {
285         // Make a copy of d0 so that caller can keep writing and summing.
286         d := new(digest)
287         *d = *d0
288         hash := d.checkSum()
289         switch d.function {
290         case crypto.SHA384:
291                 return append(in, hash[:Size384]...)
292         case crypto.SHA512_224:
293                 return append(in, hash[:Size224]...)
294         case crypto.SHA512_256:
295                 return append(in, hash[:Size256]...)
296         default:
297                 return append(in, hash[:]...)
298         }
299 }
300
301 func (d *digest) checkSum() [Size]byte {
302         // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
303         len := d.len
304         var tmp [128]byte
305         tmp[0] = 0x80
306         if len%128 < 112 {
307                 d.Write(tmp[0 : 112-len%128])
308         } else {
309                 d.Write(tmp[0 : 128+112-len%128])
310         }
311
312         // Length in bits.
313         len <<= 3
314         for i := uint(0); i < 16; i++ {
315                 tmp[i] = byte(len >> (120 - 8*i))
316         }
317         d.Write(tmp[0:16])
318
319         if d.nx != 0 {
320                 panic("d.nx != 0")
321         }
322
323         h := d.h[:]
324         if d.function == crypto.SHA384 {
325                 h = d.h[:6]
326         }
327
328         var digest [Size]byte
329         for i, s := range h {
330                 digest[i*8] = byte(s >> 56)
331                 digest[i*8+1] = byte(s >> 48)
332                 digest[i*8+2] = byte(s >> 40)
333                 digest[i*8+3] = byte(s >> 32)
334                 digest[i*8+4] = byte(s >> 24)
335                 digest[i*8+5] = byte(s >> 16)
336                 digest[i*8+6] = byte(s >> 8)
337                 digest[i*8+7] = byte(s)
338         }
339
340         return digest
341 }
342
343 // Sum512 returns the SHA512 checksum of the data.
344 func Sum512(data []byte) [Size]byte {
345         d := digest{function: crypto.SHA512}
346         d.Reset()
347         d.Write(data)
348         return d.checkSum()
349 }
350
351 // Sum384 returns the SHA384 checksum of the data.
352 func Sum384(data []byte) (sum384 [Size384]byte) {
353         d := digest{function: crypto.SHA384}
354         d.Reset()
355         d.Write(data)
356         sum := d.checkSum()
357         copy(sum384[:], sum[:Size384])
358         return
359 }
360
361 // Sum512_224 returns the Sum512/224 checksum of the data.
362 func Sum512_224(data []byte) (sum224 [Size224]byte) {
363         d := digest{function: crypto.SHA512_224}
364         d.Reset()
365         d.Write(data)
366         sum := d.checkSum()
367         copy(sum224[:], sum[:Size224])
368         return
369 }
370
371 // Sum512_256 returns the Sum512/256 checksum of the data.
372 func Sum512_256(data []byte) (sum256 [Size256]byte) {
373         d := digest{function: crypto.SHA512_256}
374         d.Reset()
375         d.Write(data)
376         sum := d.checkSum()
377         copy(sum256[:], sum[:Size256])
378         return
379 }