.net 8.0 HttpClient 出现错误:“身份验证失败,因为远程方发送了 TLS 警报:HandshakeFailure”

问题描述 投票:0回答:1

我需要从 Windows Server 2008 上运行的 .net 控制台应用程序发送 https 请求(不,无法更新 :( )。应用程序发出的请求失败并出现错误:

身份验证失败,因为远程方发送了 TLS 警报:HandshakeFailure

所以我做了一些研究并成功地从应用程序中调用了curl。如果可能的话,我想避免使用curl,所以我决定尝试下载Firefox CA证书存储并将其所有证书添加到http客户端:

var caCerts = LoadCACertificates(pemFilePath);

using var httpClientHandler = new HttpClientHandler();
httpClientHandler.ClientCertificates.AddRange(caCerts);

using var httpClient = new HttpClient(httpClientHandler);

...

private static X509Certificate2Collection LoadCACertificates(string pemFilePath)
{
    var certificates = new X509Certificate2Collection();

    try
    {
        string pemContent = File.ReadAllText(pemFilePath);

        // Extract each certificate in the PEM file
        var matches = Regex.Matches(pemContent, "-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----", RegexOptions.Singleline);

        foreach (Match match in matches)
        {
            string base64Cert = match.Groups[1].Value.Replace("\r", "").Replace("\n", "");
            byte[] certBytes = Convert.FromBase64String(base64Cert);
            var certificate = new X509Certificate2(certBytes);
            certificates.Add(certificate);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error loading CA certificates: {ex.Message}");
        throw;
    }

    return certificates;
}
...

但是没有任何成功,我仍然遇到同样的错误。

请问有人有什么想法吗,为什么代码不起作用?

asp.net-core .net-core client-certificates windows-server
1个回答
0
投票
  1. 虽然握手失败的一个可能原因是当服务器要求客户端身份验证时未使用客户端证书和密钥,但只有带有私钥的证书才能成为客户端证书; 您没有也永远不会拥有 Mozilla(或任何其他明智的人)信任的任何 CA 的私钥。您是否指定了客户端证书和密钥来卷曲? 如果没有并且它没有工作,那么服务器不需要客户端身份验证; curl 从不默认客户端证书,仅使用 CA 证书的信任库来验证服务器证书——这取决于它的构建方式。

  2. 另一种可能性是协议版本。假设你不是指R2,S2008支持1.0以上的TLS版本
  3. 仅在带有补丁和注册表更改的 SP2 中

    。 SSL3在2014年被彻底破解,早已被大家禁止。 TLS 1.0 现在被认为是过时的和边缘化的,尽管还没有完全被破坏, 并且许多服务器不会接受它;几乎同样多的人也不接受 1.1。除此之外,如果网站想要接受支付卡 行业标准 (PCI DSS) 有效禁止低于 1.2 的所有内容,许多政府、监管机构和其他机构也是如此,包括 IETF 您也许可以使用curl 进行测试,具体取决于它构建为使用的库以及可能的版本。 (使用

    --tls-max

    --tls-min
    --tlsv{number}
    选项仅设置最小值而不是精确版本。) 如果您无法在有问题的机器上进行测试,请使用不同的curl构建,或从另一台机器到同一台服务器的
    openssl s_client -tls{1,1_1,1_2,1_3}
    (总是准确的)。
    
    

  4. 另一种可能性是
  5. 服务器名称指示,又名 SNI

    。 尽管定义较早,但在 2008 年 SNI 很少使用,而且我很确定 Vista 不支持它, 所以S2008至少有可能不会。我的搜索结果主要是关于 IIS 中的 SNI 支持, 这在一段时间内是一个大问题,但在客户端你并不关心这个,只关心 Schannel。 SNI 在 2010 年代变得普遍,如今大多数公共服务器都需要它, 如果没有提供,通常会给出handshake_failure。任何非古代卷曲都会发送 SNI。 可以通过指定或省略

    openssl s_client

    来使用

    -noservername
    进行测试 (1.1.1 以下的 OpenSSL 除外,您今天不太可能找到它,但如果您找到了,我会更新)。
    
    

  6. 最后一个但我认为不太可能的可能性是密码套件。有一段时间,这是 XP/S2003 上的一个问题,因为它没有实现 AES, 那个时期唯一仍然被许多当局和服务器接受的密码。 Vista(我认为 S2008)确实实现了 AES,但可以想象,您的系统由于某种原因禁用了它。 当为使用 Schannel 构建时,curl 会遵循 Windows 密码设置,但在为 OpenSSL 等其他库构建时则不会。 (你可以看到它是如何用
  7. curl -V

    大写-Vee 构建的。)

    
    

© www.soinside.com 2019 - 2024. All rights reserved.