golang/go · error
crypto/sha1: invalid hash state size
Error message
crypto/sha1: invalid hash state size
What it means
Thrown by sha1.digest.UnmarshalBinary when the input length does not equal marshaledSize. SHA-1's marshaled state is a fixed size (magic + 5x uint32 state + 64-byte block + uint64 length); a length mismatch means the blob is truncated, extended, or from an incompatible version.
Source
Thrown at src/crypto/sha1/sha1.go:74
func (d *digest) AppendBinary(b []byte) ([]byte, error) {
b = append(b, magic...)
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)-d.nx)...)
b = byteorder.BEAppendUint64(b, d.len)
return b, nil
}
func (d *digest) UnmarshalBinary(b []byte) error {
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
return errors.New("crypto/sha1: invalid hash state identifier")
}
if len(b) != marshaledSize {
return errors.New("crypto/sha1: invalid hash state size")
}
b = b[len(magic):]
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, d.len = consumeUint64(b)
d.nx = int(d.len % chunk)
return nil
}
func consumeUint64(b []byte) ([]byte, uint64) {
return b[8:], byteorder.BEUint64(b)
}
func consumeUint32(b []byte) ([]byte, uint32) {View on GitHub (pinned to b6b368adc5)
Solutions
- Validate len(b) == sha1 marshaledSize (currently magic + 20 + 64 + 8 bytes) before unmarshaling.
- Re-marshal the state on the same Go version that will unmarshal it.
- If persisting hash states, version-stamp the format and migrate on load.
- Treat length mismatches as corruption and restart hashing rather than guessing.
Example fix
// before
err := d.UnmarshalBinary(truncatedBlob)
// after
const sha1MarshaledSize = len("sha\x01") + 20 + 64 + 8
if len(b) != sha1MarshaledSize {
return fmt.Errorf("bad sha1 state size: %d", len(b))
}
err := d.UnmarshalBinary(b) Defensive patterns
Strategy: validation
Validate before calling
// Validate the exact marshaled size before calling UnmarshalBinary.
// sha1.marshaledSize = len(magic) + 5*4 + 64 + 8 bytes.
func safeUnmarshalSized(d *sha1.Digest, b []byte) error {
const marshaledSize = 4 + 20 + 64 + 8 // adjust magic len to match source
if len(b) != marshaledSize {
return fmt.Errorf("sha1 state size mismatch: %d", len(b))
}
return d.UnmarshalBinary(b)
} Prevention
- Pin the Go version used to marshal/unmarshal hash states, or migrate formats explicitly.
- Persist the marshaled size alongside the blob and compare on load.
- Do not append or truncate a marshaled state blob in transit.
- Restart hashing from scratch if a state fails to load, rather than guessing.
When it happens
Trigger: Calling UnmarshalBinary on a byte slice whose length != sha1.marshaledSize. The magic check has already passed, so this is the right algorithm but wrong size.
Common situations: Truncated transfer of a marshaled state; blob from a different Go/version with a different marshaled layout; appended trailing bytes; gob/json round-trip that altered length.
Related errors
- crypto/sha1: invalid hash state identifier
- crypto/sha1: invalid hash state identifier
- crypto/sha1: invalid hash state size
- crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mo
- globalThis.crypto is not available, polyfill required (crypt
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/a90a590996229d12.
Report an issue: GitHub.