golang/go · error

crypto/sha1: invalid hash state identifier

Error message

crypto/sha1: invalid hash state identifier

What it means

Thrown by sha1.digest.UnmarshalBinary when the input does not begin with the sha1 magic identifier. UnmarshalBinary reverses MarshalBinary to restore a hash state; the magic prefix distinguishes a SHA-1 blob from other hash encodings. A missing or wrong prefix means the bytes are not a valid SHA-1 state.

Source

Thrown at src/crypto/sha1/sha1.go:71

	return d.AppendBinary(make([]byte, 0, marshaledSize))
}

func (d *digest) AppendBinary(b []byte) ([]byte, error) {
	b = append(b, magic...)
	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 = 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/sha1: invalid hash state identifier")
	}
	if len(b) != marshaledSize {
		return errors.New("crypto/sha1: invalid hash state size")
	}
	b = b[len(magic):]
	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 = 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. Ensure the bytes passed to UnmarshalBinary came from a SHA-1 MarshalBinary call.
  2. Check len(b) >= len(magic) and the magic prefix before calling, returning your own error.
  3. Use a single hash algorithm end-to-end so states are type-matched.
  4. If the source is untrusted, treat UnmarshalBinary failure as expected and discard the input.

Example fix

// before
var d sha1.digest
d.UnmarshalBinary(sha256state) // wrong algorithm's blob

// after
if !bytes.HasPrefix(b, []byte("sha\x01")) { // sha1 magic
    return errors.New("not a sha1 state")
}
err := d.UnmarshalBinary(b)
Defensive patterns

Strategy: validation

Validate before calling

// sha1 magic is "sha\x01" (3 bytes). Verify prefix before UnmarshalBinary.
var sha1Magic = []byte{'s', 'h', 'a', 0x01} // confirm exact bytes from source

func safeUnmarshal(d *sha1.Digest, b []byte) error {
    if len(b) < len(sha1Magic) || !bytes.Equal(b[:len(sha1Magic)], sha1Magic) {
        return errors.New("not a sha1 marshaled state")
    }
    return d.UnmarshalBinary(b)
}

Prevention

When it happens

Trigger: Calling UnmarshalBinary (directly, or via encoding/gob, encoding/json with MarshalBinary, or hash.Hash reset/restore) on []byte that is not a SHA-1-marshaled state. Common when the wrong hash's binary blob is fed to a SHA-1 digest.

Common situations: Interchanging marshaled states between SHA-256 and SHA-1; corrupted gob stream storing hash state; truncated blob; passing arbitrary user data to UnmarshalBinary.

Related errors


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