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