{"record":{"id":"97e57d9a9ed3088e","repo":"golang/go","slug":"sha3-invalid-hash-state-identifier","errorCode":null,"errorMessage":"sha3: invalid hash state identifier","messagePattern":"sha3: invalid hash state identifier","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/sha3/sha3.go","lineNumber":210,"sourceCode":"\tb = append(b, d.a[:]...)\n\tb = append(b, byte(d.n), byte(d.state))\n\treturn b, nil\n}\n\nfunc (d *Digest) UnmarshalBinary(b []byte) error {\n\tif len(b) != marshaledSize {\n\t\treturn errors.New(\"sha3: invalid hash state\")\n\t}\n\n\tmagic := string(b[:len(magicSHA3)])\n\tb = b[len(magicSHA3):]\n\tswitch {\n\tcase magic == magicSHA3 && d.dsbyte == dsbyteSHA3:\n\tcase magic == magicShake && d.dsbyte == dsbyteShake:\n\tcase magic == magicCShake && d.dsbyte == dsbyteCShake:\n\tcase magic == magicKeccak && d.dsbyte == dsbyteKeccak:\n\tdefault:\n\t\treturn errors.New(\"sha3: invalid hash state identifier\")\n\t}\n\n\trate := int(b[0])\n\tb = b[1:]\n\tif rate != d.rate {\n\t\treturn errors.New(\"sha3: invalid hash state function\")\n\t}\n\n\tcopy(d.a[:], b)\n\tb = b[len(d.a):]\n\n\tn, state := int(b[0]), spongeDirection(b[1])\n\tif n > d.rate {\n\t\treturn errors.New(\"sha3: invalid hash state\")\n\t}\n\td.n = n\n\tif state != spongeAbsorbing && state != spongeSqueezing {\n\t\treturn errors.New(\"sha3: invalid hash state\")","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/sha3/sha3.go#L192-L228","documentation":"Returned in the default branch of the magic/dsbyte switch in sha3 Digest.UnmarshalBinary. The state's stored magic (magicSHA3, magicShake, magicCShake, magicKeccak) must match the digest instance's preconfigured dsbyte (dsbyteSHA3, dsbyteShake, dsbyteCShake, dsbyteKeccak). A mismatch means the bytes belong to a different SHA-3 family member than the digest instance was constructed for.","triggerScenarios":"Calling UnmarshalBinary on a SHAKE digest with bytes marshaled by a plain SHA3-256 digest; on a cSHAKE digest with SHAKE bytes; on a Keccak digest with SHA3 bytes; or on a freshly zero-value Digest whose dsbyte does not match any producer.","commonSituations":"Code that creates a zero-value Digest{} directly instead of via New224/New256/NewLegacyKeccak256/etc.; mixing SHAKE (extendable output) and fixed-output SHA-3 state in the same persistence layer; a refactor that changed the digest constructor but not the persisted state.","solutions":["Always construct the Digest via the package constructor (New224, New256, NewShake128, etc.) matching the original producer.","If crossing variants, re-hash from the original input.","Tag persisted state with the variant name and dispatch to the matching constructor before UnmarshalBinary.","Never instantiate Digest{} literally with a zero dsbyte and then call UnmarshalBinary."],"exampleFix":"// before\nd := sha3.Digest{} // zero dsbyte -> default branch\nd.UnmarshalBinary(b)\n// after\nd := sha3.New224() // constructs digest with dsbyteSHA3 + 224 rate\nd.(*sha3.Digest).UnmarshalBinary(b)","handlingStrategy":"validation","validationCode":"// ensure the digest instance was constructed with the matching variant\nswitch string(b[:len(magicSHAKE)]) {\ncase magicSHA3, magicShake, magicCShake, magicKeccak:\ndefault:\n    return errors.New(\"bytes are not any SHA-3 family state\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always construct the Digest via the package constructor matching the producer.","Never instantiate Digest{} with a literal zero value and then UnmarshalBinary.","Persist the variant name and dispatch to the right constructor."],"tags":["crypto","hash","sha3","serialization","go-stdlib"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}