You can use the certificate previously installed in the Android KeyChain (system key store) extending the X509ExtendedKeyManager to configure the SSLContext used by URLConnection
The certificate is referenced by the alias you need. To request the user to select with a dialog similar to using chrome:
KeyChain.choosePrivateKeyAlias(this, this, // Callback new String[] {"RSA", "DSA"}, // Any key types. null, // Any issuers. null, // Any host -1, // Any port DEFAULT_ALIAS);
This is the code for setting up an SSL connection using a custom KeyManager . It uses the default values โโof TrustManager and HostnameVerifier . You will need to configure them if the server uses a self-signed certificate that is not in the default supermarket for Android (it is not recommended to trust all certificates)
//Configure trustManager if needed TrustManager[] trustManagers = null; //Configure keyManager to select the private key and the certificate chain from KeyChain KeyManager keyManager = KeyChainKeyManager.fromAlias( context, mClientCertAlias); //Configure SSLContext SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(new KeyManager[] {keyManager}, trustManagers, null); //Perform the connection URL url = new URL( versionUrl ); HttpsURLConnection urlConnection = ( HttpsURLConnection ) url.openConnection(); urlConnection.setSSLSocketFactory(sslContext.getSocketFactory()); //urlConnection.setHostnameVerifier(hostnameVerifier); //Configure hostnameVerifier if needed urlConnection.setConnectTimeout( 10000 ); InputStream in = urlConnection.getInputStream();
Finally, you have the full implementation of the custom X509ExtendedKeyManager extracted from here and here , which is responsible for selecting the client certificate. I extracted the required code.
public static class KeyChainKeyManager extends X509ExtendedKeyManager { private final String mClientAlias; private final X509Certificate[] mCertificateChain; private final PrivateKey mPrivateKey; public static KeyChainKeyManager fromAlias(Context context, String alias) throws CertificateException { X509Certificate[] certificateChain; try { certificateChain = KeyChain.getCertificateChain(context, alias); } catch (KeyChainException e) { throw new CertificateException(e); } catch (InterruptedException e) { throw new CertificateException(e); } PrivateKey privateKey; try { privateKey = KeyChain.getPrivateKey(context, alias); } catch (KeyChainException e) { throw new CertificateException(e); } catch (InterruptedException e) { throw new CertificateException(e); } if (certificateChain == null || privateKey == null) { throw new CertificateException("Can't access certificate from keystore"); } return new KeyChainKeyManager(alias, certificateChain, privateKey); } private KeyChainKeyManager( String clientAlias, X509Certificate[] certificateChain, PrivateKey privateKey) { mClientAlias = clientAlias; mCertificateChain = certificateChain; mPrivateKey = privateKey; } @Override public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) { return mClientAlias; } @Override public X509Certificate[] getCertificateChain(String alias) { return mCertificateChain; } @Override public PrivateKey getPrivateKey(String alias) { return mPrivateKey; } @Override public final String chooseServerAlias( String keyType, Principal[] issuers, Socket socket) {
I have not tested. Report any error!