golang/go · error

connection doesn't support Ed25519

Error message

connection doesn't support Ed25519

What it means

A server certificate uses an Ed25519 public key, but the client connection cannot use Ed25519 for signing. TLS permits Ed25519 only from TLS 1.2 onward and requires the client to advertise at least one signature scheme in its ClientHello (signature_algorithms extension). If either precondition fails, the certificate is rejected as incompatible with the connection.

Source

Thrown at src/crypto/tls/common.go:1504

			case elliptic.P521():
				curve = CurveP521
			default:
				return supportsRSAFallback(unsupportedCertificateError(c))
			}
			var curveOk bool
			for _, c := range chi.SupportedCurves {
				if c == curve && config.supportsCurve(vers, c) {
					curveOk = true
					break
				}
			}
			if !curveOk {
				return errors.New("client doesn't support certificate curve")
			}
			ecdsaCipherSuite = true
		case ed25519.PublicKey:
			if vers < VersionTLS12 || len(chi.SignatureSchemes) == 0 {
				return errors.New("connection doesn't support Ed25519")
			}
			ecdsaCipherSuite = true
		case *mldsa.PublicKey:
			// ML-DSA requires TLS 1.3, which we already excluded above.
			return errors.New("connection doesn't support ML-DSA")
		case *rsa.PublicKey:
		default:
			return supportsRSAFallback(unsupportedCertificateError(c))
		}
	} else {
		return supportsRSAFallback(unsupportedCertificateError(c))
	}

	// Make sure that there is a mutually supported cipher suite that works with
	// this certificate. Cipher suite selection will then apply the logic in
	// reverse to pick it. See also serverHandshakeState.cipherSuiteOk.
	cipherSuite := selectCipherSuite(chi.CipherSuites, config.supportedCipherSuites(), func(c *cipherSuite) bool {
		if c.flags&suiteECDHE == 0 {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Upgrade the negotiated TLS version to at least 1.2 (set MinVersion to tls.VersionTLS12 on the client config)
  2. Ensure the client advertises signature schemes — use a standard tls.Config rather than a hand-built ClientHello; if customizing, populate SignatureSchemes with ed25519 values
  3. Replace the server certificate's Ed25519 key with an ECDSA/RSA key compatible with the client's capabilities

Example fix

// before: client MinVersion left at default TLS 1.0
cfg := &tls.Config{ /* MinVersion unset */ }
// after
cfg := &tls.Config{MinVersion: tls.VersionTLS12}
Defensive patterns

Strategy: validation

Validate before calling

// Before offering the cert, check compatibility
func ed25519Compatible(vers uint16, sigSchemes []tls.SignatureScheme) bool {
    if vers < tls.VersionTLS12 || len(sigSchemes) == 0 {
        return false
    }
    for _, s := range sigSchemes {
        if s == tls.PSSWithSHA256 /* etc */ || s == 0x0807 /* ed25519 */ {
            return true
        }
    }
    return false
}

Type guard

func isEd25519Cert(c *tls.Certificate) bool {
    pub, ok := c.PrivateKey.(crypto.Signer)
    return ok && reflect.TypeOf(pub.Public()) == reflect.TypeOf(ed25519.PublicKey{})
}

Try / catch

if _, err := cfg.BuildTLSConfig(); err != nil {
    var unsupported interface{ Unwrap() error }
    _ = unsupported
}

Prevention

When it happens

Trigger: serverCapabilitiesOfCertificate / supportsCertificate evaluates a *Certificate whose leaf public key is ed25519.PublicKey, while vers < VersionTLS12 OR len(chi.SignatureSchemes) == 0.

Common situations: Configuring a TLS 1.0/1.1-only client against an Ed25519 certificate; a legacy/bespoke client that omits the signature_algorithms extension; a server with an Ed25519 leaf cert being matched to a very old or minimal ClientHello.

Related errors


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