golang/go · error
crypto/sha256: invalid hash state identifier
Error message
crypto/sha256: invalid hash state identifier
What it means
Returned by sha224Hash.UnmarshalBinary in the BoringCrypto SHA-256 backend when the blob does not start with the SHA-224 magic (magic224). SHA-224 and SHA-256 share the same 256-bit block context but use distinct magics so a 224-state cannot be loaded into a 256-state and vice versa.
Source
Thrown at src/crypto/internal/boring/sha.go:335
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
b = append(b, magic256...)
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 = byteorder.BEAppendUint32(b, d.h[5])
b = byteorder.BEAppendUint32(b, d.h[6])
b = byteorder.BEAppendUint32(b, d.h[7])
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 *sha224Hash) UnmarshalBinary(b []byte) error {
if len(b) < len(magic224) || string(b[:len(magic224)]) != magic224 {
return errors.New("crypto/sha256: invalid hash state identifier")
}
if len(b) != marshaledSize256 {
return errors.New("crypto/sha256: invalid hash state size")
}
d := (*sha256Ctx)(unsafe.Pointer(&h.ctx))
b = b[len(magic224):]
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, d.h[5] = consumeUint32(b)
b, d.h[6] = consumeUint32(b)
b, d.h[7] = consumeUint32(b)
b = b[copy(d.x[:], b):]
b, n := consumeUint64(b)
d.nl = uint32(n << 3)
d.nh = uint32(n >> 29)View on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the destination hasher matches the source: sha256.New224() for SHA-224 blobs, sha256.New() for SHA-256 blobs.
- Re-hash instead of persisting internal state across builds.
- Check the magic prefix before calling UnmarshalBinary.
Example fix
// before h := sha256.New() // wrong: source was 224 h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state224) // after h := sha256.New224() h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state224)
Defensive patterns
Strategy: validation
Validate before calling
// magic224 is package-private; approximate by checking the SHA-256 family magic
// and use sha256.New224() only for SHA-224-derived blobs.
func looksLikeSHA224State(s []byte) bool {
// first byte differs from sha256 magic; verify against your own snapshot
return len(s) > 0 && s[0] == 's' // tighten to actual prefix in your build
} Type guard
// n/a
Try / catch
if err := h224.(encoding.BinaryUnmarshalser).UnmarshalBinary(state); err != nil {
// mismatched family; route to the correct hasher
} Prevention
- Keep SHA-224 and SHA-256 blobs tagged with their algorithm externally.
- Do not share UnmarshalBinary targets between 224 and 256.
- Re-hash when crossing builds.
When it happens
Trigger: Calling UnmarshalBinary on a sha256.New224() hash with a blob whose prefix is not magic224 (e.g. a SHA-256 blob, an empty slice, or a SHA-1 blob).
Common situations: Mixing up sha256.New224() and sha256.New() when round-tripping state; persisting state from the non-BoringCrypto build; truncation/corruption of the prefix.
Related errors
- crypto/sha256: invalid hash state size
- crypto/sha1: invalid hash state identifier
- crypto/sha512: invalid hash state identifier
- 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/4706967b5d70c4e7.
Report an issue: GitHub.