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  }