{"record":{"id":"19c691446491bd05","repo":"golang/go","slug":"crypto-sha1-invalid-hash-state-identifier","errorCode":null,"errorMessage":"crypto/sha1: invalid hash state identifier","messagePattern":"crypto/sha1: invalid hash state identifier","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/boring/sha.go","lineNumber":182,"sourceCode":"}\n\nfunc (h *sha1Hash) AppendBinary(b []byte) ([]byte, error) {\n\td := (*sha1Ctx)(unsafe.Pointer(&h.ctx))\n\tb = append(b, sha1Magic...)\n\tb = byteorder.BEAppendUint32(b, d.h[0])\n\tb = byteorder.BEAppendUint32(b, d.h[1])\n\tb = byteorder.BEAppendUint32(b, d.h[2])\n\tb = byteorder.BEAppendUint32(b, d.h[3])\n\tb = byteorder.BEAppendUint32(b, d.h[4])\n\tb = append(b, d.x[:d.nx]...)\n\tb = append(b, make([]byte, len(d.x)-int(d.nx))...)\n\tb = byteorder.BEAppendUint64(b, uint64(d.nl)>>3|uint64(d.nh)<<29)\n\treturn b, nil\n}\n\nfunc (h *sha1Hash) UnmarshalBinary(b []byte) error {\n\tif len(b) < len(sha1Magic) || string(b[:len(sha1Magic)]) != sha1Magic {\n\t\treturn errors.New(\"crypto/sha1: invalid hash state identifier\")\n\t}\n\tif len(b) != sha1MarshaledSize {\n\t\treturn errors.New(\"crypto/sha1: invalid hash state size\")\n\t}\n\td := (*sha1Ctx)(unsafe.Pointer(&h.ctx))\n\tb = b[len(sha1Magic):]\n\tb, d.h[0] = consumeUint32(b)\n\tb, d.h[1] = consumeUint32(b)\n\tb, d.h[2] = consumeUint32(b)\n\tb, d.h[3] = consumeUint32(b)\n\tb, d.h[4] = consumeUint32(b)\n\tb = b[copy(d.x[:], b):]\n\tb, n := consumeUint64(b)\n\td.nl = uint32(n << 3)\n\td.nh = uint32(n >> 29)\n\td.nx = uint32(n) % 64\n\treturn nil\n}","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/boring/sha.go#L164-L200","documentation":"Returned by sha1Hash.UnmarshalBinary in the BoringCrypto SHA-1 backend when the marshalled blob does not begin with the magic bytes \"sha\\x01\". This is the Go encoding.BinaryUnmarshalser contract used by hash.Hash; the magic identifies which algorithm/version produced the state so it cannot be loaded into the wrong hasher.","triggerScenarios":"Calling h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state) on a sha1.New() hash with state bytes that do not start with \"sha\\x01\", are empty, or were produced by a different hash (e.g. sha256.MarshalBinary output) or a non-BoringCrypto sha1 implementation.","commonSituations":"Cross-build portability: state marshalled by the standard (non-Boring) crypto/sha1 uses a different magic and cannot be unmarshalled by the BoringCrypto build, or vice versa. Also triggered by truncation, corruption, or feeding a SHA-256/512 blob into a SHA-1 hasher.","solutions":["Confirm the blob was produced by MarshalBinary on the same SHA-1 implementation (same BoringCrypto setting) in the same Go version.","Use sha1.New() fresh and re-hash the data instead of round-tripping state across builds/versions.","Validate the magic prefix (\"sha\\x01\") and length before calling UnmarshalBinary."],"exampleFix":"// before\nh := sha1.New()\nh.(encoding.BinaryUnmarshalser).UnmarshalBinary(stateFromOtherBuild)\n// after\nh := sha1.New()\nh.Write(data) // recompute instead of cross-loading state","handlingStrategy":"validation","validationCode":"func isValidSHA1State(state []byte) bool {\n    const magic = \"sha\\x01\"\n    return len(state) >= len(magic) && string(state[:len(magic)]) == magic\n}\n// call before h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state)","typeGuard":"// n/a","tryCatchPattern":"if err := h.(encoding.BinaryUnmarshalser).UnmarshalBinary(state); err != nil {\n    // treat as unrecoverable; recompute the hash from source data\n}","preventionTips":["Never persist hash internal state across Go versions or build configs.","Round-trip state only within the same process lifetime.","Re-hash the original data when in doubt."],"tags":["crypto","sha1","boringcrypto","serialization","hash"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}