]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/sha3: make the zero value of SHAKE useable
authorqiulaidongfeng <2645477756@qq.com>
Thu, 6 Nov 2025 17:58:58 +0000 (01:58 +0800)
committerSean Liao <sean@liao.dev>
Fri, 21 Nov 2025 21:27:43 +0000 (13:27 -0800)
For #75154

Change-Id: Iee5a11ebea8c74b9abab4c077dc7990fe8f562dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/718521
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/crypto/sha3/sha3.go
src/crypto/sha3/sha3_test.go

index 9bdc91409838738e53017b80bd3f3b98e8552893..48c67e9fe11005957038fdcc8181bb6e0ef94c0b 100644 (file)
@@ -188,10 +188,17 @@ func (d *SHA3) Clone() (hash.Cloner, error) {
 }
 
 // SHAKE is an instance of a SHAKE extendable output function.
+// The zero value is a usable SHAKE256 hash.
 type SHAKE struct {
        s sha3.SHAKE
 }
 
+func (s *SHAKE) init() {
+       if s.s.Size() == 0 {
+               *s = *NewSHAKE256()
+       }
+}
+
 // NewSHAKE128 creates a new SHAKE128 XOF.
 func NewSHAKE128() *SHAKE {
        return &SHAKE{*sha3.NewShake128()}
@@ -224,6 +231,7 @@ func NewCSHAKE256(N, S []byte) *SHAKE {
 //
 // It panics if any output has already been read.
 func (s *SHAKE) Write(p []byte) (n int, err error) {
+       s.init()
        return s.s.Write(p)
 }
 
@@ -231,30 +239,36 @@ func (s *SHAKE) Write(p []byte) (n int, err error) {
 //
 // Any call to Write after a call to Read will panic.
 func (s *SHAKE) Read(p []byte) (n int, err error) {
+       s.init()
        return s.s.Read(p)
 }
 
 // Reset resets the XOF to its initial state.
 func (s *SHAKE) Reset() {
+       s.init()
        s.s.Reset()
 }
 
 // BlockSize returns the rate of the XOF.
 func (s *SHAKE) BlockSize() int {
+       s.init()
        return s.s.BlockSize()
 }
 
 // MarshalBinary implements [encoding.BinaryMarshaler].
 func (s *SHAKE) MarshalBinary() ([]byte, error) {
+       s.init()
        return s.s.MarshalBinary()
 }
 
 // AppendBinary implements [encoding.BinaryAppender].
 func (s *SHAKE) AppendBinary(p []byte) ([]byte, error) {
+       s.init()
        return s.s.AppendBinary(p)
 }
 
 // UnmarshalBinary implements [encoding.BinaryUnmarshaler].
 func (s *SHAKE) UnmarshalBinary(data []byte) error {
+       s.init()
        return s.s.UnmarshalBinary(data)
 }
index 2c2e5c98ff84d0ece695e939d8fdfa2870130c4d..3973e0afd1b935e0ab2f5b631f44a43cb7cd68b9 100644 (file)
@@ -37,10 +37,11 @@ var testShakes = map[string]struct {
        defCustomStr string
 }{
        // NewCSHAKE without customization produces same result as SHAKE
-       "SHAKE128":  {NewCSHAKE128, "", ""},
-       "SHAKE256":  {NewCSHAKE256, "", ""},
-       "cSHAKE128": {NewCSHAKE128, "CSHAKE128", "CustomString"},
-       "cSHAKE256": {NewCSHAKE256, "CSHAKE256", "CustomString"},
+       "SHAKE128":   {NewCSHAKE128, "", ""},
+       "SHAKE256":   {NewCSHAKE256, "", ""},
+       "cSHAKE128":  {NewCSHAKE128, "CSHAKE128", "CustomString"},
+       "cSHAKE256":  {NewCSHAKE256, "CSHAKE256", "CustomString"},
+       "SHAKE-Zero": {func(N []byte, S []byte) *SHAKE { return &SHAKE{} }, "", ""},
 }
 
 func TestSHA3Hash(t *testing.T) {