golang/go · error

ecdsa: hash cannot be empty

Error message

ecdsa: hash cannot be empty

What it means

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.

Source

Thrown at src/crypto/ecdsa/ecdsa.go:393

	privateKey, err := ecdsa.GenerateKey(c, rand)
	if err != nil {
		return nil, err
	}
	return privateKeyFromFIPS(curve, privateKey)
}

// SignASN1 signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
// returns the ASN.1 encoded signature.
//
// The signature is randomized. Since Go 1.26, a secure source of random bytes
// is always used, and the Reader is ignored unless GODEBUG=cryptocustomrand=1
// is set. This setting will be removed in a future Go release. Instead, use
// [testing/cryptotest.SetGlobalRandom].
func SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
	if len(hash) == 0 {
		return nil, errors.New("ecdsa: hash cannot be empty")
	}

	if boring.Enabled && rand.IsDefaultReader(r) {
		b, err := boringPrivateKey(priv)
		if err != nil {
			return nil, err
		}
		return boring.SignMarshalECDSA(b, hash)
	}
	boring.UnreachableExceptTests()

	r = rand.CustomReader(r)

	switch priv.Curve.Params() {
	case elliptic.P224().Params():
		return signFIPS(ecdsa.P224(), priv, r, hash)
	case elliptic.P256().Params():
		return signFIPS(ecdsa.P256(), priv, r, hash)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Always hash the message before calling SignASN1: digest := sha256.Sum256(msg); then pass digest[:].
  2. Add a pre-check: if len(hash) == 0 { return error } before calling SignASN1 to give a more descriptive error.
  3. Verify the hashing pipeline produces non-empty output for all expected inputs.

Example fix

// before
sig, err := ecdsa.SignASN1(rand.Reader, priv, nil)

// after
digest := sha256.Sum256(msg)
sig, err := ecdsa.SignASN1(rand.Reader, priv, digest[:])
Defensive patterns

Strategy: validation

Validate before calling

func validateHashNotEmpty(hash []byte) error {
    if len(hash) == 0 {
        return errors.New("hash digest must not be empty")
    }
    return nil
}

Type guard

func isNonEmptyHash(hash []byte) bool {
    return len(hash) > 0
}

Try / catch

sig, err := ecdsa.SignASN1(r, priv, hash)
if err != nil {
    return fmt.Errorf("cannot sign empty hash (len=%d): %w", len(hash), err)
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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