aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/internal
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2024-11-18 16:58:49 +0100
committerGopher Robot <gobot@golang.org>2024-11-22 01:58:53 +0000
commit8b97607280810d8effcfda56e47aa3ff73dced67 (patch)
treef47f33b4d63cf2ab83d97ddff238a548bfb588ac /src/crypto/internal
parent8cecfad2a99987a35edfbcd875bef5e894abbce7 (diff)
downloadgo-8b97607280810d8effcfda56e47aa3ff73dced67.tar.xz
crypto/sha3: new package
Implement the SHA-3 hash algorithms and the SHAKE extendable output functions defined in FIPS 202. This is a wrapper for crypto/internal/fips/sha3 which in turn was ported from x/crypto/sha3 in CL 616717 as part of #65269. Fixes #69982 Change-Id: I64ce7f362c1a773f7f5b05f7e0acb4110e52a329 Reviewed-on: https://go-review.googlesource.com/c/go/+/629176 Reviewed-by: Russ Cox <rsc@golang.org> Auto-Submit: Filippo Valsorda <filippo@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/crypto/internal')
-rw-r--r--src/crypto/internal/fips140test/sha3_test.go674
1 files changed, 0 insertions, 674 deletions
diff --git a/src/crypto/internal/fips140test/sha3_test.go b/src/crypto/internal/fips140test/sha3_test.go
deleted file mode 100644
index 2bc2a6df23..0000000000
--- a/src/crypto/internal/fips140test/sha3_test.go
+++ /dev/null
@@ -1,674 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package fipstest_test
-
-// TODO(fips, #69982): move to the crypto/sha3 package once it exists.
-
-import (
- "bytes"
- "crypto/internal/cryptotest"
- "crypto/internal/fips140"
- . "crypto/internal/fips140/sha3"
- "encoding"
- "encoding/hex"
- "fmt"
- "io"
- "math/rand"
- "strings"
- "testing"
-)
-
-// Sum224 returns the SHA3-224 digest of the data.
-func Sum224(data []byte) (digest [28]byte) {
- h := New224()
- h.Write(data)
- h.Sum(digest[:0])
- return
-}
-
-// Sum256 returns the SHA3-256 digest of the data.
-func Sum256(data []byte) (digest [32]byte) {
- h := New256()
- h.Write(data)
- h.Sum(digest[:0])
- return
-}
-
-// Sum384 returns the SHA3-384 digest of the data.
-func Sum384(data []byte) (digest [48]byte) {
- h := New384()
- h.Write(data)
- h.Sum(digest[:0])
- return
-}
-
-// Sum512 returns the SHA3-512 digest of the data.
-func Sum512(data []byte) (digest [64]byte) {
- h := New512()
- h.Write(data)
- h.Sum(digest[:0])
- return
-}
-
-// ShakeSum128 writes an arbitrary-length digest of data into hash.
-func ShakeSum128(hash, data []byte) {
- h := NewShake128()
- h.Write(data)
- h.Read(hash)
-}
-
-// ShakeSum256 writes an arbitrary-length digest of data into hash.
-func ShakeSum256(hash, data []byte) {
- h := NewShake256()
- h.Write(data)
- h.Read(hash)
-}
-
-const testString = "brekeccakkeccak koax koax"
-
-// testDigests contains functions returning hash.Hash instances
-// with output-length equal to the KAT length for SHA-3, Keccak
-// and SHAKE instances.
-var testDigests = map[string]func() *Digest{
- "SHA3-224": New224,
- "SHA3-256": New256,
- "SHA3-384": New384,
- "SHA3-512": New512,
- "Keccak-256": NewLegacyKeccak256,
- "Keccak-512": NewLegacyKeccak512,
-}
-
-// testShakes contains functions that return *sha3.SHAKE instances for
-// with output-length equal to the KAT length.
-var testShakes = map[string]struct {
- constructor func(N []byte, S []byte) *SHAKE
- defAlgoName string
- defCustomStr string
-}{
- // NewCShake without customization produces same result as SHAKE
- "SHAKE128": {NewCShake128, "", ""},
- "SHAKE256": {NewCShake256, "", ""},
- "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomString"},
- "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomString"},
-}
-
-// decodeHex converts a hex-encoded string into a raw byte string.
-func decodeHex(s string) []byte {
- b, err := hex.DecodeString(s)
- if err != nil {
- panic(err)
- }
- return b
-}
-
-// TestKeccak does a basic test of the non-standardized Keccak hash functions.
-func TestKeccak(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testKeccak)
-}
-
-func testKeccak(t *testing.T) {
- tests := []struct {
- fn func() *Digest
- data []byte
- want string
- }{
- {
- NewLegacyKeccak256,
- []byte("abc"),
- "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
- },
- {
- NewLegacyKeccak512,
- []byte("abc"),
- "18587dc2ea106b9a1563e32b3312421ca164c7f1f07bc922a9c83d77cea3a1e5d0c69910739025372dc14ac9642629379540c17e2a65b19d77aa511a9d00bb96",
- },
- }
-
- for _, u := range tests {
- h := u.fn()
- h.Write(u.data)
- got := h.Sum(nil)
- want := decodeHex(u.want)
- if !bytes.Equal(got, want) {
- t.Errorf("unexpected hash for size %d: got '%x' want '%s'", h.Size()*8, got, u.want)
- }
- }
-}
-
-// TestShakeSum tests that the output of Sum matches the output of Read.
-func TestShakeSum(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testShakeSum)
-}
-
-func testShakeSum(t *testing.T) {
- tests := [...]struct {
- name string
- hash *SHAKE
- expectedLen int
- }{
- {"SHAKE128", NewShake128(), 32},
- {"SHAKE256", NewShake256(), 64},
- {"cSHAKE128", NewCShake128([]byte{'X'}, nil), 32},
- {"cSHAKE256", NewCShake256([]byte{'X'}, nil), 64},
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- s := test.hash.Sum(nil)
- if len(s) != test.expectedLen {
- t.Errorf("Unexpected digest length: got %d, want %d", len(s), test.expectedLen)
- }
- r := make([]byte, test.expectedLen)
- test.hash.Read(r)
- if !bytes.Equal(s, r) {
- t.Errorf("Mismatch between Sum and Read:\nSum: %s\nRead: %s", hex.EncodeToString(s), hex.EncodeToString(r))
- }
- })
- }
-}
-
-// TestUnalignedWrite tests that writing data in an arbitrary pattern with
-// small input buffers.
-func TestUnalignedWrite(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testUnalignedWrite)
-}
-
-func testUnalignedWrite(t *testing.T) {
- buf := sequentialBytes(0x10000)
- for alg, df := range testDigests {
- d := df()
- d.Reset()
- d.Write(buf)
- want := d.Sum(nil)
- d.Reset()
- for i := 0; i < len(buf); {
- // Cycle through offsets which make a 137 byte sequence.
- // Because 137 is prime this sequence should exercise all corner cases.
- offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
- for _, j := range offsets {
- if v := len(buf) - i; v < j {
- j = v
- }
- d.Write(buf[i : i+j])
- i += j
- }
- }
- got := d.Sum(nil)
- if !bytes.Equal(got, want) {
- t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
- }
- }
-
- // Same for SHAKE
- for alg, df := range testShakes {
- want := make([]byte, 16)
- got := make([]byte, 16)
- d := df.constructor([]byte(df.defAlgoName), []byte(df.defCustomStr))
-
- d.Reset()
- d.Write(buf)
- d.Read(want)
- d.Reset()
- for i := 0; i < len(buf); {
- // Cycle through offsets which make a 137 byte sequence.
- // Because 137 is prime this sequence should exercise all corner cases.
- offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1}
- for _, j := range offsets {
- if v := len(buf) - i; v < j {
- j = v
- }
- d.Write(buf[i : i+j])
- i += j
- }
- }
- d.Read(got)
- if !bytes.Equal(got, want) {
- t.Errorf("Unaligned writes, alg=%s\ngot %q, want %q", alg, got, want)
- }
- }
-}
-
-// TestAppend checks that appending works when reallocation is necessary.
-func TestAppend(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testAppend)
-}
-
-func testAppend(t *testing.T) {
- d := New224()
-
- for capacity := 2; capacity <= 66; capacity += 64 {
- // The first time around the loop, Sum will have to reallocate.
- // The second time, it will not.
- buf := make([]byte, 2, capacity)
- d.Reset()
- d.Write([]byte{0xcc})
- buf = d.Sum(buf)
- expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
- if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
- t.Errorf("got %s, want %s", got, expected)
- }
- }
-}
-
-// TestAppendNoRealloc tests that appending works when no reallocation is necessary.
-func TestAppendNoRealloc(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testAppendNoRealloc)
-}
-
-func testAppendNoRealloc(t *testing.T) {
- buf := make([]byte, 1, 200)
- d := New224()
- d.Write([]byte{0xcc})
- buf = d.Sum(buf)
- expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39"
- if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected {
- t.Errorf("got %s, want %s", got, expected)
- }
-}
-
-// TestSqueezing checks that squeezing the full output a single time produces
-// the same output as repeatedly squeezing the instance.
-func TestSqueezing(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testSqueezing)
-}
-
-func testSqueezing(t *testing.T) {
- for algo, v := range testShakes {
- d0 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
- d0.Write([]byte(testString))
- ref := make([]byte, 32)
- d0.Read(ref)
-
- d1 := v.constructor([]byte(v.defAlgoName), []byte(v.defCustomStr))
- d1.Write([]byte(testString))
- var multiple []byte
- for range ref {
- d1.Read(make([]byte, 0))
- one := make([]byte, 1)
- d1.Read(one)
- multiple = append(multiple, one...)
- }
- if !bytes.Equal(ref, multiple) {
- t.Errorf("%s: squeezing %d bytes one at a time failed", algo, len(ref))
- }
- }
-}
-
-// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing.
-//
-// The alignment of each slice is intentionally randomized to detect alignment
-// issues in the implementation. See https://golang.org/issue/37644.
-// Ideally, the compiler should fuzz the alignment itself.
-// (See https://golang.org/issue/35128.)
-func sequentialBytes(size int) []byte {
- alignmentOffset := rand.Intn(8)
- result := make([]byte, size+alignmentOffset)[alignmentOffset:]
- for i := range result {
- result[i] = byte(i)
- }
- return result
-}
-
-func TestReset(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testReset)
-}
-
-func testReset(t *testing.T) {
- out1 := make([]byte, 32)
- out2 := make([]byte, 32)
-
- for _, v := range testShakes {
- // Calculate hash for the first time
- c := v.constructor(nil, []byte{0x99, 0x98})
- c.Write(sequentialBytes(0x100))
- c.Read(out1)
-
- // Calculate hash again
- c.Reset()
- c.Write(sequentialBytes(0x100))
- c.Read(out2)
-
- if !bytes.Equal(out1, out2) {
- t.Error("\nExpected:\n", out1, "\ngot:\n", out2)
- }
- }
-}
-
-func TestClone(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testClone)
-}
-
-func testClone(t *testing.T) {
- out1 := make([]byte, 16)
- out2 := make([]byte, 16)
-
- // Test for sizes smaller and larger than block size.
- for _, size := range []int{0x1, 0x100} {
- in := sequentialBytes(size)
- for _, v := range testShakes {
- h1 := v.constructor(nil, []byte{0x01})
- h1.Write([]byte{0x01})
-
- h2 := h1.Clone()
-
- h1.Write(in)
- h1.Read(out1)
-
- h2.Write(in)
- h2.Read(out2)
-
- if !bytes.Equal(out1, out2) {
- t.Error("\nExpected:\n", hex.EncodeToString(out1), "\ngot:\n", hex.EncodeToString(out2))
- }
- }
- }
-}
-
-var sinkSHA3 byte
-
-func TestAllocations(t *testing.T) {
- cryptotest.SkipTestAllocations(t)
- t.Run("New", func(t *testing.T) {
- if allocs := testing.AllocsPerRun(10, func() {
- h := New256()
- b := []byte("ABC")
- h.Write(b)
- out := make([]byte, 0, 32)
- out = h.Sum(out)
- sinkSHA3 ^= out[0]
- }); allocs > 0 {
- t.Errorf("expected zero allocations, got %0.1f", allocs)
- }
- })
- t.Run("NewShake", func(t *testing.T) {
- if allocs := testing.AllocsPerRun(10, func() {
- h := NewShake128()
- b := []byte("ABC")
- h.Write(b)
- out := make([]byte, 0, 32)
- out = h.Sum(out)
- sinkSHA3 ^= out[0]
- h.Read(out)
- sinkSHA3 ^= out[0]
- }); allocs > 0 {
- t.Errorf("expected zero allocations, got %0.1f", allocs)
- }
- })
- t.Run("Sum", func(t *testing.T) {
- if allocs := testing.AllocsPerRun(10, func() {
- b := []byte("ABC")
- out := Sum256(b)
- sinkSHA3 ^= out[0]
- }); allocs > 0 {
- t.Errorf("expected zero allocations, got %0.1f", allocs)
- }
- })
-}
-
-func TestCSHAKEAccumulated(t *testing.T) {
- // Generated with pycryptodome@3.20.0
- //
- // from Crypto.Hash import cSHAKE128
- // rng = cSHAKE128.new()
- // acc = cSHAKE128.new()
- // for n in range(200):
- // N = rng.read(n)
- // for s in range(200):
- // S = rng.read(s)
- // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
- // c.update(rng.read(100))
- // acc.update(c.read(200))
- // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
- // c.update(rng.read(168))
- // acc.update(c.read(200))
- // c = cSHAKE128.cSHAKE_XOF(data=None, custom=S, capacity=256, function=N)
- // c.update(rng.read(200))
- // acc.update(c.read(200))
- // print(acc.read(32).hex())
- //
- // and with @noble/hashes@v1.5.0
- //
- // import { bytesToHex } from "@noble/hashes/utils";
- // import { cshake128 } from "@noble/hashes/sha3-addons";
- // const rng = cshake128.create();
- // const acc = cshake128.create();
- // for (let n = 0; n < 200; n++) {
- // const N = rng.xof(n);
- // for (let s = 0; s < 200; s++) {
- // const S = rng.xof(s);
- // let c = cshake128.create({ NISTfn: N, personalization: S });
- // c.update(rng.xof(100));
- // acc.update(c.xof(200));
- // c = cshake128.create({ NISTfn: N, personalization: S });
- // c.update(rng.xof(168));
- // acc.update(c.xof(200));
- // c = cshake128.create({ NISTfn: N, personalization: S });
- // c.update(rng.xof(200));
- // acc.update(c.xof(200));
- // }
- // }
- // console.log(bytesToHex(acc.xof(32)));
- //
- cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) {
- t.Run("cSHAKE128", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake128, (1600-256)/8,
- "bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
- })
- t.Run("cSHAKE256", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake256, (1600-512)/8,
- "0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef")
- })
- })
-}
-
-func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) *SHAKE, rate int64, exp string) {
- rnd := newCShake(nil, nil)
- acc := newCShake(nil, nil)
- for n := 0; n < 200; n++ {
- N := make([]byte, n)
- rnd.Read(N)
- for s := 0; s < 200; s++ {
- S := make([]byte, s)
- rnd.Read(S)
-
- c := newCShake(N, S)
- io.CopyN(c, rnd, 100 /* < rate */)
- io.CopyN(acc, c, 200)
-
- c.Reset()
- io.CopyN(c, rnd, rate)
- io.CopyN(acc, c, 200)
-
- c.Reset()
- io.CopyN(c, rnd, 200 /* > rate */)
- io.CopyN(acc, c, 200)
- }
- }
- if got := hex.EncodeToString(acc.Sum(nil)[:32]); got != exp {
- t.Errorf("got %s, want %s", got, exp)
- }
-}
-
-func TestCSHAKELargeS(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", testCSHAKELargeS)
-}
-
-func testCSHAKELargeS(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping test in short mode.")
- }
-
- // See https://go.dev/issue/66232.
- const s = (1<<32)/8 + 1000 // s * 8 > 2^32
- S := make([]byte, s)
- rnd := NewShake128()
- rnd.Read(S)
- c := NewCShake128(nil, S)
- io.CopyN(c, rnd, 1000)
-
- // Generated with pycryptodome@3.20.0
- //
- // from Crypto.Hash import cSHAKE128
- // rng = cSHAKE128.new()
- // S = rng.read(536871912)
- // c = cSHAKE128.new(custom=S)
- // c.update(rng.read(1000))
- // print(c.read(32).hex())
- //
- exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0"
- if got := hex.EncodeToString(c.Sum(nil)); got != exp {
- t.Errorf("got %s, want %s", got, exp)
- }
-}
-
-func TestMarshalUnmarshal(t *testing.T) {
- cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) {
- t.Run("SHA3-224", func(t *testing.T) { testMarshalUnmarshal(t, New224()) })
- t.Run("SHA3-256", func(t *testing.T) { testMarshalUnmarshal(t, New256()) })
- t.Run("SHA3-384", func(t *testing.T) { testMarshalUnmarshal(t, New384()) })
- t.Run("SHA3-512", func(t *testing.T) { testMarshalUnmarshal(t, New512()) })
- t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewShake128()) })
- t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewShake256()) })
- t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake128([]byte("N"), []byte("S"))) })
- t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshal(t, NewCShake256([]byte("N"), []byte("S"))) })
- t.Run("Keccak-256", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak256()) })
- t.Run("Keccak-512", func(t *testing.T) { testMarshalUnmarshal(t, NewLegacyKeccak512()) })
- })
-}
-
-// TODO(filippo): move this to crypto/internal/cryptotest.
-func testMarshalUnmarshal(t *testing.T, h fips140.Hash) {
- buf := make([]byte, 200)
- rand.Read(buf)
- n := rand.Intn(200)
- h.Write(buf)
- want := h.Sum(nil)
- h.Reset()
- h.Write(buf[:n])
- b, err := h.(encoding.BinaryMarshaler).MarshalBinary()
- if err != nil {
- t.Errorf("MarshalBinary: %v", err)
- }
- h.Write(bytes.Repeat([]byte{0}, 200))
- if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary(b); err != nil {
- t.Errorf("UnmarshalBinary: %v", err)
- }
- h.Write(buf[n:])
- got := h.Sum(nil)
- if !bytes.Equal(got, want) {
- t.Errorf("got %x, want %x", got, want)
- }
-}
-
-// benchmarkHash tests the speed to hash num buffers of buflen each.
-func benchmarkHash(b *testing.B, h fips140.Hash, size, num int) {
- b.StopTimer()
- h.Reset()
- data := sequentialBytes(size)
- b.SetBytes(int64(size * num))
- b.StartTimer()
-
- var state []byte
- for i := 0; i < b.N; i++ {
- for j := 0; j < num; j++ {
- h.Write(data)
- }
- state = h.Sum(state[:0])
- }
- b.StopTimer()
- h.Reset()
-}
-
-// benchmarkShake is specialized to the Shake instances, which don't
-// require a copy on reading output.
-func benchmarkShake(b *testing.B, h *SHAKE, size, num int) {
- b.StopTimer()
- h.Reset()
- data := sequentialBytes(size)
- d := make([]byte, 32)
-
- b.SetBytes(int64(size * num))
- b.StartTimer()
-
- for i := 0; i < b.N; i++ {
- h.Reset()
- for j := 0; j < num; j++ {
- h.Write(data)
- }
- h.Read(d)
- }
-}
-
-func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) }
-func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) }
-func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) }
-func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) }
-
-func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) }
-func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
-func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
-func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
-
-func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) }
-
-func Example_sum() {
- buf := []byte("some data to hash")
- // A hash needs to be 64 bytes long to have 256-bit collision resistance.
- h := make([]byte, 64)
- // Compute a 64-byte hash of buf and put it in h.
- ShakeSum256(h, buf)
- fmt.Printf("%x\n", h)
- // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d
-}
-
-func Example_mac() {
- k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
- buf := []byte("and this is some data to authenticate")
- // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key.
- h := make([]byte, 32)
- d := NewShake256()
- // Write the key into the hash.
- d.Write(k)
- // Now write the data.
- d.Write(buf)
- // Read 32 bytes of output from the hash into h.
- d.Read(h)
- fmt.Printf("%x\n", h)
- // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff
-}
-
-func ExampleNewCShake256() {
- out := make([]byte, 32)
- msg := []byte("The quick brown fox jumps over the lazy dog")
-
- // Example 1: Simple cshake
- c1 := NewCShake256([]byte("NAME"), []byte("Partition1"))
- c1.Write(msg)
- c1.Read(out)
- fmt.Println(hex.EncodeToString(out))
-
- // Example 2: Different customization string produces different digest
- c1 = NewCShake256([]byte("NAME"), []byte("Partition2"))
- c1.Write(msg)
- c1.Read(out)
- fmt.Println(hex.EncodeToString(out))
-
- // Example 3: Longer output length produces longer digest
- out = make([]byte, 64)
- c1 = NewCShake256([]byte("NAME"), []byte("Partition1"))
- c1.Write(msg)
- c1.Read(out)
- fmt.Println(hex.EncodeToString(out))
-
- // Example 4: Next read produces different result
- c1.Read(out)
- fmt.Println(hex.EncodeToString(out))
-
- // Output:
- //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b
- //a8db03e71f3e4da5c4eee9d28333cdd355f51cef3c567e59be5beb4ecdbb28f0
- //a90a4c6ca9af2156eba43dc8398279e6b60dcd56fb21837afe6c308fd4ceb05b9dd98c6ee866ca7dc5a39d53e960f400bcd5a19c8a2d6ec6459f63696543a0d8
- //85e73a72228d08b46515553ca3a29d47df3047e5d84b12d6c2c63e579f4fd1105716b7838e92e981863907f434bfd4443c9e56ea09da998d2f9b47db71988109
-}