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