--- /dev/null
+// Copyright 2024 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 sha3 implements the SHA-3 hash algorithms and the SHAKE extendable
+// output functions defined in FIPS 202.
+package sha3
+
+import (
+ "crypto"
+ "crypto/internal/fips140/sha3"
+ "hash"
+)
+
+func init() {
+ crypto.RegisterHash(crypto.SHA3_224, func() hash.Hash { return New224() })
+ crypto.RegisterHash(crypto.SHA3_256, func() hash.Hash { return New256() })
+ crypto.RegisterHash(crypto.SHA3_384, func() hash.Hash { return New384() })
+ crypto.RegisterHash(crypto.SHA3_512, func() hash.Hash { return New512() })
+}
+
+// Sum224 returns the SHA3-224 hash of data.
+func Sum224(data []byte) [28]byte {
+ var out [28]byte
+ h := sha3.New224()
+ h.Write(data)
+ h.Sum(out[:0])
+ return out
+}
+
+// Sum256 returns the SHA3-256 hash of data.
+func Sum256(data []byte) [32]byte {
+ var out [32]byte
+ h := sha3.New256()
+ h.Write(data)
+ h.Sum(out[:0])
+ return out
+}
+
+// Sum384 returns the SHA3-384 hash of data.
+func Sum384(data []byte) [48]byte {
+ var out [48]byte
+ h := sha3.New384()
+ h.Write(data)
+ h.Sum(out[:0])
+ return out
+}
+
+// Sum512 returns the SHA3-512 hash of data.
+func Sum512(data []byte) [64]byte {
+ var out [64]byte
+ h := sha3.New512()
+ h.Write(data)
+ h.Sum(out[:0])
+ return out
+}
+
+// SumSHAKE128 applies the SHAKE128 extendable output function to data and
+// returns an output of the given length in bytes.
+func SumSHAKE128(data []byte, length int) []byte {
+ // Outline the allocation for up to 256 bits of output to the caller's stack.
+ out := make([]byte, 32)
+ return sumSHAKE128(out, data, length)
+}
+
+func sumSHAKE128(out, data []byte, length int) []byte {
+ if len(out) < length {
+ out = make([]byte, length)
+ } else {
+ out = out[:length]
+ }
+ h := sha3.NewShake128()
+ h.Write(data)
+ h.Read(out)
+ return out
+}
+
+// SumSHAKE256 applies the SHAKE256 extendable output function to data and
+// returns an output of the given length in bytes.
+func SumSHAKE256(data []byte, length int) []byte {
+ // Outline the allocation for up to 512 bits of output to the caller's stack.
+ out := make([]byte, 64)
+ return sumSHAKE256(out, data, length)
+}
+
+func sumSHAKE256(out, data []byte, length int) []byte {
+ if len(out) < length {
+ out = make([]byte, length)
+ } else {
+ out = out[:length]
+ }
+ h := sha3.NewShake256()
+ h.Write(data)
+ h.Read(out)
+ return out
+}
+
+// SHA3 is an instance of a SHA-3 hash. It implements [hash.Hash].
+type SHA3 struct {
+ s sha3.Digest
+}
+
+// New224 creates a new SHA3-224 hash.
+func New224() *SHA3 {
+ return &SHA3{*sha3.New224()}
+}
+
+// New256 creates a new SHA3-256 hash.
+func New256() *SHA3 {
+ return &SHA3{*sha3.New256()}
+}
+
+// New384 creates a new SHA3-384 hash.
+func New384() *SHA3 {
+ return &SHA3{*sha3.New384()}
+}
+
+// New512 creates a new SHA3-512 hash.
+func New512() *SHA3 {
+ return &SHA3{*sha3.New512()}
+}
+
+// Write absorbs more data into the hash's state.
+func (s *SHA3) Write(p []byte) (n int, err error) {
+ return s.s.Write(p)
+}
+
+// Sum appends the current hash to b and returns the resulting slice.
+func (s *SHA3) Sum(b []byte) []byte {
+ return s.s.Sum(b)
+}
+
+// Reset resets the hash to its initial state.
+func (s *SHA3) Reset() {
+ s.s.Reset()
+}
+
+// Size returns the number of bytes Sum will produce.
+func (s *SHA3) Size() int {
+ return s.s.Size()
+}
+
+// BlockSize returns the hash's rate.
+func (s *SHA3) BlockSize() int {
+ return s.s.BlockSize()
+}
+
+// MarshalBinary implements [encoding.BinaryMarshaler].
+func (s *SHA3) MarshalBinary() ([]byte, error) {
+ return s.s.MarshalBinary()
+}
+
+// AppendBinary implements [encoding.BinaryAppender].
+func (s *SHA3) AppendBinary(p []byte) ([]byte, error) {
+ return s.s.AppendBinary(p)
+}
+
+// UnmarshalBinary implements [encoding.BinaryUnmarshaler].
+func (s *SHA3) UnmarshalBinary(data []byte) error {
+ return s.s.UnmarshalBinary(data)
+}
+
+// SHAKE is an instance of a SHAKE extendable output function.
+type SHAKE struct {
+ s sha3.SHAKE
+}
+
+// NewSHAKE128 creates a new SHAKE128 XOF.
+func NewSHAKE128() *SHAKE {
+ return &SHAKE{*sha3.NewShake128()}
+}
+
+// NewSHAKE256 creates a new SHAKE256 XOF.
+func NewSHAKE256() *SHAKE {
+ return &SHAKE{*sha3.NewShake256()}
+}
+
+// NewCSHAKE128 creates a new cSHAKE128 XOF.
+//
+// N is used to define functions based on cSHAKE, it can be empty when plain
+// cSHAKE is desired. S is a customization byte string used for domain
+// separation. When N and S are both empty, this is equivalent to NewSHAKE128.
+func NewCSHAKE128(N, S []byte) *SHAKE {
+ return &SHAKE{*sha3.NewCShake128(N, S)}
+}
+
+// NewCSHAKE256 creates a new cSHAKE256 XOF.
+//
+// N is used to define functions based on cSHAKE, it can be empty when plain
+// cSHAKE is desired. S is a customization byte string used for domain
+// separation. When N and S are both empty, this is equivalent to NewSHAKE256.
+func NewCSHAKE256(N, S []byte) *SHAKE {
+ return &SHAKE{*sha3.NewCShake256(N, S)}
+}
+
+// Write absorbs more data into the XOF's state.
+//
+// It panics if any output has already been read.
+func (s *SHAKE) Write(p []byte) (n int, err error) {
+ return s.s.Write(p)
+}
+
+// Read squeezes more output from the XOF.
+//
+// Any call to Write after a call to Read will panic.
+func (s *SHAKE) Read(p []byte) (n int, err error) {
+ return s.s.Read(p)
+}
+
+// Reset resets the XOF to its initial state.
+func (s *SHAKE) Reset() {
+ s.s.Reset()
+}
+
+// BlockSize returns the rate of the XOF.
+func (s *SHAKE) BlockSize() int {
+ return s.s.BlockSize()
+}
+
+// MarshalBinary implements [encoding.BinaryMarshaler].
+func (s *SHAKE) MarshalBinary() ([]byte, error) {
+ return s.s.MarshalBinary()
+}
+
+// AppendBinary implements [encoding.BinaryAppender].
+func (s *SHAKE) AppendBinary(p []byte) ([]byte, error) {
+ return s.s.AppendBinary(p)
+}
+
+// UnmarshalBinary implements [encoding.BinaryUnmarshaler].
+func (s *SHAKE) UnmarshalBinary(data []byte) error {
+ return s.s.UnmarshalBinary(data)
+}
// 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.
+package sha3_test
import (
"bytes"
"crypto/internal/cryptotest"
"crypto/internal/fips140"
- . "crypto/internal/fips140/sha3"
- "encoding"
+ . "crypto/sha3"
"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,
+var testDigests = map[string]func() *SHA3{
+ "SHA3-224": New224,
+ "SHA3-256": New256,
+ "SHA3-384": New384,
+ "SHA3-512": New512,
}
// testShakes contains functions that return *sha3.SHAKE instances for
defAlgoName string
defCustomStr string
}{
- // NewCShake without customization produces same result as SHAKE
- "SHAKE128": {NewCShake128, "", ""},
- "SHAKE256": {NewCShake256, "", ""},
- "cSHAKE128": {NewCShake128, "CSHAKE128", "CustomString"},
- "cSHAKE256": {NewCShake256, "CSHAKE256", "CustomString"},
+ // 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.
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) {
}
}
-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) {
t.Errorf("expected zero allocations, got %0.1f", allocs)
}
})
- t.Run("NewShake", func(t *testing.T) {
+ t.Run("NewSHAKE", func(t *testing.T) {
if allocs := testing.AllocsPerRun(10, func() {
- h := NewShake128()
+ h := NewSHAKE128()
b := []byte("ABC")
h.Write(b)
- out := make([]byte, 0, 32)
- out = h.Sum(out)
- sinkSHA3 ^= out[0]
+ out := make([]byte, 32)
h.Read(out)
sinkSHA3 ^= out[0]
}); allocs > 0 {
t.Errorf("expected zero allocations, got %0.1f", allocs)
}
})
+ t.Run("SumSHAKE", func(t *testing.T) {
+ if allocs := testing.AllocsPerRun(10, func() {
+ b := []byte("ABC")
+ out := SumSHAKE128(b, 10)
+ sinkSHA3 ^= out[0]
+ }); allocs > 0 {
+ t.Errorf("expected zero allocations, got %0.1f", allocs)
+ }
+ })
}
func TestCSHAKEAccumulated(t *testing.T) {
//
cryptotest.TestAllImplementations(t, "sha3", func(t *testing.T) {
t.Run("cSHAKE128", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake128, (1600-256)/8,
+ testCSHAKEAccumulated(t, NewCSHAKE128, (1600-256)/8,
"bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
})
t.Run("cSHAKE256", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake256, (1600-512)/8,
+ 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)
+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)
S := make([]byte, s)
rnd.Read(S)
- c := newCShake(N, S)
+ c := newCSHAKE(N, S)
io.CopyN(c, rnd, 100 /* < rate */)
io.CopyN(acc, c, 200)
io.CopyN(acc, c, 200)
}
}
- if got := hex.EncodeToString(acc.Sum(nil)[:32]); got != exp {
+ out := make([]byte, 32)
+ acc.Read(out)
+ if got := hex.EncodeToString(out); got != exp {
t.Errorf("got %s, want %s", got, exp)
}
}
// See https://go.dev/issue/66232.
const s = (1<<32)/8 + 1000 // s * 8 > 2^32
S := make([]byte, s)
- rnd := NewShake128()
+ rnd := NewSHAKE128()
rnd.Read(S)
- c := NewCShake128(nil, S)
+ c := NewCSHAKE128(nil, S)
io.CopyN(c, rnd, 1000)
+ out := make([]byte, 32)
+ c.Read(out)
// Generated with pycryptodome@3.20.0
//
// print(c.read(32).hex())
//
exp := "2cb9f237767e98f2614b8779cf096a52da9b3a849280bbddec820771ae529cf0"
- if got := hex.EncodeToString(c.Sum(nil)); got != exp {
+ if got := hex.EncodeToString(out); got != exp {
t.Errorf("got %s, want %s", got, exp)
}
}
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()) })
+ t.Run("SHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE128()) })
+ t.Run("SHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewSHAKE256()) })
+ t.Run("cSHAKE128", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE128([]byte("N"), []byte("S"))) })
+ t.Run("cSHAKE256", func(t *testing.T) { testMarshalUnmarshalSHAKE(t, NewCSHAKE256([]byte("N"), []byte("S"))) })
})
}
// TODO(filippo): move this to crypto/internal/cryptotest.
-func testMarshalUnmarshal(t *testing.T, h fips140.Hash) {
+func testMarshalUnmarshal(t *testing.T, h *SHA3) {
buf := make([]byte, 200)
rand.Read(buf)
n := rand.Intn(200)
want := h.Sum(nil)
h.Reset()
h.Write(buf[:n])
- b, err := h.(encoding.BinaryMarshaler).MarshalBinary()
+ b, err := h.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 {
+ if err := h.UnmarshalBinary(b); err != nil {
t.Errorf("UnmarshalBinary: %v", err)
}
h.Write(buf[n:])
}
}
+// TODO(filippo): move this to crypto/internal/cryptotest.
+func testMarshalUnmarshalSHAKE(t *testing.T, h *SHAKE) {
+ buf := make([]byte, 200)
+ rand.Read(buf)
+ n := rand.Intn(200)
+ h.Write(buf)
+ want := make([]byte, 32)
+ h.Read(want)
+ h.Reset()
+ h.Write(buf[:n])
+ b, err := h.MarshalBinary()
+ if err != nil {
+ t.Errorf("MarshalBinary: %v", err)
+ }
+ h.Write(bytes.Repeat([]byte{0}, 200))
+ if err := h.UnmarshalBinary(b); err != nil {
+ t.Errorf("UnmarshalBinary: %v", err)
+ }
+ h.Write(buf[n:])
+ got := make([]byte, 32)
+ h.Read(got)
+ 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()
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 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
-}