github.com/turingchain2020/turingchain@v1.1.21/common/crypto/sha3/sha3_test.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Copyright 2014 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 package sha3 10 11 // Tests include all the ShortMsgKATs provided by the Keccak team at 12 // https://github.com/gvanas/KeccakCodePackage 13 // 14 // They only include the zero-bit case of the bitwise testvectors 15 // published by NIST in the draft of FIPS-202. 16 17 import ( 18 "bytes" 19 "compress/flate" 20 "encoding/hex" 21 "encoding/json" 22 "fmt" 23 "hash" 24 "os" 25 "strings" 26 "testing" 27 28 "github.com/stretchr/testify/assert" 29 ) 30 31 const ( 32 testString = "brekeccakkeccak koax koax" 33 katFilename = "testdata/keccakKats.json.deflate" 34 ) 35 36 // Internal-use instances of SHAKE used to test against KATs. 37 func newHashShake128() hash.Hash { 38 return &state{rate: 168, dsbyte: 0x1f, outputLen: 512} 39 } 40 func newHashShake256() hash.Hash { 41 return &state{rate: 136, dsbyte: 0x1f, outputLen: 512} 42 } 43 44 // testDigests contains functions returning hash.Hash instances 45 // with output-length equal to the KAT length for SHA-3, Keccak 46 // and SHAKE instances. 47 var testDigests = map[string]func() hash.Hash{ 48 "SHA3-224": New224, 49 "SHA3-256": New256, 50 "SHA3-384": New384, 51 "SHA3-512": New512, 52 "Keccak-256": NewLegacyKeccak256, 53 "SHAKE128": newHashShake128, 54 "SHAKE256": newHashShake256, 55 } 56 57 // testShakes contains functions that return ShakeHash instances for 58 // testing the ShakeHash-specific interface. 59 var testShakes = map[string]func() ShakeHash{ 60 "SHAKE128": NewShake128, 61 "SHAKE256": NewShake256, 62 } 63 64 // decodeHex converts a hex-encoded string into a raw byte string. 65 func decodeHex(s string) []byte { 66 b, err := hex.DecodeString(s) 67 if err != nil { 68 panic(err) 69 } 70 return b 71 } 72 73 // structs used to marshal JSON test-cases. 74 type KeccakKats struct { 75 Kats map[string][]struct { 76 Digest string `json:"digest"` 77 Length int64 `json:"length"` 78 Message string `json:"message"` 79 } 80 } 81 82 const xorImplementationUnaligned = "generic" 83 84 func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { 85 xorInOrig, copyOutOrig := xorIn, copyOut 86 xorIn, copyOut = xorInGeneric, copyOutGeneric 87 testf("generic") 88 if xorImplementationUnaligned != "generic" { 89 xorIn, copyOut = xorInUnaligned, copyOutUnaligned 90 testf("unaligned") 91 } 92 xorIn, copyOut = xorInOrig, copyOutOrig 93 } 94 95 // TestKeccakKats tests the SHA-3 and Shake implementations against all the 96 // ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage 97 // (The testvectors are stored in keccakKats.json.deflate due to their length.) 98 func TestKeccakKats(t *testing.T) { 99 testUnalignedAndGeneric(t, func(impl string) { 100 // Read the KATs. 101 deflated, err := os.Open(katFilename) 102 if err != nil { 103 t.Errorf("error opening %s: %s", katFilename, err) 104 } 105 file := flate.NewReader(deflated) 106 dec := json.NewDecoder(file) 107 var katSet KeccakKats 108 err = dec.Decode(&katSet) 109 if err != nil { 110 t.Errorf("error decoding KATs: %s", err) 111 } 112 113 // Do the KATs. 114 for functionName, kats := range katSet.Kats { 115 d := testDigests[functionName]() 116 for _, kat := range kats { 117 d.Reset() 118 in, err := hex.DecodeString(kat.Message) 119 if err != nil { 120 t.Errorf("error decoding KAT: %s", err) 121 } 122 d.Write(in[:kat.Length/8]) 123 got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) 124 if got != kat.Digest { 125 t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", 126 functionName, impl, kat.Length, kat.Message, got, kat.Digest) 127 t.Logf("wanted %+v", kat) 128 t.FailNow() 129 } 130 continue 131 } 132 } 133 }) 134 } 135 136 // TestKeccak does a basic test of the non-standardized Keccak hash functions. 137 func TestKeccak(t *testing.T) { 138 tests := []struct { 139 fn func() hash.Hash 140 data []byte 141 want string 142 }{ 143 { 144 NewLegacyKeccak256, 145 []byte("abc"), 146 "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45", 147 }, 148 } 149 150 for _, u := range tests { 151 h := u.fn() 152 h.Write(u.data) 153 got := h.Sum(nil) 154 want := decodeHex(u.want) 155 if !bytes.Equal(got, want) { 156 t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want) 157 } 158 } 159 } 160 161 // TestUnalignedWrite tests that writing data in an arbitrary pattern with 162 // small input buffers. 163 func TestUnalignedWrite(t *testing.T) { 164 testUnalignedAndGeneric(t, func(impl string) { 165 buf := sequentialBytes(0x10000) 166 for alg, df := range testDigests { 167 d := df() 168 d.Reset() 169 d.Write(buf) 170 want := d.Sum(nil) 171 d.Reset() 172 for i := 0; i < len(buf); { 173 // Cycle through offsets which make a 137 byte sequence. 174 // Because 137 is prime this sequence should exercise all corner cases. 175 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} 176 for _, j := range offsets { 177 if v := len(buf) - i; v < j { 178 j = v 179 } 180 d.Write(buf[i : i+j]) 181 i += j 182 } 183 } 184 got := d.Sum(nil) 185 if !bytes.Equal(got, want) { 186 t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) 187 } 188 } 189 }) 190 } 191 192 // TestAppend checks that appending works when reallocation is necessary. 193 func TestAppend(t *testing.T) { 194 testUnalignedAndGeneric(t, func(impl string) { 195 d := New224() 196 197 for capacity := 2; capacity <= 66; capacity += 64 { 198 // The first time around the loop, Sum will have to reallocate. 199 // The second time, it will not. 200 buf := make([]byte, 2, capacity) 201 d.Reset() 202 d.Write([]byte{0xcc}) 203 buf = d.Sum(buf) 204 expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" 205 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { 206 t.Errorf("got %s, want %s", got, expected) 207 } 208 } 209 }) 210 } 211 212 // TestAppendNoRealloc tests that appending works when no reallocation is necessary. 213 func TestAppendNoRealloc(t *testing.T) { 214 testUnalignedAndGeneric(t, func(impl string) { 215 buf := make([]byte, 1, 200) 216 d := New224() 217 d.Write([]byte{0xcc}) 218 buf = d.Sum(buf) 219 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" 220 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { 221 t.Errorf("%s: got %s, want %s", impl, got, expected) 222 } 223 }) 224 } 225 226 // TestSqueezing checks that squeezing the full output a single time produces 227 // the same output as repeatedly squeezing the instance. 228 func TestSqueezing(t *testing.T) { 229 testUnalignedAndGeneric(t, func(impl string) { 230 for functionName, newShakeHash := range testShakes { 231 d0 := newShakeHash() 232 d0.Write([]byte(testString)) 233 ref := make([]byte, 32) 234 d0.Read(ref) 235 236 d1 := newShakeHash() 237 d1.Write([]byte(testString)) 238 var multiple []byte 239 for range ref { 240 one := make([]byte, 1) 241 d1.Read(one) 242 multiple = append(multiple, one...) 243 } 244 if !bytes.Equal(ref, multiple) { 245 t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref)) 246 } 247 } 248 }) 249 } 250 251 // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. 252 func sequentialBytes(size int) []byte { 253 result := make([]byte, size) 254 for i := range result { 255 result[i] = byte(i) 256 } 257 return result 258 } 259 260 // BenchmarkPermutationFunction measures the speed of the permutation function 261 // with no input data. 262 func BenchmarkPermutationFunction(b *testing.B) { 263 b.SetBytes(int64(200)) 264 var lanes [25]uint64 265 for i := 0; i < b.N; i++ { 266 keccakF1600(&lanes) 267 } 268 } 269 270 // benchmarkHash tests the speed to hash num buffers of buflen each. 271 func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { 272 b.StopTimer() 273 h.Reset() 274 data := sequentialBytes(size) 275 b.SetBytes(int64(size * num)) 276 b.StartTimer() 277 278 var state []byte 279 for i := 0; i < b.N; i++ { 280 for j := 0; j < num; j++ { 281 h.Write(data) 282 } 283 state = h.Sum(state[:0]) 284 } 285 b.StopTimer() 286 h.Reset() 287 } 288 289 // benchmarkShake is specialized to the Shake instances, which don't 290 // require a copy on reading output. 291 func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { 292 b.StopTimer() 293 h.Reset() 294 data := sequentialBytes(size) 295 d := make([]byte, 32) 296 297 b.SetBytes(int64(size * num)) 298 b.StartTimer() 299 300 for i := 0; i < b.N; i++ { 301 h.Reset() 302 for j := 0; j < num; j++ { 303 h.Write(data) 304 } 305 h.Read(d) 306 } 307 } 308 309 func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } 310 func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } 311 func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } 312 func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } 313 314 func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } 315 func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } 316 func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } 317 func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } 318 319 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } 320 321 func Example_sum() { 322 buf := []byte("some data to hash") 323 // A hash needs to be 64 bytes long to have 256-bit collision resistance. 324 h := make([]byte, 64) 325 // Compute a 64-byte hash of buf and put it in h. 326 ShakeSum256(h, buf) 327 fmt.Printf("%x\n", h) 328 // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d 329 } 330 331 func Example_mac() { 332 k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") 333 buf := []byte("and this is some data to authenticate") 334 // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. 335 h := make([]byte, 32) 336 d := NewShake256() 337 // Write the key into the hash. 338 d.Write(k) 339 // Now write the data. 340 d.Write(buf) 341 // Read 32 bytes of output from the hash into h. 342 d.Read(h) 343 fmt.Printf("%x\n", h) 344 // ProtoToJson: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff 345 } 346 347 func TestNew(t *testing.T) { 348 d28 := Sum224(nil) 349 assert.True(t, len(d28) == 28) 350 351 d32 := Sum256(nil) 352 assert.True(t, len(d32) == 32) 353 354 d48 := Sum384(nil) 355 assert.True(t, len(d48) == 48) 356 357 d64 := Sum512(nil) 358 assert.True(t, len(d64) == 64) 359 360 d32 = KeccakSum256(nil) 361 assert.True(t, len(d32) == 32) 362 363 d32 = KeccakSum512(nil) 364 assert.True(t, len(d32) == 32) 365 }