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.

Solutions

  1. Validate length equals marshaledSize256 before unmarshalling.
  2. Regenerate the persisted blob from the current Go build.
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/8daa5d59f9348313. Report an issue: GitHub.

Appendix: 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)