mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
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:
parent
8cecfad2a9
commit
8b97607280
31
api/next/69982.txt
Normal file
31
api/next/69982.txt
Normal 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
|
6
doc/next/6-stdlib/5-sha3.md
Normal file
6
doc/next/6-stdlib/5-sha3.md
Normal 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`.
|
1
doc/next/6-stdlib/99-minor/crypto/sha3/69982.md
Normal file
1
doc/next/6-stdlib/99-minor/crypto/sha3/69982.md
Normal file
@ -0,0 +1 @@
|
||||
<!-- This is a new package; covered in 6-stdlib/5-sha3.md. -->
|
233
src/crypto/sha3/sha3.go
Normal file
233
src/crypto/sha3/sha3.go
Normal 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)
|
||||
}
|
@ -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
|
||||
}
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user