Search code examples
androidkotlinandroid-network-security-config

Network security config android


I am setting android app network security config as described in Andoid official doc. I have got certificate as .pem file from sever devops people and stored in res/raw as cert. this is my network config file

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain
            cleartextTrafficPermitted="false"
            includeSubdomains="true">my.domain.com</domain>
        <trust-anchors>
            <certificates src="@raw/cert" />
            <certificates src="system"/> // WHEN I REMOVE IT , GIVES Exception
        </trust-anchors>
    </domain-config>
    <base-config cleartextTrafficPermitted="false" />
</network-security-config>

When i remove <certificates src="system"/> it gives SSL handshake exception. Is adding this line is safe ? But without this line it gives SSL Handshake exception.Can you please tell this is the right way of doing it and what this actually mean as i could not find proper explanation inthe official doc.

Here is the exception

HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Solution

  • When you access a normal HTTPS websites you have 3 certificates in the chain:

    1. root CA
    2. intermediate CA
    3. end-user certificate

    3 is signed by 2 and 2 is signed by 1. You can view these certificates in any browser (Firefox/Chrome/Edge/Opera/...).

    The Android OS provides (as also Linux or Windows) a list of trusted root CAs. You can even view them in the settings. They are about ~150 on my device. Microsoft has one and also Google.

    So your app can simply trust any certificate chain signed by one of these root CAs. To do this you use <certificates src="system" />. If you don't use a network security config you also trust all these default root CAs.

    As you see it's normal to use <certificates src="system" /> (because this is the default if you don't use any network security config). It's also safe except you don't install Android system updates.

    So if your app is running on a phone which didn't get system updates there might be root CAs which have been leaked or use out-dated encryption (short key length for example). This is why browsers like Firefox use their own root CAs. Because they know some people don't update their OS.

    You said when you remove the line <certificates src="system" /> it no longer works. So it seems to be a normal certificate and you don't need <certificates src="@raw/cert" />.

    Sometimes there are websites which use self-signed certificates. These don't have a chain (cert 1, 2, 3) but instead only one. Because such a cert is not signed by a trusted root CA it's normally rejected and this is when you need <certificates src="@raw/cert" />.

    When you open your HTTPS site in Google Chrome there is a nice dialogue where you can see the certificate chain. You should take a look at it. You can reach it when you click the button next to the URL. Under "Certificate Hierarchy" you can see the 3 certificates I mentioned.

    certificate viewer