Android and Client Authentication
Originally published at kbremner.github.io on February 18, 2014.
Recently I have been developing an application that had to support client authentication using certificates. The process wasn’t quite as well documented as I would have expected, so this post aims to help others that need to support client authentication in their application (aimed at Ice Cream Sandwich (ICS) and above).
System Keystore
Traditionally, Android applications created their own keystores for storing sensitive credentials. ICS, however, brought in the ability for applications to access credentials stored in a system keystore when authorised by a user. This not only simplifies the process, but with some devices supporting hardware-backed keystores, it can also be more secure than an application keystore stored in the file system.
If credentials using a particular algorithm are stored using a hardware feature, such as a secure element or Trusted Execution Environment (TEE), they are effectively “bound” to that particular device once installed and so protected against extraction. To determine if an algorithm is hardware-backed, the method KeyChain.isBoundKeyAlgorithm(String) can be used.
Getting an Alias
Before an application can use credentials stored in the system keystore, the user needs to give the application access to them. The KeyChain API provides a simple means of doing this:
The user will be shown a dialog where they can select a certificate currently stored in the system keystore, or install a new certificate. When the user selects a certificate and closes the dialog, the callback will be given an alias for the selected certificate that it can use to access it. If the user cancels the dialog, the callback will be given a null alias.
It is important to note that although the KeyChain API allows an application to provide hints as to which certificate the user should choose, it cannot force the user to select a particular certificate.
Once an application has an alias for a certificate, it can be used to obtain information associated with it. Below is an example implementation of an X509KeyManager that uses the alias for a certificate to get it’s certificate chain and private key. This can then be used to initialise an SSL context, before setting a URL connection to use the SSL context to allow it to support client authentication, as shown below. Note that the X509Impl instance should be cached instead of being created for each connection, as getting the certificate chain and private key can be slow.