Source file src/crypto/internal/fips/sha3/sha3_test.go

     1  // Copyright 2014 The Go Authors. 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  package sha3_test
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/internal/cryptotest"
    10  	"crypto/internal/fips"
    11  	. "crypto/internal/fips/sha3"
    12  	"encoding"
    13  	"encoding/hex"
    14  	"fmt"
    15  	"internal/testenv"
    16  	"io"
    17  	"math/rand"
    18  	"strings"
    19  	"testing"
    20  )
    21  
    22  // TODO(fips): move tests to the stdlib crypto/sha3 package.
    23  
    24  // Sum224 returns the SHA3-224 digest of the data.
    25  func Sum224(data []byte) (digest [28]byte) {
    26  	h := New224()
    27  	h.Write(data)
    28  	h.Sum(digest[:0])
    29  	return
    30  }
    31  
    32  // Sum256 returns the SHA3-256 digest of the data.
    33  func Sum256(data []byte) (digest [32]byte) {
    34  	h := New256()
    35  	h.Write(data)
    36  	h.Sum(digest[:0])
    37  	return
    38  }
    39  
    40  // Sum384 returns the SHA3-384 digest of the data.
    41  func Sum384(data []byte) (digest [48]byte) {
    42  	h := New384()
    43  	h.Write(data)
    44  	h.Sum(digest[:0])
    45  	return
    46  }
    47  
    48  // Sum512 returns the SHA3-512 digest of the data.
    49  func Sum512(data []byte) (digest [64]byte) {
    50  	h := New512()
    51  	h.Write(data)
    52  	h.Sum(digest[:0])
    53  	return
    54  }
    55  
    56  // ShakeSum128 writes an arbitrary-length digest of data into hash.
    57  func ShakeSum128(hash, data []byte) {
    58  	h := NewShake128()
    59  	h.Write(data)
    60  	h.Read(hash)
    61  }
    62  
    63  // ShakeSum256 writes an arbitrary-length digest of data into hash.
    64  func ShakeSum256(hash, data []byte) {
    65  	h := NewShake256()
    66  	h.Write(data)
    67  	h.Read(hash)
    68  }
    69  
    70  const testString = "brekeccakkeccak koax koax"
    71  
    72  // testDigests contains functions returning hash.Hash instances
    73  // with output-length equal to the KAT length for SHA-3, Keccak
    74  // and SHAKE instances.
    75  var testDigests = map[string]func() *Digest{
    76  	"SHA3-224":   New224,
    77  	"SHA3-256":   New256,
    78  	"SHA3-384":   New384,
    79  	"SHA3-512":   New512,
    80  	"Keccak-256": NewLegacyKeccak256,
    81  	"Keccak-512": NewLegacyKeccak512,
    82  }
    83  
    84  // testShakes contains functions that return *sha3.SHAKE instances for
    85  // with output-length equal to the KAT length.
    86  var testShakes = map[string]struct {
    87  	constructor  func(N []byte, S []byte) *SHAKE
    88  	defAlgoName  string
    89  	defCustomStr string
    90  }{
    91  	// NewCShake without customization produces same result as SHAKE
    92  	"SHAKE128":  {NewCShake128, "", ""},
    93  	"SHAKE256":  {NewCShake256, "", ""},
    94  	"cSHAKE128": {NewCShake128, "CSHAKE128", "CustomString"},
    95  	"cSHAKE256": {NewCShake256, "CSHAKE256", "CustomString"},
    96  }
    97  
    98  // decodeHex converts a hex-encoded string into a raw byte string.
    99  func decodeHex(s string) []byte {
   100  	b, err := hex.DecodeString(s)
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  	return b
   105  }
   106  
   107  // TestKeccak does a basic test of the non-standardized Keccak hash functions.
   108  func TestKeccak(t *testing.T) {
   109  	cryptotest.TestAllImplementations(t, "crypto/sha3", testKeccak)
   110  }
   111  
   112  func testKeccak(t *testing.T) {
   113  	tests := []struct {
   114  		fn   func() *Digest
   115  		data []byte
   116  		want string
   117  	}{
   118  		{
   119  			NewLegacyKeccak256,
   120  			[]byte("abc"),
   121  			"4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
   122  		},
   123  		{
   124  			NewLegacyKeccak512,
   125  			[]byte("abc"),
   126  			"18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96",
   127  		},
   128  	}
   129  
   130  	for _, u := range tests {
   131  		h := u.fn()
   132  		h.Write(u.data)
   133  		got := h.Sum(nil)
   134  		want := decodeHex(u.want)
   135  		if !bytes.Equal(got, want) {
   136  			t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want)
   137  		}
   138  	}
   139  }
   140  
   141  // TestShakeSum tests that the output of Sum matches the output of Read.
   142  func TestShakeSum(t *testing.T) {
   143  	cryptotest.TestAllImplementations(t, "crypto/sha3", testShakeSum)
   144  }
   145  
   146  func testShakeSum(t *testing.T) {
   147  	tests := [...]struct {
   148  		name        string
   149  		hash        *SHAKE
   150  		expectedLen int
   151  	}{
   152  		{"SHAKE128", NewShake128(), 32},
   153  		{"SHAKE256", NewShake256(), 64},
   154  		{"cSHAKE128", NewCShake128([]byte{'X'}, nil), 32},
   155  		{"cSHAKE256", NewCShake256([]byte{'X'}, nil), 64},
   156  	}
   157  
   158  	for _, test := range tests {
   159  		t.Run(test.name, func(t *testing.T) {
   160  			s := test.hash.Sum(nil)
   161  			if len(s) != test.expectedLen {
   162  				t.Errorf("Unexpected digest length: got %d, want %d", len(s), test.expectedLen)
   163  			}
   164  			r := make([]byte, test.expectedLen)
   165  			test.hash.Read(r)
   166  			if !bytes.Equal(s, r) {
   167  				t.Errorf("Mismatch between Sum and Read:\nSum:  %s\nRead: %s", hex.EncodeToString(s), hex.EncodeToString(r))
   168  			}
   169  		})
   170  	}
   171  }
   172  
   173  // TestUnalignedWrite tests that writing data in an arbitrary pattern with
   174  // small input buffers.
   175  func TestUnalignedWrite(t *testing.T) {
   176  	cryptotest.TestAllImplementations(t, "crypto/sha3", testUnalignedWrite)
   177  }
   178  
   179  func testUnalignedWrite(t *testing.T) {
   180  	buf := sequentialBytes(0x10000)
   181  	for alg, df := range testDigests {
   182  		d := df()
   183  		d.Reset()
   184  		d.Write(buf)
   185  		want := d.Sum(nil)
   186  		d.Reset()
   187  		for i := 0; i < len(buf); {
   188  			// Cycle through offsets which make a 137 byte sequence.
   189  			// Because 137 is prime this sequence should exercise all corner cases.
   190  			offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
   191  			for _, j := range offsets {
   192  				if v := len(buf) - i; v < j {
   193  					j = v
   194  				}
   195  				d.Write(buf[i : i+j])
   196  				i += j
   197  			}
   198  		}
   199  		got := d.Sum(nil)
   200  		if !bytes.Equal(got, want) {
   201  			t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
   202  		}
   203  	}
   204  
   205  	// Same for SHAKE
   206  	for alg, df := range testShakes {
   207  		want := make([]byte, 16)
   208  		got := make([]byte, 16)
   209  		d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr))
   210  
   211  		d.Reset()
   212  		d.Write(buf)
   213  		d.Read(want)
   214  		d.Reset()
   215  		for i := 0; i < len(buf); {
   216  			// Cycle through offsets which make a 137 byte sequence.
   217  			// Because 137 is prime this sequence should exercise all corner cases.
   218  			offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
   219  			for _, j := range offsets {
   220  				if v := len(buf) - i; v < j {
   221  					j = v
   222  				}
   223  				d.Write(buf[i : i+j])
   224  				i += j
   225  			}
   226  		}
   227  		d.Read(got)
   228  		if !bytes.Equal(got, want) {
   229  			t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
   230  		}
   231  	}
   232  }
   233  
   234  // TestAppend checks that appending works when reallocation is necessary.
   235  func TestAppend(t *testing.T) {
   236  	cryptotest.TestAllImplementations(t, "crypto/sha3", testAppend)
   237  }
   238  
   239  func testAppend(t *testing.T) {
   240  	d := New224()
   241  
   242  	for capacity := 2; capacity <= 66; capacity += 64 {
   243  		// The first time around the loop, Sum will have to reallocate.
   244  		// The second time, it will not.
   245  		buf := make([]byte, 2, capacity)
   246  		d.Reset()
   247  		d.Write([]byte{0xcc})
   248  		buf = d.Sum(buf)
   249  		expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
   250  		if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
   251  			t.Errorf("got %s, want %s", got, expected)
   252  		}
   253  	}
   254  }
   255  
   256  // TestAppendNoRealloc tests that appending works when no reallocation is necessary.
   257  func TestAppendNoRealloc(t *testing.T) {
   258  	cryptotest.TestAllImplementations(t, "crypto/sha3", testAppendNoRealloc)
   259  }
   260  
   261  func testAppendNoRealloc(t *testing.T) {
   262  	buf := make([]byte, 1, 200)
   263  	d := New224()
   264  	d.Write([]byte{0xcc})
   265  	buf = d.Sum(buf)
   266  	expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
   267  	if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
   268  		t.Errorf("got %s, want %s", got, expected)
   269  	}
   270  }
   271  
   272  // TestSqueezing checks that squeezing the full output a single time produces
   273  // the same output as repeatedly squeezing the instance.
   274  func TestSqueezing(t *testing.T) {
   275  	cryptotest.TestAllImplementations(t, "crypto/sha3", testSqueezing)
   276  }
   277  
   278  func testSqueezing(t *testing.T) {
   279  	for algo, v := range testShakes {
   280  		d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
   281  		d0.Write([]byte(testString))
   282  		ref := make([]byte, 32)
   283  		d0.Read(ref)
   284  
   285  		d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
   286  		d1.Write([]byte(testString))
   287  		var multiple []byte
   288  		for range ref {
   289  			d1.Read(make([]byte, 0))
   290  			one := make([]byte, 1)
   291  			d1.Read(one)
   292  			multiple = append(multiple, one...)
   293  		}
   294  		if !bytes.Equal(ref, multiple) {
   295  			t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref))
   296  		}
   297  	}
   298  }
   299  
   300  // sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
   301  //
   302  // The alignment of each slice is intentionally randomized to detect alignment
   303  // issues in the implementation. See https://golang.org/issue/37644.
   304  // Ideally, the compiler should fuzz the alignment itself.
   305  // (See https://golang.org/issue/35128.)
   306  func sequentialBytes(size int) []byte {
   307  	alignmentOffset := rand.Intn(8)
   308  	result := make([]byte, size+alignmentOffset)[alignmentOffset:]
   309  	for i := range result {
   310  		result[i] = byte(i)
   311  	}
   312  	return result
   313  }
   314  
   315  func TestReset(t *testing.T) {
   316  	cryptotest.TestAllImplementations(t, "crypto/sha3", testReset)
   317  }
   318  
   319  func testReset(t *testing.T) {
   320  	out1 := make([]byte, 32)
   321  	out2 := make([]byte, 32)
   322  
   323  	for _, v := range testShakes {
   324  		// Calculate hash for the first time
   325  		c := v.constructor(nil, []byte{0x99, 0x98})
   326  		c.Write(sequentialBytes(0x100))
   327  		c.Read(out1)
   328  
   329  		// Calculate hash again
   330  		c.Reset()
   331  		c.Write(sequentialBytes(0x100))
   332  		c.Read(out2)
   333  
   334  		if !bytes.Equal(out1, out2) {
   335  			t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
   336  		}
   337  	}
   338  }
   339  
   340  func TestClone(t *testing.T) {
   341  	cryptotest.TestAllImplementations(t, "crypto/sha3", testClone)
   342  }
   343  
   344  func testClone(t *testing.T) {
   345  	out1 := make([]byte, 16)
   346  	out2 := make([]byte, 16)
   347  
   348  	// Test for sizes smaller and larger than block size.
   349  	for _, size := range []int{0x1, 0x100} {
   350  		in := sequentialBytes(size)
   351  		for _, v := range testShakes {
   352  			h1 := v.constructor(nil, []byte{0x01})
   353  			h1.Write([]byte{0x01})
   354  
   355  			h2 := h1.Clone()
   356  
   357  			h1.Write(in)
   358  			h1.Read(out1)
   359  
   360  			h2.Write(in)
   361  			h2.Read(out2)
   362  
   363  			if !bytes.Equal(out1, out2) {
   364  				t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2))
   365  			}
   366  		}
   367  	}
   368  }
   369  
   370  var sink byte
   371  
   372  func TestAllocations(t *testing.T) {
   373  	testenv.SkipIfOptimizationOff(t)
   374  	t.Run("New", func(t *testing.T) {
   375  		if allocs := testing.AllocsPerRun(10, func() {
   376  			h := New256()
   377  			b := []byte("ABC")
   378  			h.Write(b)
   379  			out := make([]byte, 0, 32)
   380  			out = h.Sum(out)
   381  			sink ^= out[0]
   382  		}); allocs > 0 {
   383  			t.Errorf("expected zero allocations, got %0.1f", allocs)
   384  		}
   385  	})
   386  	t.Run("NewShake", func(t *testing.T) {
   387  		if allocs := testing.AllocsPerRun(10, func() {
   388  			h := NewShake128()
   389  			b := []byte("ABC")
   390  			h.Write(b)
   391  			out := make([]byte, 0, 32)
   392  			out = h.Sum(out)
   393  			sink ^= out[0]
   394  			h.Read(out)
   395  			sink ^= out[0]
   396  		}); allocs > 0 {
   397  			t.Errorf("expected zero allocations, got %0.1f", allocs)
   398  		}
   399  	})
   400  	t.Run("Sum", func(t *testing.T) {
   401  		if allocs := testing.AllocsPerRun(10, func() {
   402  			b := []byte("ABC")
   403  			out := Sum256(b)
   404  			sink ^= out[0]
   405  		}); allocs > 0 {
   406  			t.Errorf("expected zero allocations, got %0.1f", allocs)
   407  		}
   408  	})
   409  }
   410  
   411  func TestCSHAKEAccumulated(t *testing.T) {
   412  	// Generated with pycryptodome@3.20.0
   413  	//
   414  	//    from Crypto.Hash import cSHAKE128
   415  	//    rng = cSHAKE128.new()
   416  	//    acc = cSHAKE128.new()
   417  	//    for n in range(200):
   418  	//        N = rng.read(n)
   419  	//        for s in range(200):
   420  	//            S = rng.read(s)
   421  	//            c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
   422  	//            c.update(rng.read(100))
   423  	//            acc.update(c.read(200))
   424  	//            c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
   425  	//            c.update(rng.read(168))
   426  	//            acc.update(c.read(200))
   427  	//            c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
   428  	//            c.update(rng.read(200))
   429  	//            acc.update(c.read(200))
   430  	//    print(acc.read(32).hex())
   431  	//
   432  	// and with @noble/hashes@v1.5.0
   433  	//
   434  	//    import { bytesToHex } from "@noble/hashes/utils";
   435  	//    import { cshake128 } from "@noble/hashes/sha3-addons";
   436  	//    const rng = cshake128.create();
   437  	//    const acc = cshake128.create();
   438  	//    for (let n = 0; n < 200; n++) {
   439  	//        const N = rng.xof(n);
   440  	//        for (let s = 0; s < 200; s++) {
   441  	//            const S = rng.xof(s);
   442  	//            let c = cshake128.create({ NISTfn: N, personalization: S });
   443  	//            c.update(rng.xof(100));
   444  	//            acc.update(c.xof(200));
   445  	//            c = cshake128.create({ NISTfn: N, personalization: S });
   446  	//            c.update(rng.xof(168));
   447  	//            acc.update(c.xof(200));
   448  	//            c = cshake128.create({ NISTfn: N, personalization: S });
   449  	//            c.update(rng.xof(200));
   450  	//            acc.update(c.xof(200));
   451  	//        }
   452  	//    }
   453  	//    console.log(bytesToHex(acc.xof(32)));
   454  	//
   455  	cryptotest.TestAllImplementations(t, "crypto/sha3", func(t *testing.T) {
   456  		t.Run("cSHAKE128", func(t *testing.T) {
   457  			testCSHAKEAccumulated(t, NewCShake128, (1600-256)/8,
   458  				"bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
   459  		})
   460  		t.Run("cSHAKE256", func(t *testing.T) {
   461  			testCSHAKEAccumulated(t, NewCShake256, (1600-512)/8,
   462  				"0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef")
   463  		})
   464  	})
   465  }
   466  
   467  func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) *SHAKE, rate int64, exp string) {
   468  	rnd := newCShake(nil, nil)
   469  	acc := newCShake(nil, nil)
   470  	for n := 0; n < 200; n++ {
   471  		N := make([]byte, n)
   472  		rnd.Read(N)
   473  		for s := 0; s < 200; s++ {
   474  			S := make([]byte, s)
   475  			rnd.Read(S)
   476  
   477  			c := newCShake(N, S)
   478  			io.CopyN(c, rnd, 100 /* < rate */)
   479  			io.CopyN(acc, c, 200)
   480  
   481  			c.Reset()
   482  			io.CopyN(c, rnd, rate)
   483  			io.CopyN(acc, c, 200)
   484  
   485  			c.Reset()
   486  			io.CopyN(c, rnd, 200 /* > rate */)
   487  			io.CopyN(acc, c, 200)
   488  		}
   489  	}
   490  	if got := hex.EncodeToString(acc.Sum(nil)[:32]); got != exp {
   491  		t.Errorf("got %s, want %s", got, exp)
   492  	}
   493  }
   494  
   495  func TestCSHAKELargeS(t *testing.T) {
   496  	cryptotest.TestAllImplementations(t, "crypto/sha3", testCSHAKELargeS)
   497  }
   498  
   499  func testCSHAKELargeS(t *testing.T) {
   500  	if testing.Short() {
   501  		t.Skip("skipping test in short mode.")
   502  	}
   503  
   504  	// See https://go.dev/issue/66232.
   505  	const s = (1<<32)/8 + 1000 // s * 8 > 2^32
   506  	S := make([]byte, s)
   507  	rnd := NewShake128()
   508  	rnd.Read(S)
   509  	c := NewCShake128(nil, S)
   510  	io.CopyN(c, rnd, 1000)
   511  
   512  	// Generated with pycryptodome@3.20.0
   513  	//
   514  	//    from Crypto.Hash import cSHAKE128
   515  	//    rng = cSHAKE128.new()
   516  	//    S = rng.read(536871912)
   517  	//    c = cSHAKE128.new(custom=S)
   518  	//    c.update(rng.read(1000))
   519  	//    print(c.read(32).hex())
   520  	//
   521  	exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0"
   522  	if got := hex.EncodeToString(c.Sum(nil)); got != exp {
   523  		t.Errorf("got %s, want %s", got, exp)
   524  	}
   525  }
   526  
   527  func TestMarshalUnmarshal(t *testing.T) {
   528  	cryptotest.TestAllImplementations(t, "crypto/sha3", func(t *testing.T) {
   529  		t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) })
   530  		t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) })
   531  		t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) })
   532  		t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) })
   533  		t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewShake128()) })
   534  		t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewShake256()) })
   535  		t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake128([]byte("N"), []byte("S"))) })
   536  		t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake256([]byte("N"), []byte("S"))) })
   537  		t.Run("Keccak-256", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak256()) })
   538  		t.Run("Keccak-512", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak512()) })
   539  	})
   540  }
   541  
   542  // TODO(filippo): move this to crypto/internal/cryptotest.
   543  func testMarshalUnmarshal(t *testing.T, h fips.Hash) {
   544  	buf := make([]byte, 200)
   545  	rand.Read(buf)
   546  	n := rand.Intn(200)
   547  	h.Write(buf)
   548  	want := h.Sum(nil)
   549  	h.Reset()
   550  	h.Write(buf[:n])
   551  	b, err := h.(encoding.BinaryMarshaler).MarshalBinary()
   552  	if err != nil {
   553  		t.Errorf("MarshalBinary: %v", err)
   554  	}
   555  	h.Write(bytes.Repeat([]byte{0}, 200))
   556  	if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary(b); err != nil {
   557  		t.Errorf("UnmarshalBinary: %v", err)
   558  	}
   559  	h.Write(buf[n:])
   560  	got := h.Sum(nil)
   561  	if !bytes.Equal(got, want) {
   562  		t.Errorf("got %x, want %x", got, want)
   563  	}
   564  }
   565  
   566  // benchmarkHash tests the speed to hash num buffers of buflen each.
   567  func benchmarkHash(b *testing.B, h fips.Hash, size, num int) {
   568  	b.StopTimer()
   569  	h.Reset()
   570  	data := sequentialBytes(size)
   571  	b.SetBytes(int64(size * num))
   572  	b.StartTimer()
   573  
   574  	var state []byte
   575  	for i := 0; i < b.N; i++ {
   576  		for j := 0; j < num; j++ {
   577  			h.Write(data)
   578  		}
   579  		state = h.Sum(state[:0])
   580  	}
   581  	b.StopTimer()
   582  	h.Reset()
   583  }
   584  
   585  // benchmarkShake is specialized to the Shake instances, which don't
   586  // require a copy on reading output.
   587  func benchmarkShake(b *testing.B, h *SHAKE, size, num int) {
   588  	b.StopTimer()
   589  	h.Reset()
   590  	data := sequentialBytes(size)
   591  	d := make([]byte, 32)
   592  
   593  	b.SetBytes(int64(size * num))
   594  	b.StartTimer()
   595  
   596  	for i := 0; i < b.N; i++ {
   597  		h.Reset()
   598  		for j := 0; j < num; j++ {
   599  			h.Write(data)
   600  		}
   601  		h.Read(d)
   602  	}
   603  }
   604  
   605  func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
   606  func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
   607  func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
   608  func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
   609  
   610  func BenchmarkShake128_MTU(b *testing.B)  { benchmarkShake(b, NewShake128(), 1350, 1) }
   611  func BenchmarkShake256_MTU(b *testing.B)  { benchmarkShake(b, NewShake256(), 1350, 1) }
   612  func BenchmarkShake256_16x(b *testing.B)  { benchmarkShake(b, NewShake256(), 16, 1024) }
   613  func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
   614  
   615  func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
   616  
   617  func Example_sum() {
   618  	buf := []byte("some data to hash")
   619  	// A hash needs to be 64 bytes long to have 256-bit collision resistance.
   620  	h := make([]byte, 64)
   621  	// Compute a 64-byte hash of buf and put it in h.
   622  	ShakeSum256(h, buf)
   623  	fmt.Printf("%x\n", h)
   624  	// Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
   625  }
   626  
   627  func Example_mac() {
   628  	k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
   629  	buf := []byte("and this is some data to authenticate")
   630  	// A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
   631  	h := make([]byte, 32)
   632  	d := NewShake256()
   633  	// Write the key into the hash.
   634  	d.Write(k)
   635  	// Now write the data.
   636  	d.Write(buf)
   637  	// Read 32 bytes of output from the hash into h.
   638  	d.Read(h)
   639  	fmt.Printf("%x\n", h)
   640  	// Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
   641  }
   642  
   643  func ExampleNewCShake256() {
   644  	out := make([]byte, 32)
   645  	msg := []byte("The quick brown fox jumps over the lazy dog")
   646  
   647  	// Example 1: Simple cshake
   648  	c1 := NewCShake256([]byte("NAME"), []byte("Partition1"))
   649  	c1.Write(msg)
   650  	c1.Read(out)
   651  	fmt.Println(hex.EncodeToString(out))
   652  
   653  	// Example 2: Different customization string produces different digest
   654  	c1 = NewCShake256([]byte("NAME"), []byte("Partition2"))
   655  	c1.Write(msg)
   656  	c1.Read(out)
   657  	fmt.Println(hex.EncodeToString(out))
   658  
   659  	// Example 3: Longer output length produces longer digest
   660  	out = make([]byte, 64)
   661  	c1 = NewCShake256([]byte("NAME"), []byte("Partition1"))
   662  	c1.Write(msg)
   663  	c1.Read(out)
   664  	fmt.Println(hex.EncodeToString(out))
   665  
   666  	// Example 4: Next read produces different result
   667  	c1.Read(out)
   668  	fmt.Println(hex.EncodeToString(out))
   669  
   670  	// Output:
   671  	//a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b
   672  	//a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0
   673  	//a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8
   674  	//85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109
   675  }
   676  

View as plain text