Xamarin.Android Http客户端,允许我从KeyStore添加客户端证书

时间:2019-03-07 11:56:26

标签: c# android xamarin.android certificate x509certificate

我正在尝试添加通过这种方法获得的客户端证书信息:

    private X509Certificate[] GetCertificateChain(string alias)
    {
        try
        {
            return KeyChain.GetCertificateChain(this, alias);
        }
        catch (KeyChainException e)
        {

        }            

        return null;
    }

System.Net.Http.HttpClientHandler不允许我添加客户端证书。引发NotImplemented异常。有什么办法吗?也许其他Http客户端?

1 个答案:

答案 0 :(得分:1)

您需要扩展AndroidClientHandler并覆盖ConfigureCustomSSLSocketFactory

public class HttpsClientHandler : AndroidClientHandler
{
    private static readonly Logger LOG = LogManager.GetLogger();

    private SSLContext sslContext;
    private readonly ITrustManager[] trustManagers;
    private IKeyManager[] keyManagers = null;

    public HttpsClientHandler() : base()
    {
        trustManagers = GetTrustManagers();
        sslContext = GetSSLContext();
    }

    private SSLContext GetSSLContext()
    {
        string protocol;
        if (SslProtocols == SslProtocols.Tls11)
        {
            protocol = "TLSv1.1";
        } else if (SslProtocols == SslProtocols.Tls || SslProtocols == SslProtocols.Tls12)
        {
            protocol = "TLSv1.2";
        } else
        {
            throw new IOException("unsupported ssl protocol: " + SslProtocols.ToString());
        }
        SSLContext ctx = SSLContext.GetInstance(protocol);
        ctx.Init(keyManagers, trustManagers, null);
        return ctx;
    }

    public new SslProtocols SslProtocols { get; set; } = SslProtocols.Tls12;

    public void SetClientCertificate(byte[] pkcs12, char[] password)
    {
        keyManagers = GetKeyManagersFromClientCert(pkcs12, password);
        SSLContext newContext = GetSSLContext();
        sslContext = newContext;
    }

    private ITrustManager[] GetTrustManagers()
    {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
        trustManagerFactory.Init((KeyStore)null);
        return trustManagerFactory.GetTrustManagers();
    }

    private IKeyManager[] GetKeyManagersFromClientCert(byte[] pkcs12, char[] password)
    {
        if (pkcs12 != null)
        {
            using (MemoryStream memoryStream = new MemoryStream(pkcs12))
            {
                KeyStore keyStore = KeyStore.GetInstance("pkcs12");
                keyStore.Load(memoryStream, password);
                KeyManagerFactory kmf = KeyManagerFactory.GetInstance("x509");
                kmf.Init(keyStore, password);
                return kmf.GetKeyManagers();
            }
        }
        return null;
    }

    protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
    {
        SSLSocketFactory socketFactory = sslContext.SocketFactory;
        if (connection != null)
        {
            connection.SSLSocketFactory = socketFactory;
        }
        return socketFactory;
    }
}