Я хочу обеспечить безопасность TLS с помощью самозаверяющего сертификата x509 для ряда существующих приложений XamarinForms, которые подключаются к брокеру mosquitto mqtt с помощью клиента M2MqttDotnetCore .
Для этого я создалпростой пример приложения чата XamarinForms для публикации / подписки, чтобы узнать, как защитить клиентское приложение XamarinForms mqtt, которое может быть надежным в этом репозитории GitHub. jhalbrecht / XamarinFormsMqttSample
У меня есть примеры в Mosquitto_pub, python и консольном приложении .net, которые позволяют успешно подключиться к брокеру Mosquitto через порт 8883 с TLS и самозаверяющим сертификатом.Приложение XamarinForms UWP также работает незащищенным и защищенным. У меня проблемы с настройкой приложения Android для работы с TLS на порту 8883 . Приложение Android работает незащищенно на порту 1883. Это журнал выполнения Visual Studio 2017
[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
То, как я сейчас загружаю и получаю доступ к сертификатам X509, небезопасно или не рекомендуется.Оно работает.Я надеюсь в конечном итоге узнать, как получить доступ к устройству с хранилищами ключей для каждой мобильной платформы.Я использую межплатформенный подключаемый модуль FilePicker для загрузки сертификата, кодирования base64 и его сохранения.
FileData fileData = await Plugin.FilePicker.CrossFilePicker.Current.PickFile();
if (fileData == null)
return; // user canceled file picking
string fileName = fileData.FileName;
string content = Convert.ToBase64String(fileData.DataArray, 0, fileData.DataArray.Length,
Base64FormattingOptions.None);
string deviceFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), fileName);
File.WriteAllText(deviceFileName, content);
Я связался с несколькими людьми из Xamarin через твиттер.У меня есть открытый выпуск в моем вышеупомянутом репозитории, в котором обсуждается проблема, по которой @baulig от Microsoft, я полагаю, дал мне ответ, однако в настоящее время я не знаю, как ее реализовать.
Я только что посмотрел код подтверждения сертификата и что он делает по существу
var certStore = KeyStore.GetInstance ("AndroidCAStore");
certStore.Load(null);
Это точка входа: https://github.com/mono/mono/blob/master/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs,он вызывает этот код https://github.com/mono/mono/blob/master/mcs/class/System/System/AndroidPlatform.cs#L101, который затем вызывает код xamarin-android
здесь: https://github.com/xamarin/xamarin-android/blob/master/src/Mono.Android/Android.Runtime/AndroidEnvironment.cs
KeyStore
должен быть таким классом: https://developer.xamarin.com/api/type/Java.Security.KeyStore/.
Так что вы должныбыть в состоянии сделать это через Java.Security.KeyStore
.
- Какие разрешения необходимо предоставить в AndroidManifest.xml?
- Какие термины я мог бы исследовать для правильного доступа к хранилищам ключей платформы?
Дополнения после первоначальной публикации
- 27 февраля,2019 (MST) 14:51
Добавлено создание сертификатов и клиента mqtt из MqttDataService.cs
X509Certificate caCert = X509Certificate.CreateFromCertFile(Path.Combine(filesDirectoryBasePath, "ca.crt"));
string thePfxPathOnDevice = Path.Combine(filesDirectoryBasePath, "xamarinclient.pfx");
string theBase64EncodedPfx = File.ReadAllText(thePfxPathOnDevice);
byte[] certificate = Convert.FromBase64String(theBase64EncodedPfx);
X509Certificate2 clientCert = new X509Certificate2(certificate, "xamarin");
_client = new MqttClient(
GetHostName(_xpdSetting.MqttBrokerAddress),
Int32.Parse(_xpdSetting.MqttBrokerTlsPort),
_xpdSetting.UseTls,
caCert,
clientCert,
MqttSslProtocols.TLSv1_2
//MyRemoteCertificateValidationCallback
);