Source file src/pkg/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 SHA384 and SHA512 hash algorithms as defined
6 // in FIPS 180-2.
7 package sha512
8
9 import (
10 "crypto"
11 "hash"
12 )
13
14 func init() {
15 crypto.RegisterHash(crypto.SHA384, New384)
16 crypto.RegisterHash(crypto.SHA512, New)
17 }
18
19 // The size of a SHA512 checksum in bytes.
20 const Size = 64
21
22 // The size of a SHA384 checksum in bytes.
23 const Size384 = 48
24
25 // The blocksize of SHA512 and SHA384 in bytes.
26 const BlockSize = 128
27
28 const (
29 _Chunk = 128
30 _Init0 = 0x6a09e667f3bcc908
31 _Init1 = 0xbb67ae8584caa73b
32 _Init2 = 0x3c6ef372fe94f82b
33 _Init3 = 0xa54ff53a5f1d36f1
34 _Init4 = 0x510e527fade682d1
35 _Init5 = 0x9b05688c2b3e6c1f
36 _Init6 = 0x1f83d9abfb41bd6b
37 _Init7 = 0x5be0cd19137e2179
38 _Init0_384 = 0xcbbb9d5dc1059ed8
39 _Init1_384 = 0x629a292a367cd507
40 _Init2_384 = 0x9159015a3070dd17
41 _Init3_384 = 0x152fecd8f70e5939
42 _Init4_384 = 0x67332667ffc00b31
43 _Init5_384 = 0x8eb44a8768581511
44 _Init6_384 = 0xdb0c2e0d64f98fa7
45 _Init7_384 = 0x47b5481dbefa4fa4
46 )
47
48 // digest represents the partial evaluation of a checksum.
49 type digest struct {
50 h [8]uint64
51 x [_Chunk]byte
52 nx int
53 len uint64
54 is384 bool // mark if this digest is SHA-384
55 }
56
57 func (d *digest) Reset() {
58 if !d.is384 {
59 d.h[0] = _Init0
60 d.h[1] = _Init1
61 d.h[2] = _Init2
62 d.h[3] = _Init3
63 d.h[4] = _Init4
64 d.h[5] = _Init5
65 d.h[6] = _Init6
66 d.h[7] = _Init7
67 } else {
68 d.h[0] = _Init0_384
69 d.h[1] = _Init1_384
70 d.h[2] = _Init2_384
71 d.h[3] = _Init3_384
72 d.h[4] = _Init4_384
73 d.h[5] = _Init5_384
74 d.h[6] = _Init6_384
75 d.h[7] = _Init7_384
76 }
77 d.nx = 0
78 d.len = 0
79 }
80
81 // New returns a new hash.Hash computing the SHA512 checksum.
82 func New() hash.Hash {
83 d := new(digest)
84 d.Reset()
85 return d
86 }
87
88 // New384 returns a new hash.Hash computing the SHA384 checksum.
89 func New384() hash.Hash {
90 d := new(digest)
91 d.is384 = true
92 d.Reset()
93 return d
94 }
95
96 func (d *digest) Size() int {
97 if !d.is384 {
98 return Size
99 }
100 return Size384
101 }
102
103 func (d *digest) BlockSize() int { return BlockSize }
104
105 func (d *digest) Write(p []byte) (nn int, err error) {
106 nn = len(p)
107 d.len += uint64(nn)
108 if d.nx > 0 {
109 n := len(p)
110 if n > _Chunk-d.nx {
111 n = _Chunk - d.nx
112 }
113 for i := 0; i < n; i++ {
114 d.x[d.nx+i] = p[i]
115 }
116 d.nx += n
117 if d.nx == _Chunk {
118 _Block(d, d.x[0:])
119 d.nx = 0
120 }
121 p = p[n:]
122 }
123 n := _Block(d, p)
124 p = p[n:]
125 if len(p) > 0 {
126 d.nx = copy(d.x[:], p)
127 }
128 return
129 }
130
131 func (d0 *digest) Sum(in []byte) []byte {
132 // Make a copy of d0 so that caller can keep writing and summing.
133 d := new(digest)
134 *d = *d0
135
136 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
137 len := d.len
138 var tmp [128]byte
139 tmp[0] = 0x80
140 if len%128 < 112 {
141 d.Write(tmp[0 : 112-len%128])
142 } else {
143 d.Write(tmp[0 : 128+112-len%128])
144 }
145
146 // Length in bits.
147 len <<= 3
148 for i := uint(0); i < 16; i++ {
149 tmp[i] = byte(len >> (120 - 8*i))
150 }
151 d.Write(tmp[0:16])
152
153 if d.nx != 0 {
154 panic("d.nx != 0")
155 }
156
157 h := d.h[:]
158 size := Size
159 if d.is384 {
160 h = d.h[:6]
161 size = Size384
162 }
163
164 var digest [Size]byte
165 for i, s := range h {
166 digest[i*8] = byte(s >> 56)
167 digest[i*8+1] = byte(s >> 48)
168 digest[i*8+2] = byte(s >> 40)
169 digest[i*8+3] = byte(s >> 32)
170 digest[i*8+4] = byte(s >> 24)
171 digest[i*8+5] = byte(s >> 16)
172 digest[i*8+6] = byte(s >> 8)
173 digest[i*8+7] = byte(s)
174 }
175
176 return append(in, digest[:size]...)
177 }