{"record":{"id":"26a4f90a79836919","repo":"golang/go","slug":"tls-client-certificate-used-with-invalid-signatur-26a4f9","errorCode":null,"errorMessage":"tls: client certificate used with invalid signature algorithm","messagePattern":"tls: client certificate used with invalid signature algorithm","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_server_tls13.go","lineNumber":1091,"sourceCode":"\t\t// this message was sent is used.\n\t\tmsg, err = c.readHandshake(nil)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tcertVerify, ok := msg.(*certificateVerifyMsg)\n\t\tif !ok {\n\t\t\tc.sendAlert(alertUnexpectedMessage)\n\t\t\treturn unexpectedMessageError(certVerify, msg)\n\t\t}\n\n\t\t// See RFC 8446, Section 4.4.3.\n\t\t// We don't use certReq.supportedSignatureAlgorithms because it would\n\t\t// require keeping the certificateRequestMsgTLS13 around in the hs.\n\t\tif !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms(c.vers, c.vers)) ||\n\t\t\t!isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, signatureSchemesForPublicKey(c.vers, c.peerCertificates[0].PublicKey)) {\n\t\t\tc.sendAlert(alertIllegalParameter)\n\t\t\treturn errors.New(\"tls: client certificate used with invalid signature algorithm\")\n\t\t}\n\t\tsigType, sigHash, err := typeAndHashFromSignatureScheme(certVerify.signatureAlgorithm)\n\t\tif err != nil {\n\t\t\treturn c.sendAlert(alertInternalError)\n\t\t}\n\t\tif sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 {\n\t\t\treturn c.sendAlert(alertInternalError)\n\t\t}\n\t\tsigned := signedMessage(clientSignatureContext, hs.transcript)\n\t\tif err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey,\n\t\t\tsigHash, signed, certVerify.signature); err != nil {\n\t\t\tc.sendAlert(alertDecryptError)\n\t\t\treturn errors.New(\"tls: invalid signature by the client certificate: \" + err.Error())\n\t\t}\n\t\tc.peerSigAlg = certVerify.signatureAlgorithm\n\n\t\tif err := transcriptMsg(certVerify, hs.transcript); err != nil {\n\t\t\treturn err","sourceCodeStart":1073,"sourceCodeEnd":1109,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_server_tls13.go#L1073-L1109","documentation":"During mutual TLS (mTLS) client certificate verification, the client's CertificateVerify message specified a signature algorithm that the server doesn't support. The check uses two filters: (1) the algorithm must be in the server's supportedSignatureAlgorithms list for the negotiated version, and (2) it must be compatible with the client certificate's public key type via signatureSchemesForPublicKey. Additionally, PKCS#1 v1.5 and SHA-1 are explicitly rejected afterward. This is defined in RFC 8446 Section 4.4.3.","triggerScenarios":"Server requested client certificates (mTLS). Client sent a CertificateVerify with a signature algorithm not in the server's supported list, or one incompatible with the client cert's key type. For example: client uses an Ed25519 cert but claims ecdsa_secp256r1_sha256; or client uses a legacy algorithm the server no longer accepts.","commonSituations":"Client cert key type (e.g. Ed25519, RSA-PSS) doesn't match the claimed signature algorithm; client library forces a deprecated algorithm (SHA-1 or PKCS#1 v1.5); version mismatch between client and server signature algorithm policies; client cert generated with an unusual key type the server's signatureSchemesForPublicKey doesn't recognize.","solutions":["Ensure the client cert's signature algorithm matches its public key type (RSA key uses RSA-PSS, ECDSA key uses ECDSA, Ed25519 uses ed25519).","Verify the client TLS library sends signature algorithms from the server's CertificateRequest supported_signature_algorithms list.","Regenerate client certificate if its key type is incompatible with the negotiated algorithms.","Update the client TLS library to one that correctly implements RFC 8446 §4.4.3 signature algorithm selection."],"exampleFix":"// Ensure client cert key type matches signature algorithm\n// before: RSA cert but client sends ed25519 sig alg\n// after: client cert uses ECDSA P-256, sends ecdsa_secp256r1_sha256\n//\n// Generate proper client cert:\n// openssl ecparam -genkey -name prime256v1 -out client.key\n// openssl req -new -x509 -key client.key -out client.crt","handlingStrategy":"validation","validationCode":"// Client-side: verify signature algorithm is compatible with cert key type\nfunc validateCertSigAlg(pubKey crypto.PublicKey, sigAlg SignatureScheme) error {\n    schemes := signatureSchemesForPublicKey(tls.VersionTLS13, pubKey)\n    for _, s := range schemes {\n        if s == sigAlg {\n            return nil\n        }\n    }\n    return fmt.Errorf(\"signature algorithm %v not compatible with public key type\", sigAlg)\n}","typeGuard":null,"tryCatchPattern":"// Server-side: handle during client cert verification\nif err := conn.Handshake(); err != nil {\n    if strings.Contains(err.Error(), \"invalid signature algorithm\") {\n        log.Printf(\"client cert used unsupported signature algorithm: %v\", err)\n    }\n}","preventionTips":["Ensure client certificate key type matches the signature algorithms it uses.","Configure the server's ClientAuth and acceptable signature algorithms consistently.","Test mTLS with certificates that use standard key types (RSA-PSS, ECDSA, Ed25519)."],"tags":["tls","tls13","mtls","client-certificate","signature-algorithm","server-side"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}