golang/go · error

crypto/sha512: invalid hash state size

Error message

crypto/sha512: invalid hash state size

What it means

Returned by sha512 Digest.UnmarshalBinary when the magic prefix is valid (variant matched) but the total byte length is not marshaledSize. The sha512 layout is fixed-length (magic + 8 x uint64 state + 128-byte block buffer + uint64 length counter); truncation or extra bytes fail this check.

Source

Thrown at src/crypto/internal/fips140/sha512/sha512.go:177

	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(magic512) {
		return errors.New("crypto/sha512: invalid hash state identifier")
	}
	switch {
	case d.size == size384 && string(b[:len(magic384)]) == magic384:
	case d.size == size224 && string(b[:len(magic512_224)]) == magic512_224:
	case d.size == size256 && string(b[:len(magic512_256)]) == magic512_256:
	case d.size == size512 && string(b[:len(magic512)]) == magic512:
	default:
		return errors.New("crypto/sha512: invalid hash state identifier")
	}
	if len(b) != marshaledSize {
		return errors.New("crypto/sha512: invalid hash state size")
	}
	b = b[len(magic512):]
	b, d.h[0] = consumeUint64(b)
	b, d.h[1] = consumeUint64(b)
	b, d.h[2] = consumeUint64(b)
	b, d.h[3] = consumeUint64(b)
	b, d.h[4] = consumeUint64(b)
	b, d.h[5] = consumeUint64(b)
	b, d.h[6] = consumeUint64(b)
	b, d.h[7] = consumeUint64(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)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Store and retrieve the full marshaledSize bytes unchanged; verify byte-for-byte length.
  2. If data transits a length-prefixed protocol, check the length prefix matches marshaledSize before forwarding.
  3. Re-hash from the original input if the state is unrecoverable.
  4. Pin producer and consumer Go major versions when persisting hash state long-term.

Example fix

// before
d.UnmarshalBinary(b[:len(b)-1]) // missing last byte -> error
// after
d.UnmarshalBinary(b) // exact marshaledSize
Defensive patterns

Strategy: validation

Validate before calling

if len(b) != marshaledSize {
    return fmt.Errorf("sha512 state size mismatch: got %d want %d", len(b), marshaledSize)
}

Prevention

When it happens

Trigger: Passing bytes whose variant magic is correct but whose length differs from the fixed marshaledSize: a buffer truncated by storage, an extra trailing byte appended by a buggy serializer, or bytes from a build with a different marshaled layout.

Common situations: Database BLOB column sized too small and silently truncating; transport framing that drops or duplicates bytes; copy/paste of a hex string that lost or added characters; version skew between producer and consumer Go builds.

Related errors


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