【问题标题】:SSL Communication with Client Certificate using Xamarin Android使用 Xamarin Android 与客户端证书进行 SSL 通信
【发布时间】:2020-02-14 11:11:45
【问题描述】:

我正在创建一个企业应用程序,其中组织的 MDM 解决方案将在设备上安装客户端证书。我使用下面的代码来阅读相同的内容,但我的连接没有与服务器建立。

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();
}   

我正在使用下面的代码来读取私钥和证书。

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;

}

我也通过使用 OnReceivedClientCertRequest 传递证书和密钥对 WebView 进行了同样的尝试,并且工作正常。

 public override void OnReceivedClientCertRequest(WebView view, ClientCertRequest request)
 {
     request.Proceed(PPritvateKey, CCertificate);
 }

请您帮忙找出我的代码有什么问题。

【问题讨论】:

    标签: android ssl xamarin.android client-certificates x509certificate2


    【解决方案1】:

    您尚未配置信任管理器工厂以及影响请求调用的实习生。试试这个

    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();
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用URLConnection.Connect Method() 打开与资源的连接。

      urlConnection.Connect();
      

      更多信息,请参考以下链接。

      URLConnection.Connect 方法: https://docs.microsoft.com/en-us/dotnet/api/java.net.urlconnection.connect?view=xamarin-android-sdk-9#Java_Net_URLConnection_Connect

      URL.openConnection 示例: https://csharp.hotexamples.com/examples/-/URL/openConnection/php-url-openconnection-method-examples.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-11
        • 2014-04-04
        • 2014-06-07
        • 2019-07-04
        • 1970-01-01
        • 2012-08-25
        • 1970-01-01
        相关资源
        最近更新 更多