Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to install trusted CA certificate on Android device?

People also ask

Where are CA certificates in Android?

Android stores CA certificates in its Java keystore in /system/etc/security/cacerts.


Prior to Android KitKat you have to root your device to install new certificates.

From Android KitKat (4.0) up to Nougat (7.0) it's possible and easy. I was able to install the Charles Web Debbuging Proxy cert on my un-rooted device and successfully sniff SSL traffic.

Extract from http://wiki.cacert.org/FAQ/ImportRootCert

Before Android version 4.0, with Android version Gingerbread & Froyo, there was a single read-only file ( /system/etc/security/cacerts.bks ) containing the trust store with all the CA ('system') certificates trusted by default on Android. Both system apps and all applications developed with the Android SDK use this. Use these instructions on installing CAcert certificates on Android Gingerbread, Froyo, ...

Starting from Android 4.0 (Android ICS/'Ice Cream Sandwich', Android 4.3 'Jelly Bean' & Android 4.4 'KitKat'), system trusted certificates are on the (read-only) system partition in the folder '/system/etc/security/' as individual files. However, users can now easily add their own 'user' certificates which will be stored in '/data/misc/keychain/certs-added'.

System-installed certificates can be managed on the Android device in the Settings -> Security -> Certificates -> 'System'-section, whereas the user trusted certificates are manged in the 'User'-section there. When using user trusted certificates, Android will force the user of the Android device to implement additional safety measures: the use of a PIN-code, a pattern-lock or a password to unlock the device are mandatory when user-supplied certificates are used.

Installing CAcert certificates as 'user trusted'-certificates is very easy. Installing new certificates as 'system trusted'-certificates requires more work (and requires root access), but it has the advantage of avoiding the Android lockscreen requirement.

From Android N onwards it gets a littler harder, see this extract from the Charles proxy website:

As of Android N, you need to add configuration to your app in order to have it trust the SSL certificates generated by Charles SSL Proxying. This means that you can only use SSL Proxying with apps that you control.

In order to configure your app to trust Charles, you need to add a Network Security Configuration File to your app. This file can override the system default, enabling your app to trust user installed CA certificates (e.g. the Charles Root Certificate). You can specify that this only applies in debug builds of your application, so that production builds use the default trust profile.

Add a file res/xml/network_security_config.xml to your app:

<network-security-config>    
    <debug-overrides> 
        <trust-anchors> 
            <!-- Trust user added CAs while debuggable only -->
            <certificates src="user" /> 
        </trust-anchors>    
    </debug-overrides>  
</network-security-config>

Then add a reference to this file in your app's manifest, as follows:

<?xml version="1.0" encoding="utf-8"?> 
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config">
    </application> 
</manifest>

I spent a lot of time trying to find an answer to this (I need Android to see StartSSL certificates). Conclusion: Android 2.1 and 2.2 allow you to import certificates, but only for use with WiFi and VPN. There is no user interface for updating the list of trusted root certificates, but there is discussion about adding that feature. It’s unclear whether there is a reliable workaround for manually updating and replacing the cacerts.bks file.

Details and links: http://www.mcbsys.com/techblog/2010/12/android-certificates/. In that post, see the link to Android bug 11231--you might want to add your vote and query to that bug.


If you need your certificate for HTTPS connections you can add the .bks file as a raw resource to your application and extend DefaultHttpConnection so your certificates are used for HTTPS connections.

public class MyHttpClient extends DefaultHttpClient {

    private Resources _resources;

    public MyHttpClient(Resources resources) {
        _resources = resources;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));
        if (_resources != null) {
            registry.register(new Scheme("https", newSslSocketFactory(), 443));
        } else {
            registry.register(new Scheme("https", SSLSocketFactory
                .getSocketFactory(), 443));
        }
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = _resources.openRawResource(R.raw.mystore);
            try {
                trusted.load(in, "pwd".toCharArray());
            } finally {
                in.close();
            }
            return new SSLSocketFactory(trusted);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

The guide linked here will probably answer the original question without the need for programming a custom SSL connector.

Found a very detailed how-to guide on importing root certificates that actually steps you through installing trusted CA certificates on different versions of Android devices (among other devices).

Basically you'll need to:

  1. Download: the cacerts.bks file from your phone.

    adb pull /system/etc/security/cacerts.bks cacerts.bks

  2. Download the .crt file from the certifying authority you want to allow.

  3. Modify the cacerts.bks file on your computer using the BouncyCastle Provider

  4. Upload the cacerts.bks file back to your phone and reboot.

Here is a more detailed step by step to update earlier android phones: How to update HTTPS security certificate authority keystore on pre-android-4.0 device


There is a MUCH easier solution to this than posted here, or in related threads. If you are using a webview (as I am), you can achieve this by executing a JAVASCRIPT function within it. If you are not using a webview, you might want to create a hidden one for this purpose. Here's a function that works in just about any browser (or webview) to kickoff ca installation (generally through the shared os cert repository, including on a Droid). It uses a nice trick with iFrames. Just pass the url to a .crt file to this function:

function installTrustedRootCert( rootCertUrl ){
    id = "rootCertInstaller";
    iframe = document.getElementById( id );
    if( iframe != null ) document.body.removeChild( iframe );
    iframe = document.createElement( "iframe" );
    iframe.id = id;
    iframe.style.display = "none";
    document.body.appendChild( iframe );
    iframe.src = rootCertUrl;
}

UPDATE:

The iframe trick works on Droids with API 19 and up, but older versions of the webview won't work like this. The general idea still works though - just download/open the file with a webview and then let the os take over. This may be an easier and more universal solution (in the actual java now):

 public static void installTrustedRootCert( final String certAddress ){
     WebView certWebView = new WebView( instance_ );
     certWebView.loadUrl( certAddress );
 }

Note that instance_ is a reference to the Activity. This works perfectly if you know the url to the cert. In my case, however, I resolve that dynamically with the server side software. I had to add a fair amount of additional code to intercept a redirection url and call this in a manner which did not cause a crash based on a threading complication, but I won't add all that confusion here...


If you have a rooted device, you can use a Magisk Module to move User Certs to System so it will be Trusted Certificate

https://github.com/Magisk-Modules-Repo/movecert