golang/go · error

sha3: invalid hash state

Error message

sha3: invalid hash state

What it means

Returned by SHAKE.UnmarshalBinary when the input is shorter than marshaledSize. SHAKE state is the inner sha3 Digest marshaled state plus a trailing initBlock (the cSHAKE/SHAKE prefix block); the SHAKE wrapper first checks the minimum length, then delegates the prefix to the inner Digest.UnmarshalBinary and clones the remainder into initBlock.

Source

Thrown at src/crypto/internal/fips140/sha3/shake.go:110

	return &ret
}

func (s *SHAKE) MarshalBinary() ([]byte, error) {
	return s.AppendBinary(make([]byte, 0, marshaledSize+len(s.initBlock)))
}

func (s *SHAKE) AppendBinary(b []byte) ([]byte, error) {
	b, err := s.d.AppendBinary(b)
	if err != nil {
		return nil, err
	}
	b = append(b, s.initBlock...)
	return b, nil
}

func (s *SHAKE) UnmarshalBinary(b []byte) error {
	if len(b) < marshaledSize {
		return errors.New("sha3: invalid hash state")
	}
	if err := s.d.UnmarshalBinary(b[:marshaledSize]); err != nil {
		return err
	}
	s.initBlock = bytes.Clone(b[marshaledSize:])
	return nil
}

// NewShake128 creates a new SHAKE128 XOF.
func NewShake128() *SHAKE {
	return &SHAKE{d: Digest{rate: rateK256, outputLen: 32, dsbyte: dsbyteShake}}
}

// NewShake256 creates a new SHAKE256 XOF.
func NewShake256() *SHAKE {
	return &SHAKE{d: Digest{rate: rateK512, outputLen: 64, dsbyte: dsbyteShake}}
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Always marshal/unmarshal SHAKE state through SHAKE's own AppendBinary/UnmarshalBinary so the initBlock is included.
  2. Verify len(b) >= marshaledSize before calling; if not, re-XOF from scratch.
  3. Tag persisted state with the XOF variant and validate length against the known SHAKE marshaled size.

Example fix

// before
shake.UnmarshalBinary(innerDigestBytesOnly) // too short -> error
// after
full, _ := producer.AppendBinary(nil) // includes initBlock
shake.UnmarshalBinary(full)
Defensive patterns

Strategy: validation

Validate before calling

if len(b) < marshaledSize {
    return fmt.Errorf("SHAKE state too short: got %d want >= %d", len(b), marshaledSize)
}

Prevention

When it happens

Trigger: Calling UnmarshalBinary on a SHAKE instance with a buffer shorter than the inner Digest's marshaledSize; e.g. passing plain SHA-3 state (no initBlock), passing a truncated buffer, or passing bytes from a non-SHAKE source.

Common situations: Storing SHAKE state without the initBlock suffix (older code path, hand-rolled serialization); buffer truncation in transit; confusion between SHAKE-128/256 inner-state size and the full SHAKE marshaled size.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/f33987900792515f. Report an issue: GitHub.