RSA密钥对生成证书后TLS握手失败问题排查
代码存在的问题及修复方案
- 目录判断逻辑异常:仅当cert目录不存在时才会执行证书生成逻辑,若目录已存在会直接跳过生成,使用旧的无效证书。建议在判断内新增
Directory.CreateDirectory("cert")确保目录创建,或移除该判断强制生成新证书。 - 增强密钥用法OID配置错误:当前使用的
1.3.6.1.5.5.7.3.8是时间戳用途的OID,TLS服务端证书需要配置服务器身份验证对应的OID1.3.6.1.5.5.7.3.1,否则证书用途校验失败导致握手失败。 - 服务器证书缺少独立密钥对:当前服务器证书复用了根CA的RSA密钥对,不符合证书规范,部分TLS协议栈会直接拒绝这类证书。
- 服务器证书密钥用法缺失:当前仅配置了DigitalSignature、NonRepudiation标志,缺少TLS握手必需的KeyEncipherment标志,无法完成预主密钥加密校验。
- PFX导出未携带私钥:生成的serverCert仅包含公钥证书,未绑定对应私钥,导出的PFX文件无法被服务端用于握手阶段的密钥解密。
修正后代码
private void GenerateCertificate() { // 确保cert目录存在 if (!Directory.Exists("cert")) { Directory.CreateDirectory("cert"); } // 生成根CA独立密钥对 using RSA rootRsa = RSA.Create(2048); CertificateRequest rootRequest = new CertificateRequest("CN=localhost", rootRsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); rootRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true)); rootRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(rootRequest.PublicKey, false)); using X509Certificate2 rootCert = rootRequest.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-45), DateTimeOffset.UtcNow.AddDays(365)); // 导出客户端信任的根证书 File.WriteAllText("cert\\certificate.crt", new string(PemEncoding.Write("CERTIFICATE", rootCert.Export(X509ContentType.Cert)))); // 生成服务器独立密钥对 using RSA serverRsa = RSA.Create(2048); CertificateRequest serverRequest = new CertificateRequest("CN=localhost", serverRsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); serverRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false)); // 补全密钥用法,新增KeyEncipherment serverRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation | X509KeyUsageFlags.KeyEncipherment, false)); // 修改为服务端身份验证OID serverRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension( new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, true)); serverRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(serverRequest.PublicKey, false)); using X509Certificate2 signedServerCert = serverRequest.Create(rootCert, DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(90), new byte[] { 1, 2, 3, 4 }); // 给服务器证书绑定私钥 using X509Certificate2 serverCertWithKey = signedServerCert.CopyWithPrivateKey(serverRsa); // 导出带私钥的PFX文件 File.WriteAllBytes("cert\\server.pfx", serverCertWithKey.Export(X509ContentType.Pfx)); }
内容的提问来源于stack exchange,提问作者Meme Machine
相关产品推荐
相关产品推荐

