golang/go · error
sha3: invalid hash state
Error message
sha3: invalid hash state
What it means
First line of defense in sha3 Digest.UnmarshalBinary: if the input length is not exactly marshaledSize, the state cannot be parsed. The sha3 marshaled layout is fixed-length (magic + rate byte + 200-byte Keccak state + n + state byte), so any size mismatch is rejected up front before the magic is even inspected.
Source
Thrown at src/crypto/internal/fips140/sha3/sha3.go:199
case dsbyteShake:
b = append(b, magicShake...)
case dsbyteCShake:
b = append(b, magicCShake...)
case dsbyteKeccak:
b = append(b, magicKeccak...)
default:
panic("unknown dsbyte")
}
// rate is at most 168, and n is at most rate.
b = append(b, byte(d.rate))
b = append(b, d.a[:]...)
b = append(b, byte(d.n), byte(d.state))
return b, nil
}
func (d *Digest) UnmarshalBinary(b []byte) error {
if len(b) != marshaledSize {
return errors.New("sha3: invalid hash state")
}
magic := string(b[:len(magicSHA3)])
b = b[len(magicSHA3):]
switch {
case magic == magicSHA3 && d.dsbyte == dsbyteSHA3:
case magic == magicShake && d.dsbyte == dsbyteShake:
case magic == magicCShake && d.dsbyte == dsbyteCShake:
case magic == magicKeccak && d.dsbyte == dsbyteKeccak:
default:
return errors.New("sha3: invalid hash state identifier")
}
rate := int(b[0])
b = b[1:]
if rate != d.rate {
return errors.New("sha3: invalid hash state function")
}View on GitHub (pinned to b6b368adc5)
Solutions
- Verify len(b) == marshaledSize before calling; if not, discard and re-hash from the source.
- Tag persisted hash state with its algorithm family (sha3-256 vs shake128 vs cshake) so the right UnmarshalBinary is invoked.
- For SHAKE state, call UnmarshalBinary on the *SHAKE type (which expects the trailing initBlock), not on the inner Digest.
- Use io.ReadFull and check the returned error when loading the buffer from disk/network.
Example fix
// before
b, _ := os.ReadFile("state.bin")
digest.UnmarshalBinary(b) // size mismatch -> error
// after
b, err := os.ReadFile("state.bin")
if err != nil || len(b) != marshaledSize { rehash() }
digest.UnmarshalBinary(b) Defensive patterns
Strategy: validation
Validate before calling
if len(b) != marshaledSize {
return fmt.Errorf("sha3 state size mismatch: got %d want %d", len(b), marshaledSize)
} Prevention
- Tag persisted SHA-3 state with the variant (sha3-256 vs shake128 vs cshake).
- For SHAKE state use the SHAKE wrapper's UnmarshalBinary, not the inner Digest's.
- Load state with io.ReadFull and surface EOF as a re-hash trigger.
When it happens
Trigger: Calling UnmarshalBinary with truncated, padded, or over-length SHA-3 state bytes; passing SHAKE-128 state to a plain SHA-3 digest (the SHAKE wrapper carries an extra initBlock suffix beyond marshaledSize and is handled by shake.go, not here); passing bytes from a non-SHA-3 source.
Common situations: Storing sha3 state and SHAKE state in the same column without tagging; a transport that fragments/reassembles the buffer incorrectly; reading the buffer with io.ReadFull that hit EOF early without the caller noticing.
Related errors
- sha3: invalid hash state identifier
- sha3: invalid hash state function
- sha3: invalid hash state
- crypto/sha256: invalid hash state identifier
- crypto/sha256: invalid hash state size
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/4955051dee621dc5.
Report an issue: GitHub.