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>
This commit is contained in:
Filippo Valsorda 2024-11-18 16:58:49 +01:00 committed by Gopher Robot
parent 8cecfad2a9
commit 8b97607280
6 changed files with 349 additions and 253 deletions

31
api/next/69982.txt Normal file
View File

@ -0,0 +1,31 @@
pkg crypto/sha3, func New224() *SHA3 #69982
pkg crypto/sha3, func New256() *SHA3 #69982
pkg crypto/sha3, func New384() *SHA3 #69982
pkg crypto/sha3, func New512() *SHA3 #69982
pkg crypto/sha3, func NewCSHAKE128([]uint8, []uint8) *SHAKE #69982
pkg crypto/sha3, func NewCSHAKE256([]uint8, []uint8) *SHAKE #69982
pkg crypto/sha3, func NewSHAKE128() *SHAKE #69982
pkg crypto/sha3, func NewSHAKE256() *SHAKE #69982
pkg crypto/sha3, func Sum224([]uint8) [28]uint8 #69982
pkg crypto/sha3, func Sum256([]uint8) [32]uint8 #69982
pkg crypto/sha3, func Sum384([]uint8) [48]uint8 #69982
pkg crypto/sha3, func Sum512([]uint8) [64]uint8 #69982
pkg crypto/sha3, func SumSHAKE128([]uint8, int) []uint8 #69982
pkg crypto/sha3, func SumSHAKE256([]uint8, int) []uint8 #69982
pkg crypto/sha3, method (*SHA3) AppendBinary([]uint8) ([]uint8, error) #69982
pkg crypto/sha3, method (*SHA3) BlockSize() int #69982
pkg crypto/sha3, method (*SHA3) MarshalBinary() ([]uint8, error) #69982
pkg crypto/sha3, method (*SHA3) Reset() #69982
pkg crypto/sha3, method (*SHA3) Size() int #69982
pkg crypto/sha3, method (*SHA3) Sum([]uint8) []uint8 #69982
pkg crypto/sha3, method (*SHA3) UnmarshalBinary([]uint8) error #69982
pkg crypto/sha3, method (*SHA3) Write([]uint8) (int, error) #69982
pkg crypto/sha3, method (*SHAKE) AppendBinary([]uint8) ([]uint8, error) #69982
pkg crypto/sha3, method (*SHAKE) BlockSize() int #69982
pkg crypto/sha3, method (*SHAKE) MarshalBinary() ([]uint8, error) #69982
pkg crypto/sha3, method (*SHAKE) Read([]uint8) (int, error) #69982
pkg crypto/sha3, method (*SHAKE) Reset() #69982
pkg crypto/sha3, method (*SHAKE) UnmarshalBinary([]uint8) error #69982
pkg crypto/sha3, method (*SHAKE) Write([]uint8) (int, error) #69982
pkg crypto/sha3, type SHA3 struct #69982
pkg crypto/sha3, type SHAKE struct #69982

View File

@ -0,0 +1,6 @@
### New sha3 package
The new [crypto/sha3] package implements the SHA-3 hash function, and SHAKE and
cSHAKE extendable-output functions.
It was imported from `golang.org/x/crypto/sha3`.

View File

@ -0,0 +1 @@
<!-- This is a new package; covered in 6-stdlib/5-sha3.md. -->

233
src/crypto/sha3/sha3.go Normal file
View File

@ -0,0 +1,233 @@
// 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)
}

View File

@ -2,82 +2,30 @@
// 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
@ -87,11 +35,11 @@ var testShakes = map[string]struct {
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.
@ -103,72 +51,6 @@ func decodeHex(s string) []byte {
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) {
@ -336,36 +218,6 @@ func testReset(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) {
@ -382,14 +234,12 @@ 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 {
@ -405,6 +255,15 @@ func TestAllocations(t *testing.T) {
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) {
@ -453,19 +312,19 @@ 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)
@ -473,7 +332,7 @@ func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) *SHAKE, rat
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)
@ -486,7 +345,9 @@ func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) *SHAKE, rat
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)
}
}
@ -503,10 +364,12 @@ func testCSHAKELargeS(t *testing.T) {
// 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
//
@ -518,7 +381,7 @@ func testCSHAKELargeS(t *testing.T) {
// 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)
}
}
@ -529,17 +392,15 @@ func TestMarshalUnmarshal(t *testing.T) {
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)
@ -547,12 +408,12 @@ func testMarshalUnmarshal(t *testing.T, h fips140.Hash) {
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:])
@ -562,6 +423,32 @@ func testMarshalUnmarshal(t *testing.T, h fips140.Hash) {
}
}
// 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()
@ -606,69 +493,9 @@ 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 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
}

View File

@ -503,7 +503,8 @@ var depsRules = `
hash, embed
< crypto
< crypto/subtle
< crypto/cipher;
< crypto/cipher
< crypto/sha3;
crypto/cipher,
crypto/internal/boring/bcache
@ -519,9 +520,6 @@ var depsRules = `
crypto/hmac < crypto/pbkdf2;
# Unfortunately, stuck with reflect via encoding/binary.
encoding/binary, crypto/boring < golang.org/x/crypto/sha3;
crypto/aes,
crypto/des,
crypto/ecdh,
@ -531,7 +529,7 @@ var depsRules = `
crypto/sha1,
crypto/sha256,
crypto/sha512,
golang.org/x/crypto/sha3,
crypto/sha3,
crypto/hkdf
< CRYPTO;