zdenek
zdenek

Reputation: 24398

How to load a certificate from "Credential storage"?

My network code is written in NDK (cURL + OpenSSL) and I'd like to use a certificate from Android's credential storage as a client certificate for a SSL connection. Moreover, I'd like to offer a list of available certificates to the user, so he can choose the certificate for the connection. Unfortunately, I cannot obtain a certificate from the key storage.

I installed a client certificate to "Credential storage" (Settings -> Secutrity -> ...) on my Android device (5.0.2), but I'm not able to access it from Java. I tried to call following code, but the key storage is empy, athough the certificate is installed in the Credential storage:

//KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);

Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()) {
    String alias = (String)aliases.nextElement();
    Log.i("app", "alias name: " + alias);
    Certificate certificate = ks.getCertificate(alias);
    Log.i("app", certificate.toString());
}

What am I doing wrong?

Upvotes: 4

Views: 1703

Answers (2)

pedrofb
pedrofb

Reputation: 39271

User credentials installed on the device are available through Android KeyChain, not Android KeyStore

The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage.

Use choosePrivateKeyAlias ​​to prompt the user for selecting the certificate. The system launches an Activity for the user to select the alias and returns it via a callback. Then use getPrivateKey and getCertificate to recover the key and the corresponding certificate chain

KeyChain.choosePrivateKeyAlias(activity, new KeyChainAliasCallback() {
            public void alias(String alias) {               
                //do something with the selected alias                      
            }               
        },
        new String[] { KeyProperties.KEY_ALGORITHM_RSA, "DSA"}, // List of acceptable key types. null for any
        null,                        // issuer, null for any
        null,                        // host name of server requesting the cert, null if unavailable
        -1,                          // port of server requesting the cert, -1 if unavailable
        "");                         // alias to preselect, null if unavailable

PrivateKey privateKey = KeyChain.getPrivateKey(activity, alias);
X509Certificate chain[] = KeyChain.getCertificateChain(activity, alias);

Upvotes: 3

Deep Lathia
Deep Lathia

Reputation: 760

Try something like this:

X509TrustManager manager = null;
FileInputStream fs = null;

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

try
{
    fs = new FileInputStream(System.getProperty("javax.net.ssl.trustStore")); 
    keyStore.load(fs, null);
}
finally
{
    if (fs != null) { fs.close(); }
}

trustManagerFactory.init(keyStore);
TrustManager[] managers = trustManagerFactory.getTrustManagers();

for (TrustManager tm : managers)
{
    if (tm instanceof X509TrustManager) 
    {
        manager = (X509TrustManager) tm;
        break;
    }
}

Upvotes: -1

Related Questions