.NET 通过 TLS 1.2 删除客户端证书

标签 .net ssl tls1.2 client-certificates

您好,似乎这个问题的某种形式已经被问了一百万种不同的方式,但很多都没有答案,或者答案不适用于我。

我们有一个微不足道的小 .NET 服务,它调用现在仅支持 TLS 1.2 的第 3 方 API。

        var requestHandler = new WebRequestHandler();
        var clientCert = GetClientCert("THUMBPRINT");

        requestHandler.ClientCertificates.Add(clientCert);
        var encodedHeader = "FOO";
        var httpClient = new HttpClient(requestHandler) { BaseAddress = new Uri("https://foo.bar.com/rest/api/") };
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedHeader);

        var httpResponse = httpClient.GetAsync("").Result;
        var responseContent = httpResponse.Content.ReadAsStringAsync().Result;

当我将安全协议(protocol)显式设置为 1.2 或针对默认为 1.2 的框架时,客户端证书不是发送到服务器的数据包的一部分。我已经在 Wireshark 中对其进行了检查,并且证书从未超过 1.2。此时,服务器发送致命警报握手失败 (40),导致以下 .Net 异常:
The request was aborted: Could not create SSL/TLS secure channel.

我可以通过 Chrome 或 Postman( native )调用同样的电话,而且效果很好。如果我将协议(protocol)设置为 1.1,它可以正常工作。但是,如果我通过 .NET 将它作为 1.2 运行,它每次都会失败。即使我故意根本不添加我的客户端证书,我也会在 Wireshark 中得到相同的错误和相同的流量。

我通过 https://www.ssllabs.com/ 运行了第 3 方端点它的成绩很好。我在任何一侧都看不到任何 MD5 签名。一切都使用 sha1 或 sha256 进行签名,并使用 RSA 加密。

我启用了跟踪。以下输出似乎表明找到证书或其私钥没有问题:
System.Net Information: 0 : [19512] SecureChannel#41622463 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [19512] SecureChannel#41622463::.AcquireClientCredentials, new SecureCredential() (flags=(ValidateManual, NoDefaultCred, SendAuxRecord, UseStrongCrypto), m_ProtocolFlags=(Zero), m_EncryptionPolicy=RequireEncryption)
System.Net Information: 0 : [19512] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent  = Outbound, scc     = System.Net.SecureCredential)
System.Net Information: 0 : [19512] InitializeSecurityContext(credential = 
System.Net.SafeFreeCredential_SECURITY, context = 1ed7465db80:1f1d854c910, targetName = foo.bar.com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [19512] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=133, returned code=ContinueNeeded).

我还打开了 SCHANNEL 事件记录。在那里我可以看到它使用私钥获取客户端证书。
The TLS client credential's private key has the following properties:

   CSP name: Microsoft Enhanced Cryptographic Provider v1.0
   CSP type: 1
   Key name: {some hex here}
   Key Type: key exchange
   Key Flags: 0x0

 The attached data contains the certificate.

接着是Wireshark中Alert包对应的错误:
A fatal alert was received from the remote endpoint. The TLS protocol defined fatal alert code is 40.

我完全没有想法。感觉就像 .Net 中的一个错误。我们一度认为这是一个不完整的客户端证书信任链,因为我们的证书包只有客户端证书和一个中间 CA。但是我们从供应商那里得到了根 CA,现在 Windows 说证书是合法的。

我在 Wireshark 中注意到的一件有趣的事情是,我们会在成功调用时发送客户端证书和中间 CA。我不知道它是如何获取中间 CA 的,因为我只拉入客户端证书以附加到请求。为什么它不提交根 CA 呢?我的直觉告诉我问题可能仍然存在于此,但我无法证明这一点。任何日志中都没有任何内容表明信任链失败。

我什至还连接了 ProcMon,看看我是否能发现任何问题,但没有任何问题。伙计,我本可以在我花在这上面的时间里用 Java 重写整个事情。

我尝试过的其他一些无效的方法:

针对.Net 4.8

机器商店与用户商店

而是直接从 pfx 加载

HttpWebRequest 而不是 HttpClient

带有 SslStream 的 TcpClient

较新的 Windows 10 版本

编辑
我刚刚读到一些内容,说 SHA-1 签名也与 MD5 一起从 TLS 1.2 中删除。我们的客户证书使用 SHA-1 签名。我想可能是这样,我们正在联系我们的供应商。

最佳答案

我的问题和我的解决方案最终与这个相同。唯一的区别是我的客户端证书是 SHA1 而不是 MD5。 .NET 显然也放弃了 SHA1 证书。

C# and dotnet 4.7.1 not adding custom certificate for TLS 1.2 calls

这篇文章给了我线索,因为其他帖子表明SHA1仍然被接受。我的 SHA1 证书在 .NET 之外仍然有效。

https://tools.ietf.org/id/draft-ietf-tls-md5-sha1-deprecate-00.html

关于.NET 通过 TLS 1.2 删除客户端证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59777145/

相关文章:

node.js - 强制 nodemailer 仅使用推荐的密码执行 TLS 1.2

c# - 在 C#.Net Winform 应用程序和 SQL Server 2008 中使用 TLS 1.2

c# - 使用新的 WCF Web API 设置 Ninject

.net - 通过互联网连接套接字失败

ssl - Varnish 3 : "Expected return action name" when using "synth"

javax.net.ssl.SSLException : java. lang.RuntimeException:无法生成 DH key 对

c# - 将 gRPC 服务绑定(bind)到 aspnetcore 中的特定端口

c# - 使用 LINQ 将数据插入到使用序列作为主键生成器的表中

java - Java Apache httpclient调用https服务是否需要Server证书?

node.js - 如何使用node.js和express.js为网站启用TLS和https请求?