golang/go · error

tls: client certificate used with invalid signature algorith

Error message

tls: client certificate used with invalid signature algorithm

What it means

The client's CertificateVerify message used a signature algorithm that the server did not advertise in its CertificateRequest. TLS 1.2+ requires the client to pick from the server's supported_signature_algorithms list; picking outside it is illegal_parameter.

Source

Thrown at src/crypto/tls/handshake_server.go:781

		// certificateVerifyMsg is included in the transcript, but not until
		// after we verify the handshake signature, since the state before
		// this message was sent is used.
		msg, err = c.readHandshake(nil)
		if err != nil {
			return err
		}
		certVerify, ok := msg.(*certificateVerifyMsg)
		if !ok {
			c.sendAlert(alertUnexpectedMessage)
			return unexpectedMessageError(certVerify, msg)
		}

		var sigType uint8
		var sigHash crypto.Hash
		if c.vers >= VersionTLS12 {
			if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, certReq.supportedSignatureAlgorithms) {
				c.sendAlert(alertIllegalParameter)
				return errors.New("tls: client certificate used with invalid signature algorithm")
			}
			sigType, sigHash, err = typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm)
			if err != nil {
				return c.sendAlert(alertInternalError)
			}
			if sigHash == crypto.SHA1 {
				tlssha1.Value() // ensure godebug is initialized
				tlssha1.IncNonDefault()
			}
			if hs.finishedHash.buffer == nil {
				c.sendAlert(alertInternalError)
				return errors.New("tls: internal error: did not keep handshake transcript for TLS 1.2")
			}
			if err := verifyHandshakeSignature(sigType, pub, sigHash, hs.finishedHash.buffer, certVerify.signature); err != nil {
				c.sendAlert(alertDecryptError)
				return errors.New("tls: invalid signature by the client certificate: " + err.Error())
			}
		} else {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Ensure the client signs CertificateVerify with one of the algorithms the server advertised in its CertificateRequest.
  2. On the server side, broaden supported signature algorithms if interoperability with the client is required.
  3. Update the client TLS stack — modern libraries pick from the server's list automatically.
  4. Verify the client certificate's key type supports the algorithm being requested.

Example fix

// Server: ensure the algorithm list matches what legitimate clients can use
cfg := &tls.Config{
    ClientAuth: tls.RequireAndVerifyClientCert,
    // Go selects supported algorithms automatically; do not over-restrict.
}

// Client: use a current TLS library — Go picks from server's list.
// Custom signing code must honor certReq.supportedSignatureAlgorithms.
Defensive patterns

Strategy: validation

Validate before calling

// Client: pick a signature algorithm from the server's CertificateRequest
// list. Go's standard machinery does this automatically.
// For manual signers, intersect supported algorithms with the server list.

Try / catch

// Server: broaden supported algorithms if interoperability is required,
// or log which algorithm the client mis-used.
if err != nil && strings.Contains(err.Error(), "invalid signature algorithm") {
    log.Warn("client used unadvertised signature algorithm",
        "remote", conn.RemoteAddr())
}

Prevention

When it happens

Trigger: In the TLS 1.2 client-cert path, isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, certReq.supportedSignatureAlgorithms) returned false. The client signed with e.g. RSA-PKCS1-SHA1 when the server only offered SHA256+.

Common situations: A client library defaulting to a weak or legacy signature algorithm (SHA1, MD5) against a hardened server, mismatched signature algorithm support between client and server policy, or a misconfigured client cert whose key only supports certain algorithms.

Understand the failure class

Related errors


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