客户端环境是 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。
服务器环境是 Windows .NET 4.7,运行 Fleck(WebSocket 服务器),配置了 TLS 1.2,使用自制(全球任何地方不受信任)证书颁发机构 (CA) 颁发的证书。
假设已通过“设置”->“安全”->“从 SD 卡安装”在 Android 设备上安装了自制的 CA 证书(.pem 或 .cer 格式),则 ClientWebSocket 使用 TLS 1.2 进行连接,正如人们所期望的那样,没有任何问题。由于这是针对本地(我的应用程序的一部分)问题的全局解决方案,更不用说为更大的设备生态系统打开安全漏洞,因此我不希望需要此设置。
然后,我尝试了多种方法将 CA 的信任本地化到仅我的应用程序,但没有成功。无论采用哪种方法,ClientWebSocket.ConnectAsync() 总是会抛出相同的异常A call to SSPI failed: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 证书。服务器代码动态颁发客户端证书,其中 SAN 绑定到您的 IP/主机名,以便于重现。
将android:networkSecurityConfig="@xml/network_security_config"属性应用于 AndroidManifest.xml 文件中的应用程序元素,包括资源Resources\raw\sample_ca.pem …
client-certificates x509certificate2 xamarin.android xamarin tls1.2