1
2
3
4
5 package sha3_test
6
7 import (
8 "bytes"
9 "crypto/internal/cryptotest"
10 "crypto/internal/fips"
11 . "crypto/internal/fips/sha3"
12 "encoding"
13 "encoding/hex"
14 "fmt"
15 "internal/testenv"
16 "io"
17 "math/rand"
18 "strings"
19 "testing"
20 )
21
22
23
24
25 func Sum224(data []byte) (digest [28]byte) {
26 h := New224()
27 h.Write(data)
28 h.Sum(digest[:0])
29 return
30 }
31
32
33 func Sum256(data []byte) (digest [32]byte) {
34 h := New256()
35 h.Write(data)
36 h.Sum(digest[:0])
37 return
38 }
39
40
41 func Sum384(data []byte) (digest [48]byte) {
42 h := New384()
43 h.Write(data)
44 h.Sum(digest[:0])
45 return
46 }
47
48
49 func Sum512(data []byte) (digest [64]byte) {
50 h := New512()
51 h.Write(data)
52 h.Sum(digest[:0])
53 return
54 }
55
56
57 func ShakeSum128(hash, data []byte) {
58 h := NewShake128()
59 h.Write(data)
60 h.Read(hash)
61 }
62
63
64 func ShakeSum256(hash, data []byte) {
65 h := NewShake256()
66 h.Write(data)
67 h.Read(hash)
68 }
69
70 const testString = "brekeccakkeccak koax koax"
71
72
73
74
75 var testDigests = map[string]func() *Digest{
76 "SHA3-224": New224,
77 "SHA3-256": New256,
78 "SHA3-384": New384,
79 "SHA3-512": New512,
80 "Keccak-256": NewLegacyKeccak256,
81 "Keccak-512": NewLegacyKeccak512,
82 }
83
84
85
86 var testShakes = map[string]struct {
87 constructor func(N []byte, S []byte) *SHAKE
88 defAlgoName string
89 defCustomStr string
90 }{
91
92 "SHAKE128": {NewCShake128, "", ""},
93 "SHAKE256": {NewCShake256, "", ""},
94 "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomString"},
95 "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomString"},
96 }
97
98
99 func decodeHex(s string) []byte {
100 b, err := hex.DecodeString(s)
101 if err != nil {
102 panic(err)
103 }
104 return b
105 }
106
107
108 func TestKeccak(t *testing.T) {
109 cryptotest.TestAllImplementations(t, "crypto/sha3", testKeccak)
110 }
111
112 func testKeccak(t *testing.T) {
113 tests := []struct {
114 fn func() *Digest
115 data []byte
116 want string
117 }{
118 {
119 NewLegacyKeccak256,
120 []byte("abc"),
121 "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
122 },
123 {
124 NewLegacyKeccak512,
125 []byte("abc"),
126 "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96",
127 },
128 }
129
130 for _, u := range tests {
131 h := u.fn()
132 h.Write(u.data)
133 got := h.Sum(nil)
134 want := decodeHex(u.want)
135 if !bytes.Equal(got, want) {
136 t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want)
137 }
138 }
139 }
140
141
142 func TestShakeSum(t *testing.T) {
143 cryptotest.TestAllImplementations(t, "crypto/sha3", testShakeSum)
144 }
145
146 func testShakeSum(t *testing.T) {
147 tests := [...]struct {
148 name string
149 hash *SHAKE
150 expectedLen int
151 }{
152 {"SHAKE128", NewShake128(), 32},
153 {"SHAKE256", NewShake256(), 64},
154 {"cSHAKE128", NewCShake128([]byte{'X'}, nil), 32},
155 {"cSHAKE256", NewCShake256([]byte{'X'}, nil), 64},
156 }
157
158 for _, test := range tests {
159 t.Run(test.name, func(t *testing.T) {
160 s := test.hash.Sum(nil)
161 if len(s) != test.expectedLen {
162 t.Errorf("Unexpected digest length: got %d, want %d", len(s), test.expectedLen)
163 }
164 r := make([]byte, test.expectedLen)
165 test.hash.Read(r)
166 if !bytes.Equal(s, r) {
167 t.Errorf("Mismatch between Sum and Read:\nSum: %s\nRead: %s", hex.EncodeToString(s), hex.EncodeToString(r))
168 }
169 })
170 }
171 }
172
173
174
175 func TestUnalignedWrite(t *testing.T) {
176 cryptotest.TestAllImplementations(t, "crypto/sha3", testUnalignedWrite)
177 }
178
179 func testUnalignedWrite(t *testing.T) {
180 buf := sequentialBytes(0x10000)
181 for alg, df := range testDigests {
182 d := df()
183 d.Reset()
184 d.Write(buf)
185 want := d.Sum(nil)
186 d.Reset()
187 for i := 0; i < len(buf); {
188
189
190 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
191 for _, j := range offsets {
192 if v := len(buf) - i; v < j {
193 j = v
194 }
195 d.Write(buf[i : i+j])
196 i += j
197 }
198 }
199 got := d.Sum(nil)
200 if !bytes.Equal(got, want) {
201 t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
202 }
203 }
204
205
206 for alg, df := range testShakes {
207 want := make([]byte, 16)
208 got := make([]byte, 16)
209 d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr))
210
211 d.Reset()
212 d.Write(buf)
213 d.Read(want)
214 d.Reset()
215 for i := 0; i < len(buf); {
216
217
218 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
219 for _, j := range offsets {
220 if v := len(buf) - i; v < j {
221 j = v
222 }
223 d.Write(buf[i : i+j])
224 i += j
225 }
226 }
227 d.Read(got)
228 if !bytes.Equal(got, want) {
229 t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
230 }
231 }
232 }
233
234
235 func TestAppend(t *testing.T) {
236 cryptotest.TestAllImplementations(t, "crypto/sha3", testAppend)
237 }
238
239 func testAppend(t *testing.T) {
240 d := New224()
241
242 for capacity := 2; capacity <= 66; capacity += 64 {
243
244
245 buf := make([]byte, 2, capacity)
246 d.Reset()
247 d.Write([]byte{0xcc})
248 buf = d.Sum(buf)
249 expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
250 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
251 t.Errorf("got %s, want %s", got, expected)
252 }
253 }
254 }
255
256
257 func TestAppendNoRealloc(t *testing.T) {
258 cryptotest.TestAllImplementations(t, "crypto/sha3", testAppendNoRealloc)
259 }
260
261 func testAppendNoRealloc(t *testing.T) {
262 buf := make([]byte, 1, 200)
263 d := New224()
264 d.Write([]byte{0xcc})
265 buf = d.Sum(buf)
266 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
267 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
268 t.Errorf("got %s, want %s", got, expected)
269 }
270 }
271
272
273
274 func TestSqueezing(t *testing.T) {
275 cryptotest.TestAllImplementations(t, "crypto/sha3", testSqueezing)
276 }
277
278 func testSqueezing(t *testing.T) {
279 for algo, v := range testShakes {
280 d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
281 d0.Write([]byte(testString))
282 ref := make([]byte, 32)
283 d0.Read(ref)
284
285 d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
286 d1.Write([]byte(testString))
287 var multiple []byte
288 for range ref {
289 d1.Read(make([]byte, 0))
290 one := make([]byte, 1)
291 d1.Read(one)
292 multiple = append(multiple, one...)
293 }
294 if !bytes.Equal(ref, multiple) {
295 t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref))
296 }
297 }
298 }
299
300
301
302
303
304
305
306 func sequentialBytes(size int) []byte {
307 alignmentOffset := rand.Intn(8)
308 result := make([]byte, size+alignmentOffset)[alignmentOffset:]
309 for i := range result {
310 result[i] = byte(i)
311 }
312 return result
313 }
314
315 func TestReset(t *testing.T) {
316 cryptotest.TestAllImplementations(t, "crypto/sha3", testReset)
317 }
318
319 func testReset(t *testing.T) {
320 out1 := make([]byte, 32)
321 out2 := make([]byte, 32)
322
323 for _, v := range testShakes {
324
325 c := v.constructor(nil, []byte{0x99, 0x98})
326 c.Write(sequentialBytes(0x100))
327 c.Read(out1)
328
329
330 c.Reset()
331 c.Write(sequentialBytes(0x100))
332 c.Read(out2)
333
334 if !bytes.Equal(out1, out2) {
335 t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
336 }
337 }
338 }
339
340 func TestClone(t *testing.T) {
341 cryptotest.TestAllImplementations(t, "crypto/sha3", testClone)
342 }
343
344 func testClone(t *testing.T) {
345 out1 := make([]byte, 16)
346 out2 := make([]byte, 16)
347
348
349 for _, size := range []int{0x1, 0x100} {
350 in := sequentialBytes(size)
351 for _, v := range testShakes {
352 h1 := v.constructor(nil, []byte{0x01})
353 h1.Write([]byte{0x01})
354
355 h2 := h1.Clone()
356
357 h1.Write(in)
358 h1.Read(out1)
359
360 h2.Write(in)
361 h2.Read(out2)
362
363 if !bytes.Equal(out1, out2) {
364 t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2))
365 }
366 }
367 }
368 }
369
370 var sink byte
371
372 func TestAllocations(t *testing.T) {
373 testenv.SkipIfOptimizationOff(t)
374 t.Run("New", func(t *testing.T) {
375 if allocs := testing.AllocsPerRun(10, func() {
376 h := New256()
377 b := []byte("ABC")
378 h.Write(b)
379 out := make([]byte, 0, 32)
380 out = h.Sum(out)
381 sink ^= out[0]
382 }); allocs > 0 {
383 t.Errorf("expected zero allocations, got %0.1f", allocs)
384 }
385 })
386 t.Run("NewShake", func(t *testing.T) {
387 if allocs := testing.AllocsPerRun(10, func() {
388 h := NewShake128()
389 b := []byte("ABC")
390 h.Write(b)
391 out := make([]byte, 0, 32)
392 out = h.Sum(out)
393 sink ^= out[0]
394 h.Read(out)
395 sink ^= out[0]
396 }); allocs > 0 {
397 t.Errorf("expected zero allocations, got %0.1f", allocs)
398 }
399 })
400 t.Run("Sum", func(t *testing.T) {
401 if allocs := testing.AllocsPerRun(10, func() {
402 b := []byte("ABC")
403 out := Sum256(b)
404 sink ^= out[0]
405 }); allocs > 0 {
406 t.Errorf("expected zero allocations, got %0.1f", allocs)
407 }
408 })
409 }
410
411 func TestCSHAKEAccumulated(t *testing.T) {
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455 cryptotest.TestAllImplementations(t, "crypto/sha3", func(t *testing.T) {
456 t.Run("cSHAKE128", func(t *testing.T) {
457 testCSHAKEAccumulated(t, NewCShake128, (1600-256)/8,
458 "bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
459 })
460 t.Run("cSHAKE256", func(t *testing.T) {
461 testCSHAKEAccumulated(t, NewCShake256, (1600-512)/8,
462 "0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef")
463 })
464 })
465 }
466
467 func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) *SHAKE, rate int64, exp string) {
468 rnd := newCShake(nil, nil)
469 acc := newCShake(nil, nil)
470 for n := 0; n < 200; n++ {
471 N := make([]byte, n)
472 rnd.Read(N)
473 for s := 0; s < 200; s++ {
474 S := make([]byte, s)
475 rnd.Read(S)
476
477 c := newCShake(N, S)
478 io.CopyN(c, rnd, 100 )
479 io.CopyN(acc, c, 200)
480
481 c.Reset()
482 io.CopyN(c, rnd, rate)
483 io.CopyN(acc, c, 200)
484
485 c.Reset()
486 io.CopyN(c, rnd, 200 )
487 io.CopyN(acc, c, 200)
488 }
489 }
490 if got := hex.EncodeToString(acc.Sum(nil)[:32]); got != exp {
491 t.Errorf("got %s, want %s", got, exp)
492 }
493 }
494
495 func TestCSHAKELargeS(t *testing.T) {
496 cryptotest.TestAllImplementations(t, "crypto/sha3", testCSHAKELargeS)
497 }
498
499 func testCSHAKELargeS(t *testing.T) {
500 if testing.Short() {
501 t.Skip("skipping test in short mode.")
502 }
503
504
505 const s = (1<<32)/8 + 1000
506 S := make([]byte, s)
507 rnd := NewShake128()
508 rnd.Read(S)
509 c := NewCShake128(nil, S)
510 io.CopyN(c, rnd, 1000)
511
512
513
514
515
516
517
518
519
520
521 exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0"
522 if got := hex.EncodeToString(c.Sum(nil)); got != exp {
523 t.Errorf("got %s, want %s", got, exp)
524 }
525 }
526
527 func TestMarshalUnmarshal(t *testing.T) {
528 cryptotest.TestAllImplementations(t, "crypto/sha3", func(t *testing.T) {
529 t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) })
530 t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) })
531 t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) })
532 t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) })
533 t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewShake128()) })
534 t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewShake256()) })
535 t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake128([]byte("N"), []byte("S"))) })
536 t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake256([]byte("N"), []byte("S"))) })
537 t.Run("Keccak-256", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak256()) })
538 t.Run("Keccak-512", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak512()) })
539 })
540 }
541
542
543 func testMarshalUnmarshal(t *testing.T, h fips.Hash) {
544 buf := make([]byte, 200)
545 rand.Read(buf)
546 n := rand.Intn(200)
547 h.Write(buf)
548 want := h.Sum(nil)
549 h.Reset()
550 h.Write(buf[:n])
551 b, err := h.(encoding.BinaryMarshaler).MarshalBinary()
552 if err != nil {
553 t.Errorf("MarshalBinary: %v", err)
554 }
555 h.Write(bytes.Repeat([]byte{0}, 200))
556 if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary(b); err != nil {
557 t.Errorf("UnmarshalBinary: %v", err)
558 }
559 h.Write(buf[n:])
560 got := h.Sum(nil)
561 if !bytes.Equal(got, want) {
562 t.Errorf("got %x, want %x", got, want)
563 }
564 }
565
566
567 func benchmarkHash(b *testing.B, h fips.Hash, size, num int) {
568 b.StopTimer()
569 h.Reset()
570 data := sequentialBytes(size)
571 b.SetBytes(int64(size * num))
572 b.StartTimer()
573
574 var state []byte
575 for i := 0; i < b.N; i++ {
576 for j := 0; j < num; j++ {
577 h.Write(data)
578 }
579 state = h.Sum(state[:0])
580 }
581 b.StopTimer()
582 h.Reset()
583 }
584
585
586
587 func benchmarkShake(b *testing.B, h *SHAKE, size, num int) {
588 b.StopTimer()
589 h.Reset()
590 data := sequentialBytes(size)
591 d := make([]byte, 32)
592
593 b.SetBytes(int64(size * num))
594 b.StartTimer()
595
596 for i := 0; i < b.N; i++ {
597 h.Reset()
598 for j := 0; j < num; j++ {
599 h.Write(data)
600 }
601 h.Read(d)
602 }
603 }
604
605 func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
606 func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
607 func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
608 func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
609
610 func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
611 func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
612 func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
613 func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
614
615 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
616
617 func Example_sum() {
618 buf := []byte("some data to hash")
619
620 h := make([]byte, 64)
621
622 ShakeSum256(h, buf)
623 fmt.Printf("%x\n", h)
624
625 }
626
627 func Example_mac() {
628 k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
629 buf := []byte("and this is some data to authenticate")
630
631 h := make([]byte, 32)
632 d := NewShake256()
633
634 d.Write(k)
635
636 d.Write(buf)
637
638 d.Read(h)
639 fmt.Printf("%x\n", h)
640
641 }
642
643 func ExampleNewCShake256() {
644 out := make([]byte, 32)
645 msg := []byte("The quick brown fox jumps over the lazy dog")
646
647
648 c1 := NewCShake256([]byte("NAME"), []byte("Partition1"))
649 c1.Write(msg)
650 c1.Read(out)
651 fmt.Println(hex.EncodeToString(out))
652
653
654 c1 = NewCShake256([]byte("NAME"), []byte("Partition2"))
655 c1.Write(msg)
656 c1.Read(out)
657 fmt.Println(hex.EncodeToString(out))
658
659
660 out = make([]byte, 64)
661 c1 = NewCShake256([]byte("NAME"), []byte("Partition1"))
662 c1.Write(msg)
663 c1.Read(out)
664 fmt.Println(hex.EncodeToString(out))
665
666
667 c1.Read(out)
668 fmt.Println(hex.EncodeToString(out))
669
670
671
672
673
674
675 }
676
View as plain text