Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Central Keystore

I'm hoping that there's a way to programmatically access a central trusted keystore on an Android device. I know one exists, at least for verifying SSL connections etc. which also comes with a handy tool for adding certificates, browsing, etc. (Found under settings->location & security->manage trusted certificates)

I'd like to be able to programmatically retrieve public keys from it for the purpose of encrypting files etc.

Given the documentation available, it seems like other app developers are managing their own keystore within their app, which seems redundant.

Any ideas?

like image 752
Nick Avatar asked Aug 09 '11 20:08

Nick


2 Answers

ICS (Android 4.0 / API 14) introduced the TrustedCertificateStore (not directly available in the SDK) that enables you to do exactly that. You can access it using the JCA Keystore api like this:

/**
 * Android Central Keystore repo usually located on /data/misc/keychain 
 * including the system trusted anchors located on /system/etc/security
 */
KeyStore keyStore = KetStore.getInstance("AndroidCAStore");
keyStore.load(null, null); //Load default system keystore
Enumeration<String> keyAliases = keyStore.aliases();

while(keyAliases.hasMoreElements()){
    String alias = keyAliases.nextElement();
    X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);

    //<User cert in whatever way you want>
}
like image 39
Chepech Avatar answered Oct 07 '22 15:10

Chepech


This is not supported, may break in future versions, etc., but here's how to get a list of the trusted certificates. You cannot add new ones without root access, because /system is mounted read-only. But if you do have root access, you can use the regular KeyStore API's to add certificates.

KeyStore ks = KeyStore.getInstance("BKS");
InputStream is = new FileInputStream("/etc/security/cacerts.bks");
ks.load(is, "changeit".toCharArray());

List<X509Certificate> certs = new ArrayList<X509Certificate>();
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
  String alias = aliases.nextElement();
  X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
  certs.add(cert);
}

EDIT: This should work with needing to hardcode the path to the keystore:

TrustManagerFactory tmf = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
X509TrustManager xtm = (X509TrustManager) tmf.getTrustManagers()[0];
for (X509Certificate cert : xtm.getAcceptedIssuers()) {
    String certStr = "S:" + cert.getSubjectDN().getName() + "\nI:"
                        + cert.getIssuerDN().getName();
    Log.d(TAG, certStr);
}
like image 73
Nikolay Elenkov Avatar answered Oct 07 '22 15:10

Nikolay Elenkov