github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/sha3/sha3_test.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go作者。版权所有。 10 //此源代码的使用受BSD样式的控制 11 //可以在许可文件中找到的许可证。 12 13 package sha3 14 15 //测试包括Keccak团队在 16 //网址:https://github.com/gvanas/keccakcodepackage 17 // 18 //它们只包括按位测试向量的零位情况。 19 //由NIST在FIPS-202草案中发布。 20 21 import ( 22 "bytes" 23 "compress/flate" 24 "encoding/hex" 25 "encoding/json" 26 "hash" 27 "os" 28 "strings" 29 "testing" 30 ) 31 32 const ( 33 testString = "brekeccakkeccak koax koax" 34 katFilename = "testdata/keccakKats.json.deflate" 35 ) 36 37 //用于测试KAT的震动的内部使用实例。 38 func newHashShake128() hash.Hash { 39 return &state{rate: 168, dsbyte: 0x1f, outputLen: 512} 40 } 41 func newHashShake256() hash.Hash { 42 return &state{rate: 136, dsbyte: 0x1f, outputLen: 512} 43 } 44 45 //testDigests contains functions returning hash.Hash instances 46 //输出长度等于SHA-3和 47 //震动实例。 48 var testDigests = map[string]func() hash.Hash{ 49 "SHA3-224": New224, 50 "SHA3-256": New256, 51 "SHA3-384": New384, 52 "SHA3-512": New512, 53 "SHAKE128": newHashShake128, 54 "SHAKE256": newHashShake256, 55 } 56 57 //testshakes包含返回的shakehash实例的函数 58 //测试特定于ShakeHash的接口。 59 var testShakes = map[string]func() ShakeHash{ 60 "SHAKE128": NewShake128, 61 "SHAKE256": NewShake256, 62 } 63 64 //用于封送JSON测试用例的结构。 65 type KeccakKats struct { 66 Kats map[string][]struct { 67 Digest string `json:"digest"` 68 Length int64 `json:"length"` 69 Message string `json:"message"` 70 } 71 } 72 73 func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { 74 xorInOrig, copyOutOrig := xorIn, copyOut 75 xorIn, copyOut = xorInGeneric, copyOutGeneric 76 testf("generic") 77 if xorImplementationUnaligned != "generic" { 78 xorIn, copyOut = xorInUnaligned, copyOutUnaligned 79 testf("unaligned") 80 } 81 xorIn, copyOut = xorInOrig, copyOutOrig 82 } 83 84 //testkeccakkats针对所有 85 //来自HTTPS://GITHUBCOM/GVANAS/KECAKCOCODECAGE的StimeMgKATS 86 //(由于其长度,测试向量存储在keccakcats.json.deflate中。) 87 func TestKeccakKats(t *testing.T) { 88 testUnalignedAndGeneric(t, func(impl string) { 89 //阅读KATS。 90 deflated, err := os.Open(katFilename) 91 if err != nil { 92 t.Errorf("error opening %s: %s", katFilename, err) 93 } 94 file := flate.NewReader(deflated) 95 dec := json.NewDecoder(file) 96 var katSet KeccakKats 97 err = dec.Decode(&katSet) 98 if err != nil { 99 t.Errorf("error decoding KATs: %s", err) 100 } 101 102 //做KATS。 103 for functionName, kats := range katSet.Kats { 104 d := testDigests[functionName]() 105 for _, kat := range kats { 106 d.Reset() 107 in, err := hex.DecodeString(kat.Message) 108 if err != nil { 109 t.Errorf("error decoding KAT: %s", err) 110 } 111 d.Write(in[:kat.Length/8]) 112 got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) 113 if got != kat.Digest { 114 t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", 115 functionName, impl, kat.Length, kat.Message, got, kat.Digest) 116 t.Logf("wanted %+v", kat) 117 t.FailNow() 118 } 119 continue 120 } 121 } 122 }) 123 } 124 125 //TestUnAlignedWrite测试以任意模式写入数据 126 //小输入缓冲器。 127 func TestUnalignedWrite(t *testing.T) { 128 testUnalignedAndGeneric(t, func(impl string) { 129 buf := sequentialBytes(0x10000) 130 for alg, df := range testDigests { 131 d := df() 132 d.Reset() 133 d.Write(buf) 134 want := d.Sum(nil) 135 d.Reset() 136 for i := 0; i < len(buf); { 137 //循环通过偏移,形成137字节序列。 138 //因为137是素数,所以这个序列应该练习所有的角情况。 139 offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} 140 for _, j := range offsets { 141 if v := len(buf) - i; v < j { 142 j = v 143 } 144 d.Write(buf[i : i+j]) 145 i += j 146 } 147 } 148 got := d.Sum(nil) 149 if !bytes.Equal(got, want) { 150 t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) 151 } 152 } 153 }) 154 } 155 156 //TestAppend checks that appending works when reallocation is necessary. 157 func TestAppend(t *testing.T) { 158 testUnalignedAndGeneric(t, func(impl string) { 159 d := New224() 160 161 for capacity := 2; capacity <= 66; capacity += 64 { 162 //第一次循环时,sum必须重新分配。 163 //第二次,不会。 164 buf := make([]byte, 2, capacity) 165 d.Reset() 166 d.Write([]byte{0xcc}) 167 buf = d.Sum(buf) 168 expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" 169 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { 170 t.Errorf("got %s, want %s", got, expected) 171 } 172 } 173 }) 174 } 175 176 //testappendnorealloc在不需要重新分配的情况下测试附加是否有效。 177 func TestAppendNoRealloc(t *testing.T) { 178 testUnalignedAndGeneric(t, func(impl string) { 179 buf := make([]byte, 1, 200) 180 d := New224() 181 d.Write([]byte{0xcc}) 182 buf = d.Sum(buf) 183 expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" 184 if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { 185 t.Errorf("%s: got %s, want %s", impl, got, expected) 186 } 187 }) 188 } 189 190 //测试压缩检查压缩一次产生的全部输出 191 //与重复压缩实例的输出相同。 192 func TestSqueezing(t *testing.T) { 193 testUnalignedAndGeneric(t, func(impl string) { 194 for functionName, newShakeHash := range testShakes { 195 d0 := newShakeHash() 196 d0.Write([]byte(testString)) 197 ref := make([]byte, 32) 198 d0.Read(ref) 199 200 d1 := newShakeHash() 201 d1.Write([]byte(testString)) 202 var multiple []byte 203 for range ref { 204 one := make([]byte, 1) 205 d1.Read(one) 206 multiple = append(multiple, one...) 207 } 208 if !bytes.Equal(ref, multiple) { 209 t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref)) 210 } 211 } 212 }) 213 } 214 215 //sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. 216 func sequentialBytes(size int) []byte { 217 result := make([]byte, size) 218 for i := range result { 219 result[i] = byte(i) 220 } 221 return result 222 } 223 224 //基准置换函数测量置换函数的速度 225 //没有输入数据。 226 func BenchmarkPermutationFunction(b *testing.B) { 227 b.SetBytes(int64(200)) 228 var lanes [25]uint64 229 for i := 0; i < b.N; i++ { 230 keccakF1600(&lanes) 231 } 232 } 233 234 //BenchmarkHash测试每个buflen的哈希num缓冲区的速度。 235 func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { 236 b.StopTimer() 237 h.Reset() 238 data := sequentialBytes(size) 239 b.SetBytes(int64(size * num)) 240 b.StartTimer() 241 242 var state []byte 243 for i := 0; i < b.N; i++ { 244 for j := 0; j < num; j++ { 245 h.Write(data) 246 } 247 state = h.Sum(state[:0]) 248 } 249 b.StopTimer() 250 h.Reset() 251 } 252 253 //BenchmarkShake专门针对那些不支持 254 //读取输出时需要副本。 255 func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { 256 b.StopTimer() 257 h.Reset() 258 data := sequentialBytes(size) 259 d := make([]byte, 32) 260 261 b.SetBytes(int64(size * num)) 262 b.StartTimer() 263 264 for i := 0; i < b.N; i++ { 265 h.Reset() 266 for j := 0; j < num; j++ { 267 h.Write(data) 268 } 269 h.Read(d) 270 } 271 } 272 273 func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } 274 func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } 275 func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } 276 func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } 277 278 func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } 279 func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } 280 func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } 281 func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } 282 283 func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } 284 285 func Example_sum() { 286 buf := []byte("some data to hash") 287 //哈希需要64字节长才能具有256位的抗冲突性。 288 h := make([]byte, 64) 289 //计算一个64字节的buf散列并将其放入h中。 290 ShakeSum256(h, buf) 291 } 292 293 func Example_mac() { 294 k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") 295 buf := []byte("and this is some data to authenticate") 296 //一个输出为32字节的MAC具有256位的安全性——如果您至少使用一个32字节长的密钥。 297 h := make([]byte, 32) 298 d := NewShake256() 299 //将密钥写入哈希。 300 d.Write(k) 301 //现在写数据。 302 d.Write(buf) 303 //从散列中读取32个字节的输出到h。 304 d.Read(h) 305 }