Source file
src/crypto/sha3/sha3_test.go
1
2
3
4
5 package sha3_test
6
7 import (
8 "bytes"
9 "crypto/internal/cryptotest"
10 "crypto/internal/fips140"
11 . "crypto/sha3"
12 "encoding/hex"
13 "io"
14 "math/rand"
15 "strings"
16 "testing"
17 )
18
19 const testString = "brekeccakkeccak koax koax"
20
21
22
23
24 var testDigests = map[string]func() *SHA3{
25 "SHA3-224": New224,
26 "SHA3-256": New256,
27 "SHA3-384": New384,
28 "SHA3-512": New512,
29 }
30
31
32
33 var testShakes = map[string]struct {
34 constructor func(N []byte, S []byte) *SHAKE
35 defAlgoName string
36 defCustomStr string
37 }{
38
39 "SHAKE128": {NewCSHAKE128, "", ""},
40 "SHAKE256": {NewCSHAKE256, "", ""},
41 "cSHAKE128": {NewCSHAKE128, "CSHAKE128", "CustomString"},
42 "cSHAKE256": {NewCSHAKE256, "CSHAKE256", "CustomString"},
43 }
44
45
46 func decodeHex(s string) []byte {
47 b, err := hex.DecodeString(s)
48 if err != nil {
49 panic(err)
50 }
51 return b
52 }
53
54
55
56 func TestUnalignedWrite(t *testing.T) {
57 cryptotest.TestAllImplementations(t, "sha3", testUnalignedWrite)
58 }
59
60 func testUnalignedWrite(t *testing.T) {
61 buf := sequentialBytes(0x10000)
62 for alg, df := range testDigests {
63 d := df()
64 d.Reset()
65 d.Write(buf)
66 want := d.Sum(nil)
67 d.Reset()
68 for i := 0; i < len(buf); {
69
70
71 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
72 for _, j := range offsets {
73 if v := len(buf) - i; v < j {
74 j = v
75 }
76 d.Write(buf[i : i+j])
77 i += j
78 }
79 }
80 got := d.Sum(nil)
81 if !bytes.Equal(got, want) {
82 t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
83 }
84 }
85
86
87 for alg, df := range testShakes {
88 want := make([]byte, 16)
89 got := make([]byte, 16)
90 d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr))
91
92 d.Reset()
93 d.Write(buf)
94 d.Read(want)
95 d.Reset()
96 for i := 0; i < len(buf); {
97
98
99 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
100 for _, j := range offsets {
101 if v := len(buf) - i; v < j {
102 j = v
103 }
104 d.Write(buf[i : i+j])
105 i += j
106 }
107 }
108 d.Read(got)
109 if !bytes.Equal(got, want) {
110 t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
111 }
112 }
113 }
114
115
116 func TestAppend(t *testing.T) {
117 cryptotest.TestAllImplementations(t, "sha3", testAppend)
118 }
119
120 func testAppend(t *testing.T) {
121 d := New224()
122
123 for capacity := 2; capacity <= 66; capacity += 64 {
124
125
126 buf := make([]byte, 2, capacity)
127 d.Reset()
128 d.Write([]byte{0xcc})
129 buf = d.Sum(buf)
130 expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
131 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
132 t.Errorf("got %s, want %s", got, expected)
133 }
134 }
135 }
136
137
138 func TestAppendNoRealloc(t *testing.T) {
139 cryptotest.TestAllImplementations(t, "sha3", testAppendNoRealloc)
140 }
141
142 func testAppendNoRealloc(t *testing.T) {
143 buf := make([]byte, 1, 200)
144 d := New224()
145 d.Write([]byte{0xcc})
146 buf = d.Sum(buf)
147 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
148 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
149 t.Errorf("got %s, want %s", got, expected)
150 }
151 }
152
153
154
155 func TestSqueezing(t *testing.T) {
156 cryptotest.TestAllImplementations(t, "sha3", testSqueezing)
157 }
158
159 func testSqueezing(t *testing.T) {
160 for algo, v := range testShakes {
161 d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
162 d0.Write([]byte(testString))
163 ref := make([]byte, 32)
164 d0.Read(ref)
165
166 d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
167 d1.Write([]byte(testString))
168 var multiple []byte
169 for range ref {
170 d1.Read(make([]byte, 0))
171 one := make([]byte, 1)
172 d1.Read(one)
173 multiple = append(multiple, one...)
174 }
175 if !bytes.Equal(ref, multiple) {
176 t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref))
177 }
178 }
179 }
180
181
182
183
184
185
186
187 func sequentialBytes(size int) []byte {
188 alignmentOffset := rand.Intn(8)
189 result := make([]byte, size+alignmentOffset)[alignmentOffset:]
190 for i := range result {
191 result[i] = byte(i)
192 }
193 return result
194 }
195
196 func TestReset(t *testing.T) {
197 cryptotest.TestAllImplementations(t, "sha3", testReset)
198 }
199
200 func testReset(t *testing.T) {
201 out1 := make([]byte, 32)
202 out2 := make([]byte, 32)
203
204 for _, v := range testShakes {
205
206 c := v.constructor(nil, []byte{0x99, 0x98})
207 c.Write(sequentialBytes(0x100))
208 c.Read(out1)
209
210
211 c.Reset()
212 c.Write(sequentialBytes(0x100))
213 c.Read(out2)
214
215 if !bytes.Equal(out1, out2) {
216 t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
217 }
218 }
219 }
220
221 var sinkSHA3 byte
222
223 func TestAllocations(t *testing.T) {
224 cryptotest.SkipTestAllocations(t)
225 t.Run("New", func(t *testing.T) {
226 if allocs := testing.AllocsPerRun(10, func() {
227 h := New256()
228 b := []byte("ABC")
229 h.Write(b)
230 out := make([]byte, 0, 32)
231 out = h.Sum(out)
232 sinkSHA3 ^= out[0]
233 }); allocs > 0 {
234 t.Errorf("expected zero allocations, got %0.1f", allocs)
235 }
236 })
237 t.Run("NewSHAKE", func(t *testing.T) {
238 if allocs := testing.AllocsPerRun(10, func() {
239 h := NewSHAKE128()
240 b := []byte("ABC")
241 h.Write(b)
242 out := make([]byte, 32)
243 h.Read(out)
244 sinkSHA3 ^= out[0]
245 }); allocs > 0 {
246 t.Errorf("expected zero allocations, got %0.1f", allocs)
247 }
248 })
249 t.Run("Sum", func(t *testing.T) {
250 if allocs := testing.AllocsPerRun(10, func() {
251 b := []byte("ABC")
252 out := Sum256(b)
253 sinkSHA3 ^= out[0]
254 }); allocs > 0 {
255 t.Errorf("expected zero allocations, got %0.1f", allocs)
256 }
257 })
258 t.Run("SumSHAKE", func(t *testing.T) {
259 if allocs := testing.AllocsPerRun(10, func() {
260 b := []byte("ABC")
261 out := SumSHAKE128(b, 10)
262 sinkSHA3 ^= out[0]
263 }); allocs > 0 {
264 t.Errorf("expected zero allocations, got %0.1f", allocs)
265 }
266 })
267 }
268
269 func TestCSHAKEAccumulated(t *testing.T) {
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) {
314 t.Run("cSHAKE128", func(t *testing.T) {
315 testCSHAKEAccumulated(t, NewCSHAKE128, (1600-256)/8,
316 "bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
317 })
318 t.Run("cSHAKE256", func(t *testing.T) {
319 testCSHAKEAccumulated(t, NewCSHAKE256, (1600-512)/8,
320 "0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef")
321 })
322 })
323 }
324
325 func testCSHAKEAccumulated(t *testing.T, newCSHAKE func(N, S []byte) *SHAKE, rate int64, exp string) {
326 rnd := newCSHAKE(nil, nil)
327 acc := newCSHAKE(nil, nil)
328 for n := 0; n < 200; n++ {
329 N := make([]byte, n)
330 rnd.Read(N)
331 for s := 0; s < 200; s++ {
332 S := make([]byte, s)
333 rnd.Read(S)
334
335 c := newCSHAKE(N, S)
336 io.CopyN(c, rnd, 100 )
337 io.CopyN(acc, c, 200)
338
339 c.Reset()
340 io.CopyN(c, rnd, rate)
341 io.CopyN(acc, c, 200)
342
343 c.Reset()
344 io.CopyN(c, rnd, 200 )
345 io.CopyN(acc, c, 200)
346 }
347 }
348 out := make([]byte, 32)
349 acc.Read(out)
350 if got := hex.EncodeToString(out); got != exp {
351 t.Errorf("got %s, want %s", got, exp)
352 }
353 }
354
355 func TestCSHAKELargeS(t *testing.T) {
356 cryptotest.TestAllImplementations(t, "sha3", testCSHAKELargeS)
357 }
358
359 func testCSHAKELargeS(t *testing.T) {
360 if testing.Short() {
361 t.Skip("skipping test in short mode.")
362 }
363
364
365 const s = (1<<32)/8 + 1000
366 S := make([]byte, s)
367 rnd := NewSHAKE128()
368 rnd.Read(S)
369 c := NewCSHAKE128(nil, S)
370 io.CopyN(c, rnd, 1000)
371 out := make([]byte, 32)
372 c.Read(out)
373
374
375
376
377
378
379
380
381
382
383 exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0"
384 if got := hex.EncodeToString(out); got != exp {
385 t.Errorf("got %s, want %s", got, exp)
386 }
387 }
388
389 func TestMarshalUnmarshal(t *testing.T) {
390 cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) {
391 t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) })
392 t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) })
393 t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) })
394 t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) })
395 t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE128()) })
396 t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE256()) })
397 t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE128([]byte("N"), []byte("S"))) })
398 t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE256([]byte("N"), []byte("S"))) })
399 })
400 }
401
402
403 func testMarshalUnmarshal(t *testing.T, h *SHA3) {
404 buf := make([]byte, 200)
405 rand.Read(buf)
406 n := rand.Intn(200)
407 h.Write(buf)
408 want := h.Sum(nil)
409 h.Reset()
410 h.Write(buf[:n])
411 b, err := h.MarshalBinary()
412 if err != nil {
413 t.Errorf("MarshalBinary: %v", err)
414 }
415 h.Write(bytes.Repeat([]byte{0}, 200))
416 if err := h.UnmarshalBinary(b); err != nil {
417 t.Errorf("UnmarshalBinary: %v", err)
418 }
419 h.Write(buf[n:])
420 got := h.Sum(nil)
421 if !bytes.Equal(got, want) {
422 t.Errorf("got %x, want %x", got, want)
423 }
424 }
425
426
427 func testMarshalUnmarshalSHAKE(t *testing.T, h *SHAKE) {
428 buf := make([]byte, 200)
429 rand.Read(buf)
430 n := rand.Intn(200)
431 h.Write(buf)
432 want := make([]byte, 32)
433 h.Read(want)
434 h.Reset()
435 h.Write(buf[:n])
436 b, err := h.MarshalBinary()
437 if err != nil {
438 t.Errorf("MarshalBinary: %v", err)
439 }
440 h.Write(bytes.Repeat([]byte{0}, 200))
441 if err := h.UnmarshalBinary(b); err != nil {
442 t.Errorf("UnmarshalBinary: %v", err)
443 }
444 h.Write(buf[n:])
445 got := make([]byte, 32)
446 h.Read(got)
447 if !bytes.Equal(got, want) {
448 t.Errorf("got %x, want %x", got, want)
449 }
450 }
451
452
453 func benchmarkHash(b *testing.B, h fips140.Hash, size, num int) {
454 b.StopTimer()
455 h.Reset()
456 data := sequentialBytes(size)
457 b.SetBytes(int64(size * num))
458 b.StartTimer()
459
460 var state []byte
461 for i := 0; i < b.N; i++ {
462 for j := 0; j < num; j++ {
463 h.Write(data)
464 }
465 state = h.Sum(state[:0])
466 }
467 b.StopTimer()
468 h.Reset()
469 }
470
471
472
473 func benchmarkShake(b *testing.B, h *SHAKE, size, num int) {
474 b.StopTimer()
475 h.Reset()
476 data := sequentialBytes(size)
477 d := make([]byte, 32)
478
479 b.SetBytes(int64(size * num))
480 b.StartTimer()
481
482 for i := 0; i < b.N; i++ {
483 h.Reset()
484 for j := 0; j < num; j++ {
485 h.Write(data)
486 }
487 h.Read(d)
488 }
489 }
490
491 func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
492 func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
493 func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
494 func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
495
496 func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewSHAKE128(), 1350, 1) }
497 func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 1350, 1) }
498 func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 16, 1024) }
499 func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewSHAKE256(), 1024, 1024) }
500
501 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
502
View as plain text