golang/go · error

ecdsa: curve not supported by deterministic signatures

Error message

ecdsa: curve not supported by deterministic signatures

What it means

Thrown by signRFC6979 when priv.Curve.Params() does not match P224, P256, P384, or P521 in the switch statement. RFC 6979 deterministic signing is only implemented for standard NIST curves through the internal FIPS ecdsa.SignDeterministic function. Custom or non-standard curves cannot produce deterministic signatures via this code path.

Source

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

	return encodeSignature(sig.R, sig.S)
}

func signRFC6979(priv *PrivateKey, hash []byte, opts crypto.SignerOpts) ([]byte, error) {
	if opts == nil {
		return nil, errors.New("ecdsa: Sign called with nil random and nil opts")
	}
	h := opts.HashFunc()
	switch priv.Curve.Params() {
	case elliptic.P224().Params():
		return signFIPSDeterministic(ecdsa.P224(), h, priv, hash)
	case elliptic.P256().Params():
		return signFIPSDeterministic(ecdsa.P256(), h, priv, hash)
	case elliptic.P384().Params():
		return signFIPSDeterministic(ecdsa.P384(), h, priv, hash)
	case elliptic.P521().Params():
		return signFIPSDeterministic(ecdsa.P521(), h, priv, hash)
	default:
		return nil, errors.New("ecdsa: curve not supported by deterministic signatures")
	}
}

func signFIPSDeterministic[P ecdsa.Point[P]](c *ecdsa.Curve[P], hashFunc crypto.Hash, priv *PrivateKey, hash []byte) ([]byte, error) {
	k, err := privateKeyToFIPS(c, priv)
	if err != nil {
		return nil, err
	}
	if !hashFunc.Available() {
		return nil, errors.New("ecdsa: requested hash function unavailable: " + hashFunc.String())
	}
	h := fips140hash.UnwrapNew(hashFunc.New)
	if fips140only.Enforced() && !fips140only.ApprovedHash(h()) {
		return nil, errors.New("crypto/ecdsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
	}
	sig, err := ecdsa.SignDeterministic(c, h, k, hash)
	if err != nil {
		return nil, err

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use randomized signing instead: pass a non-nil random reader (e.g., crypto/rand.Reader) which goes through SignASN1 rather than signRFC6979.
  2. Ensure the PrivateKey uses a standard NIST curve (P224/P256/P384/P521) if deterministic signing is required.
  3. For non-NIST deterministic signing, implement RFC 6979 externally using the curve's parameters.

Example fix

// before
sig, err := priv.Sign(nil, digest, crypto.SHA256) // deterministic on custom curve

// after
sig, err := priv.Sign(rand.Reader, digest, crypto.SHA256) // randomized signing works on all curves
Defensive patterns

Strategy: validation

Validate before calling

func supportsDeterministicSign(curve elliptic.Curve) bool {
    switch curve.Params() {
    case elliptic.P224().Params(), elliptic.P256().Params(),
         elliptic.P384().Params(), elliptic.P521().Params():
        return true
    }
    return false
}

Try / catch

sig, err := priv.Sign(nil, digest, opts) // deterministic
if err != nil && strings.Contains(err.Error(), "deterministic") {
    // fall back to randomized signing
    sig, err = priv.Sign(rand.Reader, digest, opts)
}

Prevention

When it happens

Trigger: Calling priv.Sign(nil, digest, opts) (deterministic mode) on a PrivateKey whose Curve is not one of the four NIST curves. The signRFC6979 switch falls through to the default case.

Common situations: Using a custom curve and requesting deterministic signing; loading keys with non-standard curves; code that generically calls Sign with nil random across different curve types.

Related errors


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