1
2
3
4
5
6
7 package sha512
8
9 import (
10 "crypto/internal/fips"
11 "errors"
12 "internal/byteorder"
13 )
14
15 const (
16
17 size512 = 64
18
19
20 size224 = 28
21
22
23 size256 = 32
24
25
26 size384 = 48
27
28
29
30 blockSize = 128
31 )
32
33 const (
34 chunk = 128
35 init0 = 0x6a09e667f3bcc908
36 init1 = 0xbb67ae8584caa73b
37 init2 = 0x3c6ef372fe94f82b
38 init3 = 0xa54ff53a5f1d36f1
39 init4 = 0x510e527fade682d1
40 init5 = 0x9b05688c2b3e6c1f
41 init6 = 0x1f83d9abfb41bd6b
42 init7 = 0x5be0cd19137e2179
43 init0_224 = 0x8c3d37c819544da2
44 init1_224 = 0x73e1996689dcd4d6
45 init2_224 = 0x1dfab7ae32ff9c82
46 init3_224 = 0x679dd514582f9fcf
47 init4_224 = 0x0f6d2b697bd44da8
48 init5_224 = 0x77e36f7304c48942
49 init6_224 = 0x3f9d85a86a1d36c8
50 init7_224 = 0x1112e6ad91d692a1
51 init0_256 = 0x22312194fc2bf72c
52 init1_256 = 0x9f555fa3c84c64c2
53 init2_256 = 0x2393b86b6f53b151
54 init3_256 = 0x963877195940eabd
55 init4_256 = 0x96283ee2a88effe3
56 init5_256 = 0xbe5e1e2553863992
57 init6_256 = 0x2b0199fc2c85b8aa
58 init7_256 = 0x0eb72ddc81c52ca2
59 init0_384 = 0xcbbb9d5dc1059ed8
60 init1_384 = 0x629a292a367cd507
61 init2_384 = 0x9159015a3070dd17
62 init3_384 = 0x152fecd8f70e5939
63 init4_384 = 0x67332667ffc00b31
64 init5_384 = 0x8eb44a8768581511
65 init6_384 = 0xdb0c2e0d64f98fa7
66 init7_384 = 0x47b5481dbefa4fa4
67 )
68
69
70
71 type Digest struct {
72 h [8]uint64
73 x [chunk]byte
74 nx int
75 len uint64
76 size int
77 }
78
79 func (d *Digest) Reset() {
80 switch d.size {
81 case size384:
82 d.h[0] = init0_384
83 d.h[1] = init1_384
84 d.h[2] = init2_384
85 d.h[3] = init3_384
86 d.h[4] = init4_384
87 d.h[5] = init5_384
88 d.h[6] = init6_384
89 d.h[7] = init7_384
90 case size224:
91 d.h[0] = init0_224
92 d.h[1] = init1_224
93 d.h[2] = init2_224
94 d.h[3] = init3_224
95 d.h[4] = init4_224
96 d.h[5] = init5_224
97 d.h[6] = init6_224
98 d.h[7] = init7_224
99 case size256:
100 d.h[0] = init0_256
101 d.h[1] = init1_256
102 d.h[2] = init2_256
103 d.h[3] = init3_256
104 d.h[4] = init4_256
105 d.h[5] = init5_256
106 d.h[6] = init6_256
107 d.h[7] = init7_256
108 case size512:
109 d.h[0] = init0
110 d.h[1] = init1
111 d.h[2] = init2
112 d.h[3] = init3
113 d.h[4] = init4
114 d.h[5] = init5
115 d.h[6] = init6
116 d.h[7] = init7
117 default:
118 panic("unknown size")
119 }
120 d.nx = 0
121 d.len = 0
122 }
123
124 const (
125 magic384 = "sha\x04"
126 magic512_224 = "sha\x05"
127 magic512_256 = "sha\x06"
128 magic512 = "sha\x07"
129 marshaledSize = len(magic512) + 8*8 + chunk + 8
130 )
131
132 func (d *Digest) MarshalBinary() ([]byte, error) {
133 return d.AppendBinary(make([]byte, 0, marshaledSize))
134 }
135
136 func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
137 switch d.size {
138 case size384:
139 b = append(b, magic384...)
140 case size224:
141 b = append(b, magic512_224...)
142 case size256:
143 b = append(b, magic512_256...)
144 case size512:
145 b = append(b, magic512...)
146 default:
147 panic("unknown size")
148 }
149 b = byteorder.BeAppendUint64(b, d.h[0])
150 b = byteorder.BeAppendUint64(b, d.h[1])
151 b = byteorder.BeAppendUint64(b, d.h[2])
152 b = byteorder.BeAppendUint64(b, d.h[3])
153 b = byteorder.BeAppendUint64(b, d.h[4])
154 b = byteorder.BeAppendUint64(b, d.h[5])
155 b = byteorder.BeAppendUint64(b, d.h[6])
156 b = byteorder.BeAppendUint64(b, d.h[7])
157 b = append(b, d.x[:d.nx]...)
158 b = append(b, make([]byte, len(d.x)-d.nx)...)
159 b = byteorder.BeAppendUint64(b, d.len)
160 return b, nil
161 }
162
163 func (d *Digest) UnmarshalBinary(b []byte) error {
164 if len(b) < len(magic512) {
165 return errors.New("crypto/sha512: invalid hash state identifier")
166 }
167 switch {
168 case d.size == size384 && string(b[:len(magic384)]) == magic384:
169 case d.size == size224 && string(b[:len(magic512_224)]) == magic512_224:
170 case d.size == size256 && string(b[:len(magic512_256)]) == magic512_256:
171 case d.size == size512 && string(b[:len(magic512)]) == magic512:
172 default:
173 return errors.New("crypto/sha512: invalid hash state identifier")
174 }
175 if len(b) != marshaledSize {
176 return errors.New("crypto/sha512: invalid hash state size")
177 }
178 b = b[len(magic512):]
179 b, d.h[0] = consumeUint64(b)
180 b, d.h[1] = consumeUint64(b)
181 b, d.h[2] = consumeUint64(b)
182 b, d.h[3] = consumeUint64(b)
183 b, d.h[4] = consumeUint64(b)
184 b, d.h[5] = consumeUint64(b)
185 b, d.h[6] = consumeUint64(b)
186 b, d.h[7] = consumeUint64(b)
187 b = b[copy(d.x[:], b):]
188 b, d.len = consumeUint64(b)
189 d.nx = int(d.len % chunk)
190 return nil
191 }
192
193 func consumeUint64(b []byte) ([]byte, uint64) {
194 return b[8:], byteorder.BeUint64(b)
195 }
196
197
198 func New() *Digest {
199 d := &Digest{size: size512}
200 d.Reset()
201 return d
202 }
203
204
205 func New512_224() *Digest {
206 d := &Digest{size: size224}
207 d.Reset()
208 return d
209 }
210
211
212 func New512_256() *Digest {
213 d := &Digest{size: size256}
214 d.Reset()
215 return d
216 }
217
218
219 func New384() *Digest {
220 d := &Digest{size: size384}
221 d.Reset()
222 return d
223 }
224
225 func (d *Digest) Size() int {
226 return d.size
227 }
228
229 func (d *Digest) BlockSize() int { return blockSize }
230
231 func (d *Digest) Write(p []byte) (nn int, err error) {
232 nn = len(p)
233 d.len += uint64(nn)
234 if d.nx > 0 {
235 n := copy(d.x[d.nx:], p)
236 d.nx += n
237 if d.nx == chunk {
238 block(d, d.x[:])
239 d.nx = 0
240 }
241 p = p[n:]
242 }
243 if len(p) >= chunk {
244 n := len(p) &^ (chunk - 1)
245 block(d, p[:n])
246 p = p[n:]
247 }
248 if len(p) > 0 {
249 d.nx = copy(d.x[:], p)
250 }
251 return
252 }
253
254 func (d *Digest) Sum(in []byte) []byte {
255 fips.RecordApproved()
256
257 d0 := new(Digest)
258 *d0 = *d
259 hash := d0.checkSum()
260 return append(in, hash[:d.size]...)
261 }
262
263 func (d *Digest) checkSum() [size512]byte {
264
265 len := d.len
266 var tmp [128 + 16]byte
267 tmp[0] = 0x80
268 var t uint64
269 if len%128 < 112 {
270 t = 112 - len%128
271 } else {
272 t = 128 + 112 - len%128
273 }
274
275
276 len <<= 3
277 padlen := tmp[:t+16]
278
279
280
281 byteorder.BePutUint64(padlen[t+8:], len)
282 d.Write(padlen)
283
284 if d.nx != 0 {
285 panic("d.nx != 0")
286 }
287
288 var digest [size512]byte
289 byteorder.BePutUint64(digest[0:], d.h[0])
290 byteorder.BePutUint64(digest[8:], d.h[1])
291 byteorder.BePutUint64(digest[16:], d.h[2])
292 byteorder.BePutUint64(digest[24:], d.h[3])
293 byteorder.BePutUint64(digest[32:], d.h[4])
294 byteorder.BePutUint64(digest[40:], d.h[5])
295 if d.size != size384 {
296 byteorder.BePutUint64(digest[48:], d.h[6])
297 byteorder.BePutUint64(digest[56:], d.h[7])
298 }
299
300 return digest
301 }
302
View as plain text