Ssl 访问XamarinForms中的自签名X509证书,以便mqtt TLS连接到MOSQUITO代理
我希望使用自签名x509certificate对使用客户端连接到MOSQUITO mqtt代理的许多现有XamarinForms应用程序进行TLS保护 为此,我创建了一个简单的示例XamarinForms发布/订阅聊天应用程序,以了解如何保护XamarinForms mqtt客户端应用程序,该应用程序可以在GitHub存储库中正常运行 我在Mosquitto_pub、python和.net控制台应用程序中有一些示例,它们实现了通过端口8883通过TLS和自签名证书成功连接到Mosquitto代理的目标。XamarinForms UWP应用程序也可以不安全和安全地工作我在让Android应用程序与端口8883上的TLS一起工作时遇到问题,Android应用程序确实在端口1883上工作。这是Visual Studio 2017的运行时日志Ssl 访问XamarinForms中的自签名X509证书,以便mqtt TLS连接到MOSQUITO代理,ssl,xamarin,xamarin.forms,mqtt,mosquitto,Ssl,Xamarin,Xamarin.forms,Mqtt,Mosquitto,我希望使用自签名x509certificate对使用客户端连接到MOSQUITO mqtt代理的许多现有XamarinForms应用程序进行TLS保护 为此,我创建了一个简单的示例XamarinForms发布/订阅聊天应用程序,以了解如何保护XamarinForms mqtt客户端应用程序,该应用程序可以在GitHub存储库中正常运行 我在Mosquitto_pub、python和.net控制台应用程序中有一些示例,它们实现了通过端口8883通过TLS和自签名证书成功连接到Mosquitto代理
[0:] M2Mqtt.Exceptions.MqttConnectionException: Exception connecting to the broker ---> System.AggregateException: One or more errors occurred. ---> System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Ssl error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
at /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:1132
at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status) [0x0003e] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus)
at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
at Mono.Net.Security.AsyncProtocolRequest+<ProcessOperation>d__24.MoveNext () [0x000ff] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of stack trace from previous location where exception was thrown ---
at Mono.Net.Security.AsyncProtocolRequest+<StartOperation>d__23.MoveNext () [0x0008b] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of inner exception stack trace ---
at Mono.Net.Security.MobileAuthenticatedStream+<ProcessAuthentication>d__47.MoveNext () [0x00254] in <fb6d78e506844b3b96d5b35aa047fbbd>:0
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) [0x00011] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Wait (System.Int32 millisecondsTimeout, System.Threading.CancellationToken cancellationToken) [0x00043] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Wait () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at M2Mqtt.Net.MqttNetworkChannel.Connect () [0x000a8] in <72fbe921f857483bafbb8b397ec98dd1>:0
at M2Mqtt.MqttClient.Connect (System.String clientId, System.String username, System.String password, System.Boolean willRetain, System.Byte willQosLevel, System.Boolean willFlag, System.String willTopic, System.String willMessage, System.Boolean cleanSession, System.UInt16 keepAlivePeriod) [0x0001e] in <72fbe921f857483bafbb8b397ec98dd1>:0
--- End of inner exception stack trace ---
at M2Mqtt.MqttClient.Connect (System.String clientId, System.String username, System.String password, System.Boolean willRetain, System.Byte willQosLevel, System.Boolean willFlag, System.String willTopic, System.String willMessage, System.Boolean cleanSession, System.UInt16 keepAlivePeriod) [0x00037] in <72fbe921f857483bafbb8b397ec98dd1>:0
at M2Mqtt.MqttClient.Connect (System.String clientId) [0x00000] in <72fbe921f857483bafbb8b397ec98dd1>:0
at MqttDataServices.Services.MqttDataService+<Initialize>d__5.MoveNext () [0x00266] in C:\jstuff\MqttSample\MqttDataServices\Services\MqttDataService.cs:183
我通过推特联系了一些Xamarin人。我在上面提到的存储库中有一篇文章讨论了这个问题,我相信微软的@baulig给了我答案,但我目前不知道如何实现它
我只是查看了证书验证代码,它的作用是
本质上
var certStore=KeyStore.GetInstance(“AndroidCAStore”);
加载(空)代码>
这是切入点:
,
它调用这个代码
然后在这里调用xamarin android的code:
密钥库应为此类:
因此,您应该能够通过Java.Security.KeyStore
实现这一点
- 在AndroidManifest.xml中需要授予哪些权限李>
- 我可以研究哪些术语来正确访问平台ca密钥库
首次发布后添加的内容
- 2019年2月27日(MST)下午2:51
从中添加了证书和mqtt客户端创建
X509Certificate caCert=X509Certificate.CreateFromCertFile(Path.Combine(fileDirectoryBasePath,“ca.crt”);
字符串thepfxppathondevice=Path.Combine(filedirectorybasepath,“xamarinclient.pfx”);
字符串base64encodedpfx=File.ReadAllText(Thepfxpxpath设备);
byte[]certificate=Convert.FromBase64String(base64encodedpfx);
X509Certificate2客户端证书=新的X509Certificate2(证书,“xamarin”);
_client=新的MqttClient(
GetHostName(_xpdSetting.MqttBrokerAddress),
Parse(_xpdSetting.MqttBrokerTlsPort),
_xpdSetting.UseTls,
卡塞特,
客户证书,
MqttSslProtocols.TLSv1_2
//MyRemoteCertificateValidationCallback
);
由于您使用的是.Net的/MonoSocket
(通过M2MqttDotnetCore),只需使用证书固定,您只需处理RemoteCertificateValidationCallback
。这样就不会弄乱Android的可信商店等等
Android上的SslStream使用情况:
注意:Android上的SslStream
存在问题,对象分配可能会变得疯狂。。。我相信(?)这是一个悬而未决的问题。(为了解决这个问题,我不得不多次使用Java的SSLSocket)
启用本机TLS 1.2+
- 通过Android项目构建选项使用BoringSSL
将您的证书添加到Android的资产目录:
- 这是您的cert/.pem文件(不是您的密钥!!)
- 确保这是一个没有unicode BOM表头的ascii文件
- 通过openssl示例(只需将其更改为您的主机和安全端口)
RemoteCertificateValidationCallback实现
注意:以下代码可以在NetStd2.0或Xamarin.Android中使用
x509c证书;过度插入;//类级变量
bool CertificateValidation(对象发送方、X509证书证书、X509链、SslPolicyErrors证书错误)
{
if(overpert==null)
{
//据我所知,OpenAppPackageFileAsync(通过Xamarin.Essential)没有非异步版本@SushiHangover我在原始问题中添加了证书和mqtt客户机代码。
├── Assets
│ └── sushihangover.cert
echo -n | openssl s_client -connect 10.1.10.250:5001 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'