Xamarin Android:具有自定义证书颁发机构证书验证的本机TLS,ClientWebSocket失败 [英] Xamarin Android: Native TLS, ClientWebSocket, with Custom Certificate Authority Certificate Validation Fails

查看:127
本文介绍了Xamarin Android:具有自定义证书颁发机构证书验证的本机TLS,ClientWebSocket失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

客户端环境是Xamarin Android本机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.

Client Environment is Xamarin Android Native TLS 1.2 SSL/TLS implementation (boringssl aka btls), using System.Net.WebSockets.ClientWebSocket. This is running on an Android 7.0 device. Visual Studio 2017 15.8.1, Xamarin.Android 9.0.0.18.

服务器环境是运行Fleck(WebSocket服务器)的Windows .NET 4.7,其使用由自制的证书颁发机构(CA)颁发的证书(配置为TLS 1.2)配置为TLS 1.2.

Server Environment is Windows .NET 4.7 running Fleck (WebSocket server) configured with TLS 1.2 using a certificate issued by a homemade (non-trusted anywhere on the globe) Certificate Authority (CA).

假设已通过设置"->安全性"->从SD卡安装"在Android设备上安装了自制CA Cert(.pem或.cer格式),则ClientWebSocket可以使用TLS 1.2正常连接,就像人们期望的那样.由于这是针对本地(我的应用程序的一部分)问题的全局解决方案,更不用说为更大的设备生态系统打开安全漏洞了,所以我不希望进行此设置.

Assuming a homemade CA Cert (.pem or .cer format) has been installed on the android device via Settings->Security->Install from SD Card, the ClientWebSocket connects using TLS 1.2 without problems, as one would expect. Since this is a global solution to a local (one part of my app) problem, not to mention opening a security hole for the larger device ecosystem, I do not wish to require this setup.

然后,我尝试了几种方法来将CA的信任仅限于我的应用程序,但是没有成功.无论采用哪种方法,ClientWebSocket.ConnectAsync()始终会引发相同的异常:对SSPI的调用失败 Ssl错误:1000007d:SSL例程:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED位于/Users/builder/jenkins/workspace/xamarin-android-d15-8/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:1132

I have then tried several methods to localize the trust of the CA to only my application without success. Regardless of approach, there is always the same exception thrown by ClientWebSocket.ConnectAsync(): A call to SSPI failed and Ssl 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

我创建了一个示例Windows服务器和控制台应用程序以及Xamarin.Forms Android应用程序,以演示该问题.并尝试解决该问题,如下所述.包括自定义CA证书.服务器代码动态地发布带有绑定到您的IP/主机名的SAN的客户端证书,以便于复制.

I created a sample windows server and console app and Xamarin.Forms Android app that demonstrates the issue and the attempts to workaround it described below. Included is a custom CA cert. The server code dynamically issues a client cert with SANs bound to your IP/hostnames for ease of repro.

应用 android:networkSecurityConfig ="@ xml/network_security_config" AndroidManifest.xml文件中的application元素的属性,包括资源 Resources \ raw \ sample_ca.pem Resources \ xml \ network_security_config.xml

Apply the android:networkSecurityConfig="@xml/network_security_config" attribute to the application element in the AndroidManifest.xml file, including resources 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>

这没有明显的效果,我在调试输出中看不到任何表明运行时甚至正在加载它的内容.我已经看到的引用://stackstackflow.com/questions/41365334/networksecurityconfig-no-network-security-config-specified-android-7-0-error/41365406#41365406>消息,如下所示:

This had no visible effect, and I cannot see anything in the debug output that would indicate that the runtime is even loading this. I have seen references to messages like this:

D/NetworkSecurityConfig: No Network Security Config specified, using platform default

但是,无论有没有此设置,我都从未见过类似或类似的消息.我真的不知道它是否被应用,或者btls实现甚至使用/尊重它.

However, with or without this in place I have never seen messages like this or similar. I really have no idea if it is being applied or not, or if btls implementation even uses/respects this.

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

Interestingly, since the Android minSdk is set to 24 and target sdk of 27 I would expect the lack of this declaration should cause TLS 1.2 to not work if I simply added the CA to the android device user certificate store. I suspect there are a few Xamarin bugs surrounding this.

将CA添加到X509存储,希望btls将其用作证书的来源.这种方法在Windows/.NET 4上有效(确实会弹出一个对话框,以接受证书的添加).

Add the CA to the X509 Store, hoping btls uses that as a source of certificates. This approach works on Windows/.NET 4 (it does bring up a dialog to accept the addition of the certificate).

        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上有效.

Attempt 3:

Handle ServerCertificateValidationCallback. This never gets called in Xamarin Android, but this approach works on 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;
};

一些

There are some Mono issues surrounding btls and a pull request that makes this approach look possible in the near future.

将CA证书(和/或从CA发行的证书)添加到

Add the CA cert (and/or the cert issued from the CA) to the ClientWebSocket.Options ClientCertificates collection. Technically this should not work with CA Certs but should be the approach to use with self-signed certificates. I offer it here merely for completeness. As expected, it does not work either.

易于使用的代码通过上述所有尝试的变通办法演示了此问题,请参见可在GitHub上获得.

Easy to use code that demonstrates this issue with all of the attempted workarounds described above is available on GitHub.

推荐答案

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

I don't know, what the problem was, but I also had some problems, as I have started with my first https webservices. The reason was, that I have started with a self signed certificate, what does not work without ugly workarounds... So.. only use signed (trusted) certificates from a public vendor and you should not have any problem... To switch between http and https you only have to change the url (from http to https) - no further changes in the app ae needed. I normally do first (local) tests with the web service with http (the url ist loaded from an .ini file) and then copy the web service to the "real" webserver (with certificate and https url). I never had any problems (when a trusted certificate is used)...

这篇关于Xamarin Android:具有自定义证书颁发机构证书验证的本机TLS,ClientWebSocket失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆