import (
"crypto/internal/fips"
"crypto/internal/fips/sha256"
+ "crypto/internal/fips/sha3"
"crypto/internal/fips/sha512"
)
}
switch h.(type) {
- case *sha256.Digest, *sha512.Digest:
- // TODO(fips): SHA-3
+ case *sha256.Digest, *sha512.Digest, *sha3.Digest:
default:
return
}
+++ /dev/null
-// Copyright 2023 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.
-
-//go:build !noopt
-
-package sha3_test
-
-import (
- "crypto/internal/fips/sha3"
- "runtime"
- "testing"
-)
-
-var sink byte
-
-func TestAllocations(t *testing.T) {
- want := 0.0
-
- if runtime.GOARCH == "s390x" {
- // On s390x the returned hash.Hash is conditional so it escapes.
- want = 3.0
- }
-
- t.Run("New", func(t *testing.T) {
- if allocs := testing.AllocsPerRun(10, func() {
- h := sha3.New256()
- b := []byte("ABC")
- h.Write(b)
- out := make([]byte, 0, 32)
- out = h.Sum(out)
- sink ^= out[0]
- }); allocs > want {
- t.Errorf("expected zero allocations, got %0.1f", allocs)
- }
- })
- t.Run("NewShake", func(t *testing.T) {
- if allocs := testing.AllocsPerRun(10, func() {
- h := sha3.NewShake128()
- b := []byte("ABC")
- h.Write(b)
- out := make([]byte, 0, 32)
- out = h.Sum(out)
- sink ^= out[0]
- h.Read(out)
- sink ^= out[0]
- }); allocs > want {
- 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 := sha3.Sum256(b)
- sink ^= out[0]
- }); allocs > want {
- t.Errorf("expected zero allocations, got %0.1f", allocs)
- }
- })
-}
+++ /dev/null
-// 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 sha3 implements the SHA-3 fixed-output-length hash functions and
-// the SHAKE variable-output-length hash functions defined by FIPS-202.
-//
-// All types in this package also implement [encoding.BinaryMarshaler],
-// [encoding.BinaryAppender] and [encoding.BinaryUnmarshaler] to marshal and
-// unmarshal the internal state of the hash.
-//
-// Both types of hash function use the "sponge" construction and the Keccak
-// permutation. For a detailed specification see http://keccak.noekeon.org/
-//
-// # Guidance
-//
-// If you aren't sure what function you need, use SHAKE256 with at least 64
-// bytes of output. The SHAKE instances are faster than the SHA3 instances;
-// the latter have to allocate memory to conform to the hash.Hash interface.
-//
-// If you need a secret-key MAC (message authentication code), prepend the
-// secret key to the input, hash with SHAKE256 and read at least 32 bytes of
-// output.
-//
-// # Security strengths
-//
-// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security
-// strength against preimage attacks of x bits. Since they only produce "x"
-// bits of output, their collision-resistance is only "x/2" bits.
-//
-// The SHAKE-256 and -128 functions have a generic security strength of 256 and
-// 128 bits against all attacks, provided that at least 2x bits of their output
-// is used. Requesting more than 64 or 32 bytes of output, respectively, does
-// not increase the collision-resistance of the SHAKE functions.
-//
-// # The sponge construction
-//
-// A sponge builds a pseudo-random function from a public pseudo-random
-// permutation, by applying the permutation to a state of "rate + capacity"
-// bytes, but hiding "capacity" of the bytes.
-//
-// A sponge starts out with a zero state. To hash an input using a sponge, up
-// to "rate" bytes of the input are XORed into the sponge's state. The sponge
-// is then "full" and the permutation is applied to "empty" it. This process is
-// repeated until all the input has been "absorbed". The input is then padded.
-// The digest is "squeezed" from the sponge in the same way, except that output
-// is copied out instead of input being XORed in.
-//
-// A sponge is parameterized by its generic security strength, which is equal
-// to half its capacity; capacity + rate is equal to the permutation's width.
-// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means
-// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2.
-//
-// # Recommendations
-//
-// The SHAKE functions are recommended for most new uses. They can produce
-// output of arbitrary length. SHAKE256, with an output length of at least
-// 64 bytes, provides 256-bit security against all attacks. The Keccak team
-// recommends it for most applications upgrading from SHA2-512. (NIST chose a
-// much stronger, but much slower, sponge instance for SHA3-512.)
-//
-// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions.
-// They produce output of the same length, with the same security strengths
-// against all attacks. This means, in particular, that SHA3-256 only has
-// 128-bit collision resistance, because its output length is 32 bytes.
-package sha3
package sha3
-// This file provides functions for creating instances of the SHA-3
-// and SHAKE hash functions, as well as utility functions for hashing
-// bytes.
-
-import "crypto/internal/fips"
-
-// New224 creates a new SHA3-224 hash.
-// Its generic security strength is 224 bits against preimage attacks,
-// and 112 bits against collision attacks.
-func New224() fips.Hash {
+// New224 returns a new Digest computing the SHA3-224 hash.
+func New224() *Digest {
return new224()
}
-// New256 creates a new SHA3-256 hash.
-// Its generic security strength is 256 bits against preimage attacks,
-// and 128 bits against collision attacks.
-func New256() fips.Hash {
+// New256 returns a new Digest computing the SHA3-256 hash.
+func New256() *Digest {
return new256()
}
-// New384 creates a new SHA3-384 hash.
-// Its generic security strength is 384 bits against preimage attacks,
-// and 192 bits against collision attacks.
-func New384() fips.Hash {
+// New384 returns a new Digest computing the SHA3-384 hash.
+func New384() *Digest {
return new384()
}
-// New512 creates a new SHA3-512 hash.
-// Its generic security strength is 512 bits against preimage attacks,
-// and 256 bits against collision attacks.
-func New512() fips.Hash {
+// New512 returns a new Digest computing the SHA3-512 hash.
+func New512() *Digest {
return new512()
}
rateK1024 = (1600 - 1024) / 8
)
-func new224Generic() *state {
- return &state{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3}
-}
-
-func new256Generic() *state {
- return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3}
-}
-
-func new384Generic() *state {
- return &state{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3}
+func new224Generic() *Digest {
+ return &Digest{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3}
}
-func new512Generic() *state {
- return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3}
-}
-
-// NewLegacyKeccak256 creates a new Keccak-256 hash.
-//
-// Only use this function if you require compatibility with an existing cryptosystem
-// that uses non-standard padding. All other users should use New256 instead.
-func NewLegacyKeccak256() fips.Hash {
- return &state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}
-}
-
-// NewLegacyKeccak512 creates a new Keccak-512 hash.
-//
-// Only use this function if you require compatibility with an existing cryptosystem
-// that uses non-standard padding. All other users should use New512 instead.
-func NewLegacyKeccak512() fips.Hash {
- return &state{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak}
+func new256Generic() *Digest {
+ return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3}
}
-// 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
+func new384Generic() *Digest {
+ return &Digest{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3}
}
-// 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
+func new512Generic() *Digest {
+ return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3}
}
-// 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
+// NewLegacyKeccak256 returns a new Digest computing the legacy, non-standard
+// Keccak-256 hash.
+func NewLegacyKeccak256() *Digest {
+ return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}
}
-// 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
+// NewLegacyKeccak512 returns a new Digest computing the legacy, non-standard
+// Keccak-512 hash.
+func NewLegacyKeccak512() *Digest {
+ return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteKeccak}
}
+++ /dev/null
-// Copyright 2023 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.
-
-//go:build !gc || purego || !s390x
-
-package sha3
-
-func new224() *state {
- return new224Generic()
-}
-
-func new256() *state {
- return new256Generic()
-}
-
-func new384() *state {
- return new384Generic()
-}
-
-func new512() *state {
- return new512Generic()
-}
// 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 fixed-output-length hash functions and
+// the SHAKE variable-output-length functions defined by [FIPS 202], as well as
+// the cSHAKE extendable-output-length functions defined by [SP 800-185].
+//
+// [FIPS 202]: https://doi.org/10.6028/NIST.FIPS.202
+// [SP 800-185]: https://doi.org/10.6028/NIST.SP.800-185
package sha3
import (
spongeSqueezing
)
-type state struct {
+type Digest struct {
a [1600 / 8]byte // main state of the hash
// a[n:rate] is the buffer. If absorbing, it's the remaining space to XOR
}
// BlockSize returns the rate of sponge underlying this hash function.
-func (d *state) BlockSize() int { return d.rate }
+func (d *Digest) BlockSize() int { return d.rate }
// Size returns the output size of the hash function in bytes.
-func (d *state) Size() int { return d.outputLen }
+func (d *Digest) Size() int { return d.outputLen }
-// Reset clears the internal state by zeroing the sponge state and
-// the buffer indexes, and setting Sponge.state to absorbing.
-func (d *state) Reset() {
+// Reset resets the Digest to its initial state.
+func (d *Digest) Reset() {
// Zero the permutation's state.
for i := range d.a {
d.a[i] = 0
d.n = 0
}
-func (d *state) clone() *state {
+func (d *Digest) Clone() *Digest {
ret := *d
return &ret
}
// permute applies the KeccakF-1600 permutation.
-func (d *state) permute() {
+func (d *Digest) permute() {
var a *[25]uint64
if goarch.BigEndian {
a = new([25]uint64)
}
}
-// pads appends the domain separation bits in dsbyte, applies
+// padAndPermute appends the domain separation bits in dsbyte, applies
// the multi-bitrate 10..1 padding rule, and permutes the state.
-func (d *state) padAndPermute() {
+func (d *Digest) padAndPermute() {
// Pad with this instance's domain-separator bits. We know that there's
// at least one byte of space in the sponge because, if it were full,
// permute would have been called to empty it. dsbyte also contains the
d.state = spongeSqueezing
}
-// Write absorbs more data into the hash's state. It panics if any
-// output has already been read.
-func (d *state) Write(p []byte) (n int, err error) {
+// Write absorbs more data into the hash's state.
+func (d *Digest) Write(p []byte) (n int, err error) {
if d.state != spongeAbsorbing {
panic("sha3: Write after Read")
}
return
}
-// Read squeezes an arbitrary number of bytes from the sponge.
-func (d *state) Read(out []byte) (n int, err error) {
+// read squeezes an arbitrary number of bytes from the sponge.
+func (d *Digest) read(out []byte) (n int, err error) {
// If we're still absorbing, pad and apply the permutation.
if d.state == spongeAbsorbing {
d.padAndPermute()
return
}
-// Sum applies padding to the hash state and then squeezes out the desired
-// number of output bytes. It panics if any output has already been read.
-func (d *state) Sum(in []byte) []byte {
+// Sum appends the current hash to b and returns the resulting slice.
+// It does not change the underlying hash state.
+func (d *Digest) Sum(b []byte) []byte {
if d.state != spongeAbsorbing {
panic("sha3: Sum after Read")
}
// Make a copy of the original hash so that caller can keep writing
// and summing.
- dup := d.clone()
+ dup := d.Clone()
hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation
- dup.Read(hash)
- return append(in, hash...)
+ dup.read(hash)
+ return append(b, hash...)
}
const (
marshaledSize = len(magicSHA3) + 1 + 200 + 1 + 1
)
-func (d *state) MarshalBinary() ([]byte, error) {
+func (d *Digest) MarshalBinary() ([]byte, error) {
return d.AppendBinary(make([]byte, 0, marshaledSize))
}
-func (d *state) AppendBinary(b []byte) ([]byte, error) {
+func (d *Digest) AppendBinary(b []byte) ([]byte, error) {
switch d.dsbyte {
case dsbyteSHA3:
b = append(b, magicSHA3...)
return b, nil
}
-func (d *state) UnmarshalBinary(b []byte) error {
+func (d *Digest) UnmarshalBinary(b []byte) error {
if len(b) != marshaledSize {
return errors.New("sha3: invalid hash state")
}
--- /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.
+
+//go:build !gc || purego || !s390x || !ignore
+
+package sha3
+
+func new224() *Digest {
+ return new224Generic()
+}
+
+func new256() *Digest {
+ return new256Generic()
+}
+
+func new384() *Digest {
+ return new384Generic()
+}
+
+func new512() *Digest {
+ return new512Generic()
+}
+
+func newShake128() *SHAKE {
+ return newShake128Generic()
+}
+
+func newShake256() *SHAKE {
+ return newShake256Generic()
+}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build gc && !purego
+//go:build gc && !purego && ignore
package sha3
// message digest' (KIMD) and 'compute last message digest' (KLMD)
// instructions to compute SHA-3 and SHAKE hashes on IBM Z.
-import (
- "crypto/internal/fips"
- "internal/cpu"
-)
+import "internal/cpu"
// codes represent 7-bit KIMD/KLMD function codes as defined in
// the Principles of Operation.
// new224 returns an assembly implementation of SHA3-224 if available,
// otherwise it returns a generic implementation.
-func new224() fips.Hash {
+func new224() *Digest {
if cpu.S390X.HasSHA3 {
return newAsmState(sha3_224)
}
// new256 returns an assembly implementation of SHA3-256 if available,
// otherwise it returns a generic implementation.
-func new256() fips.Hash {
+func new256() *Digest {
if cpu.S390X.HasSHA3 {
return newAsmState(sha3_256)
}
// new384 returns an assembly implementation of SHA3-384 if available,
// otherwise it returns a generic implementation.
-func new384() fips.Hash {
+func new384() *Digest {
if cpu.S390X.HasSHA3 {
return newAsmState(sha3_384)
}
// new512 returns an assembly implementation of SHA3-512 if available,
// otherwise it returns a generic implementation.
-func new512() fips.Hash {
+func new512() *Digest {
if cpu.S390X.HasSHA3 {
return newAsmState(sha3_512)
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build gc && !purego
+//go:build gc && !purego && ignore
#include "textflag.h"
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package sha3
+package sha3_test
import (
"bytes"
"crypto/internal/fips"
+ . "crypto/internal/fips/sha3"
"encoding"
"encoding/hex"
"fmt"
+ "internal/testenv"
"io"
"math/rand"
+ "runtime"
"strings"
"testing"
)
+// TODO(fips): move tests to the stdlib crypto/sha3 package.
+
+// 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() fips.Hash{
+var testDigests = map[string]func() *Digest{
"SHA3-224": New224,
"SHA3-256": New256,
"SHA3-384": New384,
"Keccak-512": NewLegacyKeccak512,
}
-// testShakes contains functions that return sha3.ShakeHash instances for
+// 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) ShakeHash
+ constructor func(N []byte, S []byte) *SHAKE
defAlgoName string
defCustomStr string
}{
// TestKeccak does a basic test of the non-standardized Keccak hash functions.
func TestKeccak(t *testing.T) {
tests := []struct {
- fn func() fips.Hash
+ fn func() *Digest
data []byte
want string
}{
func TestShakeSum(t *testing.T) {
tests := [...]struct {
name string
- hash ShakeHash
+ hash *SHAKE
expectedLen int
}{
{"SHAKE128", NewShake128(), 32},
}
}
+var sink byte
+
+func TestAllocations(t *testing.T) {
+ testenv.SkipIfOptimizationOff(t)
+
+ want := 0.0
+
+ if runtime.GOARCH == "s390x" {
+ // On s390x the returned hash.Hash is conditional so it escapes.
+ want = 3.0
+ }
+
+ 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)
+ sink ^= out[0]
+ }); allocs > want {
+ 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)
+ sink ^= out[0]
+ h.Read(out)
+ sink ^= out[0]
+ }); allocs > want {
+ 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)
+ sink ^= out[0]
+ }); allocs > want {
+ t.Errorf("expected zero allocations, got %0.1f", allocs)
+ }
+ })
+}
+
func TestCSHAKEAccumulated(t *testing.T) {
// Generated with pycryptodome@3.20.0
//
// console.log(bytesToHex(acc.xof(32)));
//
t.Run("cSHAKE128", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake128, rateK256,
+ testCSHAKEAccumulated(t, NewCShake128, (1600-256)/8,
"bb14f8657c6ec5403d0b0e2ef3d3393497e9d3b1a9a9e8e6c81dbaa5fd809252")
})
t.Run("cSHAKE256", func(t *testing.T) {
- testCSHAKEAccumulated(t, NewCShake256, rateK512,
+ testCSHAKEAccumulated(t, NewCShake256, (1600-512)/8,
"0baaf9250c6e25f0c14ea5c7f9bfde54c8a922c8276437db28f3895bdf6eeeef")
})
}
-func testCSHAKEAccumulated(t *testing.T, newCShake func(N, S []byte) ShakeHash, rate int64, exp string) {
+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++ {
}
}
-// BenchmarkPermutationFunction measures the speed of the permutation function
-// with no input data.
-func BenchmarkPermutationFunction(b *testing.B) {
- b.SetBytes(int64(200))
- var lanes [25]uint64
- for i := 0; i < b.N; i++ {
- keccakF1600(&lanes)
- }
-}
-
// benchmarkHash tests the speed to hash num buffers of buflen each.
func benchmarkHash(b *testing.B, h fips.Hash, size, num int) {
b.StopTimer()
// benchmarkShake is specialized to the Shake instances, which don't
// require a copy on reading output.
-func benchmarkShake(b *testing.B, h ShakeHash, size, num int) {
+func benchmarkShake(b *testing.B, h *SHAKE, size, num int) {
b.StopTimer()
h.Reset()
data := sequentialBytes(size)
package sha3
-// This file defines the ShakeHash interface, and provides
-// functions for creating SHAKE and cSHAKE instances, as well as utility
-// functions for hashing bytes to arbitrary-length output.
-//
-//
-// SHAKE implementation is based on FIPS PUB 202 [1]
-// cSHAKE implementations is based on NIST SP 800-185 [2]
-//
-// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
-// [2] https://doi.org/10.6028/NIST.SP.800-185
-
import (
"bytes"
- "crypto/internal/fips"
"errors"
"internal/byteorder"
- "io"
"math/bits"
)
-// ShakeHash defines the interface to hash functions that support
-// arbitrary-length output. When used as a plain [hash.Hash], it
-// produces minimum-length outputs that provide full-strength generic
-// security.
-type ShakeHash interface {
- fips.Hash
-
- // Read reads more output from the hash; reading affects the hash's
- // state. (ShakeHash.Read is thus very different from Hash.Sum)
- // It never returns an error, but subsequent calls to Write or Sum
- // will panic.
- io.Reader
-
- // Clone returns a copy of the ShakeHash in its current state.
- Clone() ShakeHash
-}
-
-// cSHAKE specific context
-type cshakeState struct {
- *state // SHA-3 state context and Read/Write operations
+type SHAKE struct {
+ d Digest // SHA-3 state context and Read/Write operations
// initBlock is the cSHAKE specific initialization set of bytes. It is initialized
// by newCShake function and stores concatenation of N followed by S, encoded
return b
}
-func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) ShakeHash {
- c := cshakeState{state: &state{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}
+func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) *SHAKE {
+ c := &SHAKE{d: Digest{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}
c.initBlock = make([]byte, 0, 9+len(N)+9+len(S)) // leftEncode returns max 9 bytes
c.initBlock = append(c.initBlock, leftEncode(uint64(len(N))*8)...)
c.initBlock = append(c.initBlock, N...)
c.initBlock = append(c.initBlock, leftEncode(uint64(len(S))*8)...)
c.initBlock = append(c.initBlock, S...)
- c.Write(bytepad(c.initBlock, c.rate))
- return &c
+ c.Write(bytepad(c.initBlock, c.d.rate))
+ return c
}
-// Reset resets the hash to initial state.
-func (c *cshakeState) Reset() {
- c.state.Reset()
- c.Write(bytepad(c.initBlock, c.rate))
+func (s *SHAKE) BlockSize() int { return s.d.BlockSize() }
+func (s *SHAKE) Size() int { return s.d.Size() }
+
+// Sum appends a portion of output to b and returns the resulting slice. The
+// output length is selected to provide full-strength generic security: 32 bytes
+// for SHAKE128 and 64 bytes for SHAKE256. It does not change the underlying
+// state. It panics if any output has already been read.
+func (s *SHAKE) Sum(in []byte) []byte { return s.d.Sum(in) }
+
+// Write absorbs more data into the hash's state.
+// It panics if any output has already been read.
+func (s *SHAKE) Write(p []byte) (n int, err error) { return s.d.Write(p) }
+
+func (s *SHAKE) Read(out []byte) (n int, err error) {
+ // Note that read is not exposed on Digest since SHA-3 does not offer
+ // variable output length. It is only used internally by Sum.
+ return s.d.read(out)
}
-// Clone returns copy of a cSHAKE context within its current state.
-func (c *cshakeState) Clone() ShakeHash {
- b := make([]byte, len(c.initBlock))
- copy(b, c.initBlock)
- return &cshakeState{state: c.clone(), initBlock: b}
+// Reset resets the hash to initial state.
+func (s *SHAKE) Reset() {
+ s.d.Reset()
+ if len(s.initBlock) != 0 {
+ s.Write(bytepad(s.initBlock, s.d.rate))
+ }
}
-// Clone returns copy of SHAKE context within its current state.
-func (c *state) Clone() ShakeHash {
- return c.clone()
+// Clone returns a copy of the SHAKE context in its current state.
+func (s *SHAKE) Clone() *SHAKE {
+ ret := *s
+ return &ret
}
-func (c *cshakeState) MarshalBinary() ([]byte, error) {
- return c.AppendBinary(make([]byte, 0, marshaledSize+len(c.initBlock)))
+func (s *SHAKE) MarshalBinary() ([]byte, error) {
+ return s.AppendBinary(make([]byte, 0, marshaledSize+len(s.initBlock)))
}
-func (c *cshakeState) AppendBinary(b []byte) ([]byte, error) {
- b, err := c.state.AppendBinary(b)
+func (s *SHAKE) AppendBinary(b []byte) ([]byte, error) {
+ b, err := s.d.AppendBinary(b)
if err != nil {
return nil, err
}
- b = append(b, c.initBlock...)
+ b = append(b, s.initBlock...)
return b, nil
}
-func (c *cshakeState) UnmarshalBinary(b []byte) error {
- if len(b) <= marshaledSize {
+func (s *SHAKE) UnmarshalBinary(b []byte) error {
+ if len(b) < marshaledSize {
return errors.New("sha3: invalid hash state")
}
- if err := c.state.UnmarshalBinary(b[:marshaledSize]); err != nil {
+ if err := s.d.UnmarshalBinary(b[:marshaledSize]); err != nil {
return err
}
- c.initBlock = bytes.Clone(b[marshaledSize:])
+ s.initBlock = bytes.Clone(b[marshaledSize:])
return nil
}
-// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.
-// Its generic security strength is 128 bits against all attacks if at
-// least 32 bytes of its output are used.
-func NewShake128() ShakeHash {
+// NewShake128 creates a new SHAKE128 XOF.
+func NewShake128() *SHAKE {
return newShake128()
}
-// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.
-// Its generic security strength is 256 bits against all attacks if
-// at least 64 bytes of its output are used.
-func NewShake256() ShakeHash {
+// NewShake256 creates a new SHAKE256 XOF.
+func NewShake256() *SHAKE {
return newShake256()
}
-func newShake128Generic() *state {
- return &state{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}
+func newShake128Generic() *SHAKE {
+ return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}
}
-func newShake256Generic() *state {
- return &state{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}
+func newShake256Generic() *SHAKE {
+ return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}
}
-// NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash,
-// a customizable variant of SHAKE128.
-// 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 - two cSHAKE
-// computations on same input with different S yield unrelated outputs.
-// When N and S are both empty, this is equivalent to NewShake128.
-func NewCShake128(N, S []byte) ShakeHash {
+// 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 {
if len(N) == 0 && len(S) == 0 {
return NewShake128()
}
return newCShake(N, S, rateK256, 32, dsbyteCShake)
}
-// NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash,
-// a customizable variant of SHAKE256.
-// 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 - two cSHAKE
-// computations on same input with different S yield unrelated outputs.
-// When N and S are both empty, this is equivalent to NewShake256.
-func NewCShake256(N, S []byte) ShakeHash {
+// 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 {
if len(N) == 0 && len(S) == 0 {
return NewShake256()
}
return newCShake(N, S, rateK512, 64, dsbyteCShake)
}
-
-// 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)
-}
+++ /dev/null
-// Copyright 2023 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.
-
-//go:build !gc || purego || !s390x
-
-package sha3
-
-func newShake128() *state {
- return newShake128Generic()
-}
-
-func newShake256() *state {
- return newShake256Generic()
-}