Make sure you are setting the SSL/TLS Implementation to Native TLS 1.2+
so BoringSsl
is used vs. Mono's managed TLS. If the managed implementation is used, your client will only negotiate 1.1.

var _clientSocket = new TcpClient();
using (var _stream = new SslStream(_clientSocket.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidation)))
{
await _stream.AuthenticateAsClientAsync(host, null, SslProtocols.Tls12, false);
// do something with your stream
// FYI: Bug/Issue with Xamarin.Android, the following always return `None`
Log.Debug(TAG, $"CipherAlgorithm: {_stream.CipherAlgorithm.ToString()}");
Log.Debug(TAG, $"KeyExchangeAlgorithm: {_stream.KeyExchangeAlgorithm.ToString()}");
Log.Debug(TAG, $"HashAlgorithm: {_stream.HashAlgorithm.ToString()}");
// The following are not implemented in Xamarin Mobile, tagged as "Need to Implement"
// Mobile CipherStrength = NotImplementedException
// Mobile KeyExchangeStrength = NotImplementedException
// Mobile HashStrength = NotImplementedException
}
- Handling
RemoteCertificateChainErrors
In order to handle the RemoteCertificateChainErrors
on the Self-Signed cert, you can provide a custom RemoteCertificateValidationCallback
, while you can just provide a true
, you should actually check that the correct server/cert is provided but adding it to the TrustManager would be the preferred/secure way...
static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors certificateErrors)
{
Console.WriteLine("CertificateValidation");
Console.WriteLine(certificate.ToString(true));
Console.WriteLine("Chain");
Console.WriteLine(chain);
Console.WriteLine("\tError(s)");
Console.WriteLine(certificateErrors);
Console.WriteLine();
return true;
}
Update:
Manual setting via .csproj
(or xbuild/msbuild
), within the PropertyGroup
for release/debug you can add:
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<AndroidTlsProvider>btls</AndroidTlsProvider>