【问题标题】:What might cause System.Net Error:AcquireCredentialsHandle() failed with error 0X8009030D?什么可能导致 System.Net 错误:AcquireCredentialsHandle() 失败并出现错误 0X8009030D?
【发布时间】:2018-05-24 11:47:35
【问题描述】:

我有一段简单的 https 连接代码,可以很好地与一个 ssl 主机配合使用,即使根证书颁发机构不受信任(这是一个沙盒环境,所以我们并不担心这会造成安全漏洞,因为现在),并使用 Nuget 包 OpenSSL.X509Certificate2Provider 从文本文件加载证书和密钥:

    public async Task<string> Register()
    {
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;

        using (var handler = new HttpClientHandler())
        {
            var rawcert = File.ReadAllText(@"C:\OpenSSL\bin\certTransport.pem");
            var rawkey = File.ReadAllText(@"C:\OpenSSL\bin\privateKeyTransport.key");

            var provider = new CertificateFromFileProvider(rawcert, rawkey);
            var cert = provider.Certificate;
            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ServerCertificateCustomValidationCallback +=
                (HttpRequestMessage req, X509Certificate2 cert2, X509Chain chain, SslPolicyErrors err) =>
                {
                    return true;
                };

            handler.ClientCertificates.Add(cert);

            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = new Uri("https://{uri}/");
                var response = await client.GetStringAsync("register");
                return response;
            }
        }
    }

当我将此代码指向另一个应该以完全相同的方式保护的主机时,我收到以下错误: System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.

深入研究日志,我发现: System.Net Information: 0 : [35036] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential) System.Net Error: 0 : [35036] AcquireCredentialsHandle() failed with error 0X8009030D.

为此搜索堆栈,我发现许多与证书存储权限相关的错误,但在这种情况下,客户端证书并未从存储中加载。

我还发现许多与 SecurityProtocolType 相关的问题。我已验证服务器正在使用 Tls1.2(仅)。

我从 VS 2017 Enterprise 中的单元测试调用代码,该代码在 Win10 x64 上以管理权限运行。该代码包含在 .Net 4.7 类库中,而不是托管在 IIS 中。

什么可能导致这个问题?

更新 在下面@Jeroen Mostert 有用的 cmets 之后,我尝试了使用 OpenSSL 的基本连接测试。稍微匿名的结果:

OpenSSL> s_client -connect {REMOVED}:443 -CAfile C:\OpenSSL\bin\archive-ii\transport-production-new\certTransport.pem
CONNECTED(000001F0)
depth=2 C = GB, O = OK, CN = {REMOVED} Root CA
verify error:num=19:self signed certificate in certificate chain
---
Certificate chain
0 s:/C=GB/O={REMOVED}/OU={REMOVED}/CN={REMOVED}
i:/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
1 s:/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
i:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
2 s:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
i:/C=GB/O={REMOVED}/CN={REMOVED} Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
{REMOVED}
-----END CERTIFICATE-----
subject=/C=GB/O={REMOVED}/OU={REMOVED}/CN={REMOVED}
issuer=/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
---
Acceptable client certificate CA names
/C=GB/O={REMOVED}/CN={REMOVED} Issuing CA
/C=GB/O={REMOVED}/CN={REMOVED} Root CA
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms:     RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5155 bytes and written 446 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID:
    Session-ID-ctx:
    Master-Key: {REMOVED}
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1527164830
    Timeout   : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
---

有什么问题吗?

我还查看了 CAPI2 日志(如 cmets 中所建议的那样)。这显示了与不受信任的根证书相关的错误,如下所示:

这是否意味着我的验证回调不起作用 - 如果是这样,知道为什么会这样吗?

进一步更新:

如果我删除了附加证书的代码行,那么错误就会消失 - 我通过了 MTLS 测试端点(当然,在那里进行的 MTLS 测试失败了)。

这说明了什么?证书本身有问题?

【问题讨论】:

  • FWIW,0x8009030D 是 SEC_E_UNKNOWN_CREDENTIALS,“提供给包的凭据未被识别”,由 AcquireCredentialsHandle 返回。这应该发生在实际证书验证发生之前(我认为);它基本上意味着该函数不喜欢SCHANNEL_CRED 中的内容,这可能是.NET 提供的内容与Schannel 配置为在该服务器上支持的内容之间存在差异。并不是说这会让找到根本原因变得容易得多。
  • 我在那里看到了 OpenSSL——您可以考虑使用 openssl s_client 来验证基础知识,您的证书是否可以与服务器一起使用(以及握手期间发生的确切情况,看看是否有明显的差异在主机 X 和 Y 之间,这可以解释为什么 .NET 可能会失败)。
  • 感谢@JeroenMostert - 请参阅上面的更新。
  • 是工作主机还是故障主机的连接测试?理想情况下,你会比较两者。
  • 您或许可以使用 CAPI2 日志。如果启用此功能,所有在 Windows 中完成的 TLS/SSL 握手都会被记录。解释如何做到这一点有点复杂,但我找到了一篇包含一些信息的博客文章:blogs.msdn.microsoft.com/saurabs/2016/10/27/…

标签: c# ssl x509certificate dotnet-httpclient tls1.2


【解决方案1】:

这里的问题最终出在OpenSSL.X509Certificate2Provider NuGet 包的CertificateFromFileProvider 方法的输出上。

无论出于何种原因,创建的证书都无法正常工作。获取相同的输入文件并生成带有OpenSSL.pfx 会生成一个运行良好的X509Certificate2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多