@@ -27,14 +27,6 @@ const (
27
27
katFilename = "testdata/keccakKats.json.deflate"
28
28
)
29
29
30
- // Internal-use instances of SHAKE used to test against KATs.
31
- func newHashShake128 () hash.Hash {
32
- return & state {rate : 168 , dsbyte : 0x1f , outputLen : 512 }
33
- }
34
- func newHashShake256 () hash.Hash {
35
- return & state {rate : 136 , dsbyte : 0x1f , outputLen : 512 }
36
- }
37
-
38
30
// testDigests contains functions returning hash.Hash instances
39
31
// with output-length equal to the KAT length for SHA-3, Keccak
40
32
// and SHAKE instances.
@@ -45,15 +37,20 @@ var testDigests = map[string]func() hash.Hash{
45
37
"SHA3-512" : New512 ,
46
38
"Keccak-256" : NewLegacyKeccak256 ,
47
39
"Keccak-512" : NewLegacyKeccak512 ,
48
- "SHAKE128" : newHashShake128 ,
49
- "SHAKE256" : newHashShake256 ,
50
40
}
51
41
52
- // testShakes contains functions that return ShakeHash instances for
53
- // testing the ShakeHash-specific interface.
54
- var testShakes = map [string ]func () ShakeHash {
55
- "SHAKE128" : NewShake128 ,
56
- "SHAKE256" : NewShake256 ,
42
+ // testShakes contains functions that return sha3.ShakeHash instances for
43
+ // with output-length equal to the KAT length.
44
+ var testShakes = map [string ]struct {
45
+ constructor func (N []byte , S []byte ) ShakeHash
46
+ defAlgoName string
47
+ defCustomStr string
48
+ }{
49
+ // NewCShake without customization produces same result as SHAKE
50
+ "SHAKE128" : {NewCShake128 , "" , "" },
51
+ "SHAKE256" : {NewCShake256 , "" , "" },
52
+ "cSHAKE128" : {NewCShake128 , "CSHAKE128" , "CustomStrign" },
53
+ "cSHAKE256" : {NewCShake256 , "CSHAKE256" , "CustomStrign" },
57
54
}
58
55
59
56
// decodeHex converts a hex-encoded string into a raw byte string.
@@ -71,6 +68,10 @@ type KeccakKats struct {
71
68
Digest string `json:"digest"`
72
69
Length int64 `json:"length"`
73
70
Message string `json:"message"`
71
+
72
+ // Defined only for cSHAKE
73
+ N string `json:"N"`
74
+ S string `json:"S"`
74
75
}
75
76
}
76
77
@@ -103,10 +104,9 @@ func TestKeccakKats(t *testing.T) {
103
104
t .Errorf ("error decoding KATs: %s" , err )
104
105
}
105
106
106
- // Do the KATs.
107
- for functionName , kats := range katSet .Kats {
108
- d := testDigests [functionName ]()
109
- for _ , kat := range kats {
107
+ for algo , function := range testDigests {
108
+ d := function ()
109
+ for _ , kat := range katSet .Kats [algo ] {
110
110
d .Reset ()
111
111
in , err := hex .DecodeString (kat .Message )
112
112
if err != nil {
@@ -115,8 +115,39 @@ func TestKeccakKats(t *testing.T) {
115
115
d .Write (in [:kat .Length / 8 ])
116
116
got := strings .ToUpper (hex .EncodeToString (d .Sum (nil )))
117
117
if got != kat .Digest {
118
- t .Errorf ("function=%s, implementation=%s, length=%d\n message:\n %s\n got:\n %s\n wanted:\n %s" ,
119
- functionName , impl , kat .Length , kat .Message , got , kat .Digest )
118
+ t .Errorf ("function=%s, implementation=%s, length=%d\n message:\n %s\n got:\n %s\n wanted:\n %s" ,
119
+ algo , impl , kat .Length , kat .Message , got , kat .Digest )
120
+ t .Logf ("wanted %+v" , kat )
121
+ t .FailNow ()
122
+ }
123
+ continue
124
+ }
125
+ }
126
+
127
+ for algo , v := range testShakes {
128
+ for _ , kat := range katSet .Kats [algo ] {
129
+ N , err := hex .DecodeString (kat .N )
130
+ if err != nil {
131
+ t .Errorf ("error decoding KAT: %s" , err )
132
+ }
133
+
134
+ S , err := hex .DecodeString (kat .S )
135
+ if err != nil {
136
+ t .Errorf ("error decoding KAT: %s" , err )
137
+ }
138
+ d := v .constructor (N , S )
139
+ in , err := hex .DecodeString (kat .Message )
140
+ if err != nil {
141
+ t .Errorf ("error decoding KAT: %s" , err )
142
+ }
143
+
144
+ d .Write (in [:kat .Length / 8 ])
145
+ out := make ([]byte , len (kat .Digest )/ 2 )
146
+ d .Read (out )
147
+ got := strings .ToUpper (hex .EncodeToString (out ))
148
+ if got != kat .Digest {
149
+ t .Errorf ("function=%s, implementation=%s, length=%d N:%s\n S:%s\n message:\n %s \n got:\n %s\n wanted:\n %s" ,
150
+ algo , impl , kat .Length , kat .N , kat .S , kat .Message , got , kat .Digest )
120
151
t .Logf ("wanted %+v" , kat )
121
152
t .FailNow ()
122
153
}
@@ -184,6 +215,34 @@ func TestUnalignedWrite(t *testing.T) {
184
215
t .Errorf ("Unaligned writes, implementation=%s, alg=%s\n got %q, want %q" , impl , alg , got , want )
185
216
}
186
217
}
218
+
219
+ // Same for SHAKE
220
+ for alg , df := range testShakes {
221
+ want := make ([]byte , 16 )
222
+ got := make ([]byte , 16 )
223
+ d := df .constructor ([]byte (df .defAlgoName ), []byte (df .defCustomStr ))
224
+
225
+ d .Reset ()
226
+ d .Write (buf )
227
+ d .Read (want )
228
+ d .Reset ()
229
+ for i := 0 ; i < len (buf ); {
230
+ // Cycle through offsets which make a 137 byte sequence.
231
+ // Because 137 is prime this sequence should exercise all corner cases.
232
+ offsets := [17 ]int {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 1 }
233
+ for _ , j := range offsets {
234
+ if v := len (buf ) - i ; v < j {
235
+ j = v
236
+ }
237
+ d .Write (buf [i : i + j ])
238
+ i += j
239
+ }
240
+ }
241
+ d .Read (got )
242
+ if ! bytes .Equal (got , want ) {
243
+ t .Errorf ("Unaligned writes, implementation=%s, alg=%s\n got %q, want %q" , impl , alg , got , want )
244
+ }
245
+ }
187
246
})
188
247
}
189
248
@@ -225,13 +284,13 @@ func TestAppendNoRealloc(t *testing.T) {
225
284
// the same output as repeatedly squeezing the instance.
226
285
func TestSqueezing (t * testing.T ) {
227
286
testUnalignedAndGeneric (t , func (impl string ) {
228
- for functionName , newShakeHash := range testShakes {
229
- d0 := newShakeHash ( )
287
+ for algo , v := range testShakes {
288
+ d0 := v . constructor ([] byte ( v . defAlgoName ), [] byte ( v . defCustomStr ) )
230
289
d0 .Write ([]byte (testString ))
231
290
ref := make ([]byte , 32 )
232
291
d0 .Read (ref )
233
292
234
- d1 := newShakeHash ( )
293
+ d1 := v . constructor ([] byte ( v . defAlgoName ), [] byte ( v . defCustomStr ) )
235
294
d1 .Write ([]byte (testString ))
236
295
var multiple []byte
237
296
for range ref {
@@ -240,7 +299,7 @@ func TestSqueezing(t *testing.T) {
240
299
multiple = append (multiple , one ... )
241
300
}
242
301
if ! bytes .Equal (ref , multiple ) {
243
- t .Errorf ("%s (%s): squeezing %d bytes one at a time failed" , functionName , impl , len (ref ))
302
+ t .Errorf ("%s (%s): squeezing %d bytes one at a time failed" , algo , impl , len (ref ))
244
303
}
245
304
}
246
305
})
@@ -255,6 +314,50 @@ func sequentialBytes(size int) []byte {
255
314
return result
256
315
}
257
316
317
+ func TestReset (t * testing.T ) {
318
+ out1 := make ([]byte , 32 )
319
+ out2 := make ([]byte , 32 )
320
+
321
+ for _ , v := range testShakes {
322
+ // Calculate hash for the first time
323
+ c := v .constructor (nil , []byte {0x99 , 0x98 })
324
+ c .Write (sequentialBytes (0x100 ))
325
+ c .Read (out1 )
326
+
327
+ // Calculate hash again
328
+ c .Reset ()
329
+ c .Write (sequentialBytes (0x100 ))
330
+ c .Read (out2 )
331
+
332
+ if ! bytes .Equal (out1 , out2 ) {
333
+ t .Error ("\n Expected:\n " , out1 , "\n got:\n " , out2 )
334
+ }
335
+ }
336
+ }
337
+
338
+ func TestClone (t * testing.T ) {
339
+ out1 := make ([]byte , 16 )
340
+ out2 := make ([]byte , 16 )
341
+ in := sequentialBytes (0x100 )
342
+
343
+ for _ , v := range testShakes {
344
+ h1 := v .constructor (nil , []byte {0x01 })
345
+ h1 .Write ([]byte {0x01 })
346
+
347
+ h2 := h1 .Clone ()
348
+
349
+ h1 .Write (in )
350
+ h1 .Read (out1 )
351
+
352
+ h2 .Write (in )
353
+ h2 .Read (out2 )
354
+
355
+ if ! bytes .Equal (out1 , out2 ) {
356
+ t .Error ("\n Expected:\n " , hex .EncodeToString (out1 ), "\n got:\n " , hex .EncodeToString (out2 ))
357
+ }
358
+ }
359
+ }
360
+
258
361
// BenchmarkPermutationFunction measures the speed of the permutation function
259
362
// with no input data.
260
363
func BenchmarkPermutationFunction (b * testing.B ) {
@@ -341,3 +444,37 @@ func Example_mac() {
341
444
fmt .Printf ("%x\n " , h )
342
445
// Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
343
446
}
447
+
448
+ func ExampleNewCShake256 () {
449
+ out := make ([]byte , 32 )
450
+ msg := []byte ("The quick brown fox jumps over the lazy dog" )
451
+
452
+ // Example 1: Simple cshake
453
+ c1 := NewCShake256 ([]byte ("NAME" ), []byte ("Partition1" ))
454
+ c1 .Write (msg )
455
+ c1 .Read (out )
456
+ fmt .Println (hex .EncodeToString (out ))
457
+
458
+ // Example 2: Different customization string produces different digest
459
+ c1 = NewCShake256 ([]byte ("NAME" ), []byte ("Partition2" ))
460
+ c1 .Write (msg )
461
+ c1 .Read (out )
462
+ fmt .Println (hex .EncodeToString (out ))
463
+
464
+ // Example 3: Longer output length produces longer digest
465
+ out = make ([]byte , 64 )
466
+ c1 = NewCShake256 ([]byte ("NAME" ), []byte ("Partition1" ))
467
+ c1 .Write (msg )
468
+ c1 .Read (out )
469
+ fmt .Println (hex .EncodeToString (out ))
470
+
471
+ // Example 4: Next read produces different result
472
+ c1 .Read (out )
473
+ fmt .Println (hex .EncodeToString (out ))
474
+
475
+ // Output:
476
+ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b
477
+ //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0
478
+ //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8
479
+ //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109
480
+ }
0 commit comments