golang/go · error
tls: invalid signature by the client certificate: {err}
Error message
tls: invalid signature by the client certificate: {err} What it means
TLS 1.2 path: the server failed to verify the client's CertificateVerify signature using verifyHandshakeSignature. The client's signature over the handshake transcript does not match its certificate's public key, indicating a bad signature, wrong key, or tampered transcript.
Source
Thrown at src/crypto/tls/handshake_server.go:797
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 {
sigType, sigHash, err = legacyTypeAndHashFromPublicKey(pub)
if err != nil {
c.sendAlert(alertIllegalParameter)
return err
}
signed := hs.finishedHash.hashForClientCertificate(sigType)
if err := verifyLegacyHandshakeSignature(sigType, pub, sigHash, signed, certVerify.signature); err != nil {
c.sendAlert(alertDecryptError)
return errors.New("tls: invalid signature by the client certificate: " + err.Error())
}
}
c.peerSigAlg = certVerify.signatureAlgorithm
if err := transcriptMsg(certVerify, &hs.finishedHash); err != nil {
return errView on GitHub (pinned to b6b368adc5)
Solutions
- Verify the client is signing the exact handshake transcript hash with the private key matching its certificate's public key.
- Inspect the wrapped err (concatenated into the message) to distinguish rsa.VerifyErr from ecdsa errors.
- Check for middleboxes or proxies that alter handshake bytes — they invalidate the transcript.
- Ensure the client certificate chain is correctly generated and the key pair matches.
Example fix
// Client must sign the handshake transcript with the matching private key. // Go's tls.Config.Certificates / GetClientCertificate handle this automatically. // If implementing manual signing, sign hs.finishedHash.buffer exactly as the // server will recompute it — do not modify any handshake messages.
Defensive patterns
Strategy: try-catch
Validate before calling
// Client: verify the cert/key pair match before connecting.
if err := cert.Leaf.CheckSignatureFrom(cert.Leaf); err == nil {
// sanity: cert parses. For key match, compare public key types.
}
// More directly: sign a probe transcript and verify with the cert's public key. Try / catch
// Server: surface as an mTLS auth failure.
if err != nil && strings.Contains(err.Error(), "invalid signature by the client certificate") {
return fmt.Errorf("client signature verification failed: %w", err)
} Prevention
- Ensure client cert and private key are generated as a pair.
- Do not alter handshake bytes via proxies or middleboxes.
- Test mTLS flows against a known-good peer before deployment.
When it happens
Trigger: verifyHandshakeSignature(sigType, pub, sigHash, hs.finishedHash.buffer, certVerify.signature) returns an error — e.g. crypto/rsa verification failure, ECDSA signature invalid, or Ed25519 mismatch. Triggered when the client signs the wrong data, uses the wrong key, or the transcript diverged.
Common situations: A client signing with a different key than the one in its certificate, a transcript hash mismatch caused by a MITM altering handshake messages, a buggy signer, or corruption in transit. Also a possible attack indicator (signature forgery attempt).
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: client certificate used with invalid signature algorith
- tls: client does not support uncompressed connections
- tls: initial handshake had non-empty renegotiation extension
- tls: FIPS 140-3 requires the use of Extended Master Secret
- tls: client's Finished message is incorrect
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/3508a6de6bee4b19.
Report an issue: GitHub.