golang/go · error
crypto/sha256: invalid hash state size
Error message
crypto/sha256: invalid hash state size
What it means
Returned by sha224Hash.UnmarshalBinary when the magic matches SHA-224 but the total length is not marshaledSize256. The SHA-224 and SHA-256 contexts share the same marshalled size constant, so this length check is shared between both UnmarshalBinary methods.
Source
Thrown at src/crypto/internal/boring/sha.go:338
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)
d.nx = uint32(n) % 64
return nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Validate length equals marshaledSize256 before unmarshalling.
- Regenerate the persisted blob from the current Go build.
- Re-hash the original data instead of restoring state.
Example fix
// before
h := sha256.New224()
h.(encoding.BinaryUnmarshalser).UnmarshalBinary(truncatedState)
// after
if !validSHA256FamilyState(state) { return errors.New("bad state") }
h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state) Defensive patterns
Strategy: validation
Validate before calling
// marshaledSize256 for the BoringCrypto build
const sha256MarshaledSize = 4 + 8*4 + 64 + 8 // = 108
func validSHA256FamilyState(s []byte) bool {
return len(s) == sha256MarshaledSize && s[0] == 's'
} Type guard
// n/a
Try / catch
if err := h224.(encoding.BinaryUnmarshalser).UnmarshalBinary(state); err != nil {
return err
} Prevention
- Validate length before unmarshalling.
- Version your persisted state format.
- Regenerate blobs on Go upgrades.
When it happens
Trigger: Calling UnmarshalBinary on a sha256.New224() hash with a blob of correct SHA-224 magic but wrong total length.
Common situations: Truncated/padded persisted state; state produced by a Go version with a different marshalled layout; corruption in transport/storage.
Related errors
- crypto/sha256: invalid hash state identifier
- crypto/sha1: 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/8daa5d59f9348313.
Report an issue: GitHub.