...

Source file src/golang.org/x/crypto/sha3/sha3_test.go

Documentation: golang.org/x/crypto/sha3

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

View as plain text