golang/go · error
crypto/md5: invalid hash state identifier
Error message
crypto/md5: invalid hash state identifier
What it means
Returned by md5 digest.UnmarshalBinary when the input is shorter than the magic prefix or the prefix does not equal md5's magic constant. The magic identifies the bytes as MD5 state; a mismatch means the data is not a valid MD5 serialized state (or belongs to a different hash).
Source
Thrown at src/crypto/md5/md5.go:83
func (d *digest) MarshalBinary() ([]byte, error) {
return d.AppendBinary(make([]byte, 0, marshaledSize))
}
func (d *digest) AppendBinary(b []byte) ([]byte, error) {
b = append(b, magic...)
b = byteorder.BEAppendUint32(b, d.s[0])
b = byteorder.BEAppendUint32(b, d.s[1])
b = byteorder.BEAppendUint32(b, d.s[2])
b = byteorder.BEAppendUint32(b, d.s[3])
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/md5: invalid hash state identifier")
}
if len(b) != marshaledSize {
return errors.New("crypto/md5: invalid hash state size")
}
b = b[len(magic):]
b, d.s[0] = consumeUint32(b)
b, d.s[1] = consumeUint32(b)
b, d.s[2] = consumeUint32(b)
b, d.s[3] = consumeUint32(b)
b = b[copy(d.x[:], b):]
b, d.len = consumeUint64(b)
d.nx = int(d.len % BlockSize)
return nil
}
func consumeUint64(b []byte) ([]byte, uint64) {
return b[8:], byteorder.BEUint64(b[0:8])
}View on GitHub (pinned to b6b368adc5)
Solutions
- Verify the bytes were produced by md5's MarshalBinary on the same Go version.
- If migrating from another hash, re-hash from the original input.
- Check len(b) >= len(magic) before calling and treat shorter buffers as corrupt.
- Prefer SHA-256 over MD5 for any new code (MD5 is cryptographically broken).
Example fix
// before d.UnmarshalBinary(sha1StateBytes) // wrong magic -> error // after d.UnmarshalBinary(md5StateBytes) // produced by md5 MarshalBinary
Defensive patterns
Strategy: validation
Validate before calling
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
return errors.New("not MD5 marshaled state")
} Prevention
- Verify bytes were produced by md5's MarshalBinary on the same Go version.
- Prefer SHA-256 over MD5 for any new code.
- Re-hash from the original input when migrating from another hash.
When it happens
Trigger: Calling UnmarshalBinary on an MD5 digest with bytes from another hash (SHA-1, SHA-256), corrupted bytes, an empty buffer, or a buffer shorter than the magic prefix.
Common situations: Persisting MD5 hash state and reloading it with corrupted or empty data; sending hash state over a protocol where another hash writes the same field; downgrading code that previously used a stronger hash and forgetting to migrate the stored state.
Related errors
- crypto/md5: invalid hash state size
- crypto/sha256: invalid hash state identifier
- crypto/sha256: invalid hash state size
- sha3: invalid hash state
- sha3: invalid hash state identifier
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/8f3ca4de6656d58b.
Report an issue: GitHub.