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