Xamarin Android : Native TLS, ClientWebSocket,自定义证书颁发机构证书验证失败

标签 xamarin xamarin.android tls1.2 client-certificates x509certificate2

客户端环境是 Xamarin Android Native TLS 1.2 SSL/TLS 实现(boringssl aka btls),使用 System.Net.WebSockets.ClientWebSocket。这是在 Android 7.0 设备上运行的。 Visual Studio 2017 15.8.1,Xamarin.Android 9.0.0.18。

服务器环境是运行 Fleck(WebSocket 服务器)的 Windows .NET 4.7,使用由自制(全局任何地方不受信任)证书颁发机构 (CA) 颁发的证书配置了 TLS 1.2。

假设已通过设置->安全->从 SD 卡安装在 android 设备上安装了自制 CA 证书(.pem 或 .cer 格式),则 ClientWebSocket 使用 TLS 1.2 连接没有问题,正如预期的那样。由于这是针对本地(我的应用程序的一部分)问题的全局解决方案,更不用说为更大的设备生态系统打开安全漏洞,我不希望需要此设置。

然后,我尝试了几种方法将 CA 的信任本地化到仅我的应用程序,但没有成功。无论采用何种方法,ClientWebSocket.ConnectAsync() 总会抛出相同的异常:A call to SSPI failedSsl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED at /Users/builder/jenkins/workspace/xamarin-android-d15-8/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:1132
我创建了一个 sample windows server and console app and Xamarin.Forms Android app这说明了该问题以及下文所述的解决方法。包括一个自定义 CA 证书。服务器代码动态发布客户端证书,其中 SAN 绑定(bind)到您的 IP/主机名,以便于重现。

尝试1:

Apply the android:networkSecurityConfig="@xml/network_security_config" attribute to the application element in the AndroidManifest.xml file ,包括资源 Resources\raw\sample_ca.pem Resources\xml\network_security_config.xml

<?xml version="1.0" encoding="utf-8" ?>
<network-security-config>
  <base-config>
    <trust-anchors>
      <certificates src="@raw/sample_ca"/>
      <certificates src="system"/>
      <certificates src="user"/>
    </trust-anchors>
  </base-config>
</network-security-config>

这没有明显的效果,我在调试输出中看不到任何表明运行时甚至正在加载它的东西。我看过referencesmessages像这样:
D/NetworkSecurityConfig: No Network Security Config specified, using platform default

然而,不管有没有这个,我从来没有见过这样或类似的消息。我真的不知道它是否被应用,或者 btls 实现是否甚至使用/尊重它。

有趣的是,由于 Android minSdk 设置为 24,目标 sdk 设置为 27,如果我只是将 CA 添加到 android 设备用户证书存储区,我预计缺少此声明会导致 TLS 1.2 无法工作。我怀疑周围有一些 Xamarin 错误。

尝试2:

将 CA 添加到 X509 存储,希望 btls 将其用作证书来源。这种方法适用于 Windows/.NET 4(它会弹出一个对话框来接受证书的添加)。
        X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadWrite);
        var certs = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false);
        if (certs.Count == 0)
            store.Add(cert);
        store.Close();

尝试 3:

拉手ServerCertificateValidationCallback .这在 Xamarin Android 中永远不会被调用,但这种方法适用于 Windows/.NET 4。
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) =>
{
    if (errors == SslPolicyErrors.None)
        return true;    
    //BUGBUG: Obviously there should be a much more extensive check here.
    if (certificate.Issuer == caCert.Issuer)
        return true;    
    return false;
};

some Mono围绕 btls 和 pull request 的问题这使得这种方法在不久的将来成为可能。

尝试4:

将 CA 证书(和/或 CA 颁发的证书)添加到 ClientWebSocket.Options ClientCertificates 集合。从技术上讲,这不应该与 CA 证书一起使用,但应该是与自签名证书一起使用的方法。我在这里提供它只是为了完整性。正如预期的那样,它也不起作用。

完整的复制代码

available on GitHub 易于使用的代码通过上述所有尝试的变通方法演示了此问题.

最佳答案

我不知道问题是什么,但我也遇到了一些问题,因为我从我的第一个 https 网络服务开始。
原因是,我从一个自签名证书开始,如果没有丑陋的解决方法,什么是行不通的......
所以..只使用来自公共(public)供应商的签名(可信)证书,你应该没有任何问题......
要在 http 和 https 之间切换,您只需更改 url(从 http 到 https) - 无需在应用程序 ae 中进行进一步更改。
我通常首先使用 http (从 .ini 文件加载的 url )对 Web 服务进行(本地)测试,然后将 Web 服务复制到“真实”网络服务器(使用证书和 https url)。
我从来没有遇到过任何问题(当使用受信任的证书时)......

关于Xamarin Android : Native TLS, ClientWebSocket,自定义证书颁发机构证书验证失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51967177/

相关文章:

ios - 发布到 Apple 商店时遇到问题

android - Forms.Context 已过时,那么我应该如何获取单个 Activity 应用程序的 Activity ?

c# - Xamarin Android 工具栏如何动态添加项目

android - Xamarin 执行 logcat 命令并将结果读取到字符串

xamarin - 如何在 xamarin android 上播放音频?

mysql - 将 tls1.2 与 python 3.5 和 mysql 服务器一起使用

ssl - ios9 自签名证书和应用程序传输安全

c# - Xamarin.Forms 中的框架边框宽度

c# - Android 警报管理器未在指定时间触发

c# - 由于 SSL 握手异常,.NET Core 3.0 上的 WebRequest 第二次失败