If you are developing some kind of Android application that needs
to connect to your own server infrastructure, and you want to
encrypt your communication with SSL, you will most likely run into
an error that looks something like this:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
The reason for this is that Android, like most other commercial
SSL-enabled systems, has a list of Certificate Authorities (CAs)
that it deems trustworthy, and it will refuse to work with any key
that you created for yourself without paying some random company
arbitrary amounts of money for some carefully crafted random bits.
internet will tell you that you can work around this problem easily by
creating your custom X509Trustmanager with disabled certificate
checks. This however is the worst thing you could do. By disabling
certification verifications, you will be wide open to
attacks, and you are only marginally better off than without SSL
in the first place.
However, the correct solution is actually relatively simple: Just
create your own CA, sign your key with that CA, and tell Android to
trust your CA.
The creation of your CA is pretty straight-forward. A CA is
actually not more than another RSA key, so here's how to create
one. The simplest way I found is to use
scripts from OpenVPN, so you should go ahead and clone their
repository. Go to easy-rsa/2.0, change the vars file to your
liking, then do
You will end up with a ca.key, which you can use to sign your keys,
and ca.crt, which is the public part of the certificate. Don't worry
too much about the values of the fields you are asked to fill in,
those are just tags and don't change the key. Now, you are ready to
create your actual server key and sign it:
This will create a server.key and server.crt, which you can use
with on your SSL-enabled server.
On the client side, what needs to be done depends on your setup. So
if you have...
... an application that connects to a self-hosted server, that is,
every user has his or her own server: Instruct your users to create their
keys as described above. Then, have them push the ca.crt that was
created during the process above anywhere on the device:
adb push ca.crt /storage/sdcard0/
Then go to System Settings - Security - Credential Storage -
Install from storage. Your device will look for any file ending with
.crt on storage, and ask to you to install it. Leave the default
(Apps and VPN) selected. After that, you can just connect to your
server, and Android will make sure that the certificate is valid.
... an application that connects to your own cloud infrastructure,
that is, most users connect to the same server: Create a custom key
store. This process is actually pretty well documented, so just
instructions here. The
basic idea is to put a key store in your resources and then load it
before opening the connection.
I hope those instructions help to reduce the number of insecure
applications on Android a bit.