{"record":{"id":"1add0af1e828a570","repo":"golang/go","slug":"ecdsa-hash-cannot-be-empty","errorCode":null,"errorMessage":"ecdsa: hash cannot be empty","messagePattern":"ecdsa: hash cannot be empty","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/ecdsa/ecdsa.go","lineNumber":393,"sourceCode":"\tprivateKey, err := ecdsa.GenerateKey(c, rand)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn privateKeyFromFIPS(curve, privateKey)\n}\n\n// SignASN1 signs a hash (which should be the result of hashing a larger message)\n// using the private key, priv. If the hash is longer than the bit-length of the\n// private key's curve order, the hash will be truncated to that length. It\n// returns the ASN.1 encoded signature.\n//\n// The signature is randomized. Since Go 1.26, a secure source of random bytes\n// is always used, and the Reader is ignored unless GODEBUG=cryptocustomrand=1\n// is set. This setting will be removed in a future Go release. Instead, use\n// [testing/cryptotest.SetGlobalRandom].\nfunc SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {\n\tif len(hash) == 0 {\n\t\treturn nil, errors.New(\"ecdsa: hash cannot be empty\")\n\t}\n\n\tif boring.Enabled && rand.IsDefaultReader(r) {\n\t\tb, err := boringPrivateKey(priv)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn boring.SignMarshalECDSA(b, hash)\n\t}\n\tboring.UnreachableExceptTests()\n\n\tr = rand.CustomReader(r)\n\n\tswitch priv.Curve.Params() {\n\tcase elliptic.P224().Params():\n\t\treturn signFIPS(ecdsa.P224(), priv, r, hash)\n\tcase elliptic.P256().Params():\n\t\treturn signFIPS(ecdsa.P256(), priv, r, hash)","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/ecdsa/ecdsa.go#L375-L411","documentation":"Thrown by SignASN1 when the hash parameter is empty (len(hash) == 0). ECDSA signing requires a non-empty hash digest — an empty hash indicates the caller didn't hash the message at all. This is a guard against trivially insecure signatures on empty data and prevents ambiguous signing behavior.","triggerScenarios":"Calling ecdsa.SignASN1(r, priv, hash) where hash is nil or an empty byte slice. This occurs when the caller forgets to hash the message, passes an uninitialized hash variable, or accidentally passes an empty message through a hash function that produced no output (shouldn't happen with standard hashes but can with custom pipelines).","commonSituations":"Code that signs a potentially-empty message without checking; deserialization bugs that produce empty digests; forgetting to call the hash function and passing the message directly (if the message itself is empty); refactoring that accidentally removes the hashing step.","solutions":["Always hash the message before calling SignASN1: digest := sha256.Sum256(msg); then pass digest[:].","Add a pre-check: if len(hash) == 0 { return error } before calling SignASN1 to give a more descriptive error.","Verify the hashing pipeline produces non-empty output for all expected inputs."],"exampleFix":"// before\nsig, err := ecdsa.SignASN1(rand.Reader, priv, nil)\n\n// after\ndigest := sha256.Sum256(msg)\nsig, err := ecdsa.SignASN1(rand.Reader, priv, digest[:])","handlingStrategy":"validation","validationCode":"func validateHashNotEmpty(hash []byte) error {\n    if len(hash) == 0 {\n        return errors.New(\"hash digest must not be empty\")\n    }\n    return nil\n}","typeGuard":"func isNonEmptyHash(hash []byte) bool {\n    return len(hash) > 0\n}","tryCatchPattern":"sig, err := ecdsa.SignASN1(r, priv, hash)\nif err != nil {\n    return fmt.Errorf(\"cannot sign empty hash (len=%d): %w\", len(hash), err)\n}","preventionTips":["Always hash the message before signing — never pass raw or empty data to SignASN1.","Add a guard: if len(digest) == 0 { return err } before calling SignASN1."],"tags":["crypto","ecdsa","signing","hash","input-validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}