简体   繁体   English

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

[英].NET dropping client certificate over TLS 1.2

Hello it seems some form of this question has been asked a million different ways but many don't have answers, or the answers don't apply to me.您好,似乎有人以一百万种不同的方式询问了这个问题的某种形式,但许多人没有答案,或者答案不适用于我。

We have a trivial little .NET service that calls out to a 3rd party API that is only supporting TLS 1.2 now.我们有一个微不足道的小 .NET 服务,它调用现在只支持 TLS 1.2 的 3rd 方 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;

When I explicitly set the security protocol to 1.2, or target a framework that defaults to 1.2, the client certificate is not part of the packet that goes to the server.当我将安全协议显式设置为 1.2 或针对默认为 1.2 的框架时,客户端证书不是发送到服务器的数据包的一部分。 I've examined it in Wireshark and the certs are never present over 1.2.我已经在 Wireshark 中检查过它并且证书从未超过 1.2。 At that point the server sends the Fatal Alert Handshake Failure (40) which results in the following .Net exception:此时,服务器发送致命警报握手失败 (40),导致以下 .Net 异常:

The request was aborted: Could not create SSL/TLS secure channel.

I can make the same call through Chrome or Postman (native) and it works fine.我可以通过 Chrome 或 Postman(本机)拨打相同的电话,并且工作正常。 If I set the protocol down to 1.1 it works fine.如果我将协议设置为 1.1,它就可以正常工作。 But if I run it as 1.2 through .NET it fails every time.但是如果我通过 .NET 作为 1.2 运行它,它每次都会失败。 I get the same exact error and same traffic in Wireshark even if I purposely do not add my client certificate at all.即使我故意不添加我的客户端证书,我也会在 Wireshark 中得到完全相同的错误和相同的流量。

I ran the 3rd party endpoint through https://www.ssllabs.com/ and it grades out fine.我通过https://www.ssllabs.com/运行了 3rd 方端点,结果很好。 There are no MD5 signatures anywhere that I can see on either side.我在任何一侧都看不到 MD5 签名。 Everything is signed with sha1 or sha256 with RSA encryption.一切都用 sha1 或 sha256 签名,并使用 RSA 加密。

I have tracing enabled.我启用了跟踪。 The following output seems to indicate there is no issue finding the certificate or its private key:以下输出似乎表明找到证书或其私钥没有问题:

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).

I also have SCHANNEL event logging turned on.我还打开了 SCHANNEL 事件日志记录。 There I can see it picking up the client cert with the private key.在那里我可以看到它使用私钥获取客户端证书。

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.

Followed by the error that corresponds to the Alert packet in Wireshark:其次是Wireshark中Alert包对应的错误:

A fatal alert was received from the remote endpoint. The TLS protocol defined fatal alert code is 40.

I am completely out of ideas.我完全没有想法。 It feels like a bug in .Net.感觉就像 .Net 中的一个错误。 We thought for a moment that it was an incomplete trust chain with our client certificate, because our cert package only had the client cert and an intermediate CA.我们想了一会儿,这是一个不完整的与我们的客户端证书的信任链,因为我们的证书包只有客户端证书和一个中间 CA。 But we got the Root CA from the vendor and now Windows says the cert is legit.但是我们从供应商那里获得了根 CA,现在 Windows 说证书是合法的。

One interesting thing I notice in Wireshark is that we send the client cert AND the intermediate CA on successful calls.我在 Wireshark 中注意到的一件有趣的事情是,我们在成功调用时发送客户端证书和中间 CA。 I don't know how it's picking up the intermediate CA because I only pull in the client cert to attach to the request.我不知道它是如何获取中间 CA 的,因为我只提取客户端证书以附加到请求。 Why wouldn't it also submit the root CA once we had it?一旦我们拥有它,为什么它不也提交根 CA? My gut tells me the problem may still lie in here somewhere but I can't prove it.我的直觉告诉我问题可能仍然存在于此,但我无法证明。 There is nothing in any logs anywhere that indicate a trust chain failure.任何日志中都没有任何内容表明信任链失败。

I've even hooked up ProcMon as well to see if I could see anything amiss but nothing jumped out.我什至还连接了 ProcMon,看看我是否能看到任何错误但没有跳出。 Man I could have rewritten the whole thing in Java in the amount of time I've spent on this.伙计,我本可以用我花在这上面的时间用 Java 重写整个事情。

Some other things I have tried that didn't work:我尝试过的其他一些不起作用的事情:

targeting .Net 4.8针对 .Net 4.8

machine store vs user store机器存储与用户存储

loading directly from the pfx instead直接从 pfx 加载

HttpWebRequest instead of HttpClient HttpWebRequest 而不是 HttpClient

TcpClient with SslStream带有 SslStream 的 TcpClient

newer Windows 10 release较新的 Windows 10 版本

EDIT I just read something that says SHA-1 signatures were also removed from TLS 1.2 along with MD5.编辑我刚刚读到一些说 SHA-1 签名也从 TLS 1.2 和 MD5 中删除的内容。 Our client cert is signed in SHA-1.我们的客户证书在 SHA-1 中签名。 I think this might be it and we are contacting our vendor.我认为可能就是这样,我们正在联系我们的供应商。

My problem and my solution ultimately ended up being the same as this one.我的问题和我的解决方案最终与这个相同。 The only difference is that my client cert was SHA1 not MD5.唯一的区别是我的客户端证书是 SHA1 而不是 MD5。 .NET is clearly dropping SHA1 certificates as well. .NET 显然也在放弃 SHA1 证书。

C# and dotnet 4.7.1 not adding custom certificate for TLS 1.2 calls C# 和 dotnet 4.7.1 没有为 TLS 1.2 调用添加自定义证书

This article gave me the clue, because other posts indicated that SHA1 was still accepted.这篇文章给了我线索,因为其他帖子表明SHA1仍然被接受。 My SHA1 certs still worked outside of .NET.我的 SHA1 证书在 .NET 之外仍然有效。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM