Reputation: 1401
I am creating an enterprise application, in which the Organization's MDM solution will install a client certificate on the device. I tied to read the same using the below code but my connection is not get established with the server.
if (x is X509Certificate[] certificates && y is IPrivateKey privateKey)
{
var keyStore = KeyStore.GetInstance("PKCS12");
keyStore.Load(null, null);
var keyFactory = KeyFactory.GetInstance(privateKey?.Algorithm);
keyStore.SetKeyEntry(alias, privateKey, null, certificates);
var kmf = KeyManagerFactory.GetInstance(KeyManagerFactory.DefaultAlgorithm);
kmf.Init(keyStore, null);
var sslContext = SSLContext.GetInstance("TLS");
sslContext.Init(kmf.GetKeyManagers(), null, null);
var sslSocketFactory = sslContext.SocketFactory;
var sslSocket = (SSLSocket)sslSocketFactory.CreateSocket(new Socket(hostName, port), hostName, port, false);
sslSocket.AddHandshakeCompletedListener(new HandshakeCompletedListener());
sslSocket.NeedClientAuth = true;
sslSocket.KeepAlive = true;
sslSocket.StartHandshake();
var uri = new URL("https://apiapp-iserver.ase-meap-dev.p.azurewebsites.net/api/CertificateLogin");
var urlConnection = (HttpsURLConnection)uri.OpenConnection();
var status = urlConnection.ResponseCode;
if (status == HttpStatus.Forbidden)
{
var errorStream = urlConnection.ErrorStream;
var errorResult = ReadStream(errorStream);
}
urlConnection.SSLSocketFactory = sslContext.SocketFactory;
var inputStream = urlConnection.InputStream;
var loResponseStream = new StreamReader(inputStream);
var response = loResponseStream.ReadToEnd();
}
I am using the below code to read the private key and certificate.
private X509Certificate[] GetCertificates(string alias)
{
try
{
return KeyChain.GetCertificateChain(RootActivity, alias);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return null;
}
private IPrivateKey GetPrivateKey(string alias)
{
try
{
return KeyChain.GetPrivateKey(RootActivity, alias);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return null;
}
I also tried the same with WebView by passing the certificate and key with OnReceivedClientCertRequest and which is working fine.
public override void OnReceivedClientCertRequest(WebView view, ClientCertRequest request)
{
request.Proceed(PPritvateKey, CCertificate);
}
Could you please help to figure out what is wrong in my code.
Upvotes: 1
Views: 1068
Reputation: 1785
You haven't configured the trust manager factory and which intern affecting the request call. Try this
if (x is X509Certificate[] certificates && y is IPrivateKey privateKey)
{
var keyStore = KeyStore.GetInstance("PKCS12");
keyStore.Load(null, null);
var keyFactory = KeyFactory.GetInstance(privateKey?.Algorithm);
keyStore.SetKeyEntry(alias, privateKey, null, certificates);
var kmf = KeyManagerFactory.GetInstance(KeyManagerFactory.DefaultAlgorithm);
kmf.Init(keyStore, null);
KeyStore serverKeysStore = KeyStore.GetInstance("AndroidCAStore");
serverKeysStore.Load(null, null);
var serverTrustManagerFactory = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
serverTrustManagerFactory.Init(serverKeysStore);
var tms = serverTrustManagerFactory.GetTrustManagers();
var sslContext = SSLContext.GetInstance("TLS");
sslContext.Init(kmf.GetKeyManagers(), serverTrustManagerFactory.GetTrustManagers(), new SecureRandom());
HttpsURLConnection.DefaultSSLSocketFactory = sslContext.SocketFactory;
var sslSocketFactory = sslContext.SocketFactory;
var sslSocket = (SSLSocket)sslSocketFactory.CreateSocket(new Socket(hostName, port), hostName, port, false);
sslSocket.AddHandshakeCompletedListener(new HandshakeCompletedListener());
sslSocket.NeedClientAuth = true;
sslSocket.KeepAlive = true;
sslSocket.StartHandshake();
var uri = new URL("https://apiapp-iserver.ase-meap-dev.p.azurewebsites.net/api/CertificateLogin");
var urlConnection = (HttpsURLConnection)uri.OpenConnection();
var status = urlConnection.ResponseCode;
if (status == HttpStatus.Forbidden)
{
var errorStream = urlConnection.ErrorStream;
var errorResult = ReadStream(errorStream);
}
urlConnection.SSLSocketFactory = sslContext.SocketFactory;
var inputStream = urlConnection.InputStream;
var loResponseStream = new StreamReader(inputStream);
var response = loResponseStream.ReadToEnd();
}
Upvotes: 1
Reputation: 10938
You could use URLConnection.Connect Method()
to open a connection to the resource.
urlConnection.Connect();
For more information, please refer to the link below.
URLConnection.Connect Method: https://learn.microsoft.com/en-us/dotnet/api/java.net.urlconnection.connect?view=xamarin-android-sdk-9#Java_Net_URLConnection_Connect
URL.openConnection Examples: https://csharp.hotexamples.com/examples/-/URL/openConnection/php-url-openconnection-method-examples.html
Upvotes: 1