golang/go · error
crypto/sha1: invalid hash state size
Error message
crypto/sha1: invalid hash state size
What it means
Returned by sha1Hash.UnmarshalBinary after the magic check passes but the total byte length does not equal sha1MarshaledSize (len("sha\x01") + 5*4 + 64 + 8 = 92). It guards against partial/truncated or extended blobs that would otherwise read out of bounds during the fixed-shape decode.
Source
Thrown at src/crypto/internal/boring/sha.go:185
d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
b = append(b, sha1Magic...)
b = byteorder.BEAppendUint32(b, d.h[0])
b = byteorder.BEAppendUint32(b, d.h[1])
b = byteorder.BEAppendUint32(b, d.h[2])
b = byteorder.BEAppendUint32(b, d.h[3])
b = byteorder.BEAppendUint32(b, d.h[4])
b = append(b, d.x[:d.nx]...)
b = append(b, make([]byte, len(d.x)-int(d.nx))...)
b = byteorder.BEAppendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)
return b, nil
}
func (h *sha1Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(sha1Magic) || string(b[:len(sha1Magic)]) != sha1Magic {
return errors.New("crypto/sha1: invalid hash state identifier")
}
if len(b) != sha1MarshaledSize {
return errors.New("crypto/sha1: invalid hash state size")
}
d := (*sha1Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(sha1Magic):]
b, d.h[0] = consumeUint32(b)
b, d.h[1] = consumeUint32(b)
b, d.h[2] = consumeUint32(b)
b, d.h[3] = consumeUint32(b)
b, d.h[4] = consumeUint32(b)
b = b[copy(d.x[:], b):]
b, n := consumeUint64(b)
d.nl = uint32(n << 3)
d.nh = uint32(n >> 29)
d.nx = uint32(n) % 64
return nil
}
// NewSHA224 returns a new SHA224 hash.
func NewSHA224() hash.Hash {View on GitHub (pinned to b6b368adc5)
Solutions
- Verify length == 92 bytes (current Go) before unmarshalling, and reject mismatches explicitly.
- Re-derive the state by re-hashing rather than persisting internal state across versions.
- Regenerate the persisted blob from a current build of Go.
Example fix
// before
h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state)
// after
const sha1MarshaledSize = 92
if len(state) != sha1MarshaledSize || string(state[:4]) != "sha\x01" {
return fmt.Errorf("bad sha1 state")
}
h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state) Defensive patterns
Strategy: validation
Validate before calling
const sha1MarshaledSize = 4 + 5*4 + 64 + 8 // = 92
func validSHA1State(s []byte) bool {
return len(s) == sha1MarshaledSize && string(s[:4]) == "sha\x01"
} Type guard
// n/a
Try / catch
if err := h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state); err != nil {
return fmt.Errorf("cannot restore sha1 state: %w", err)
} Prevention
- Validate magic and length before UnmarshalBinary.
- Regenerate fixtures when upgrading Go.
- Avoid storing marshalled hash state long-term.
When it happens
Trigger: Calling UnmarshalBinary on a sha1.New() hash with a blob of the correct magic but wrong length (truncated, padded, or from a future Go version whose marshalled layout differs).
Common situations: Blob stored in a DB/queue and later truncated; blob produced by a different Go version whose sha1MarshaledSize changed; hand-constructed test fixture with wrong padding.
Related errors
- crypto/sha1: invalid hash state identifier
- crypto/sha256: invalid hash state size
- crypto/sha512: invalid hash state size
- crypto/ecdh: invalid private key
- crypto/aes: GCM tag and nonce sizes can't be non-standard at
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/d1698a3c35ca4cf5.
Report an issue: GitHub.