Securing server communications:
The android uses the standard way of communication (HTTPS) connection using the
HttpsURLConnection class
HttpsURLConnection
urlConn = new HttpsURLConnection("https://
clientaccess.example.com");
Once the connection has
been made you can check the connection using the
getServerCertificates() which
gives you the server certificate with the server name and other stuff. If the
server certificates don’t match with the server connected, it brings out an
exception and terminates that connection. The hostname verification can be done
with 3 different interfaces.
AllowAllHostnameVerifier
This hostname verifier
turns hostname verification off. As long as the certificate that is presented by
the server is trusted comes from a trusted Certificate Authority . It just
accepts regardless of the hostname and the URL match.
StrictHostnameVerifier
This hostname verifier is the same as the verification in the
default. It checks the first CN present in the server certificate against the
hostname specified in the URL and also checks all of the subject entries in the
certificate for a match. Wildcards are allowed, but only up to one level. For
example,*.example.com would match server1.example.com, but not
server1.domain1.example.com.
BrowserCompatHostnameVerifier
This hostname verifier is just like StrictHostnameVerifier, but wildcards in
the certificate name will match multiple levels. It accepts server1.domain1.example.com
if you specify *.example.com.
In the above three
verifications StrictHostnameVerifier has the more secure interaction with the
server
HostnameVerifier newHV = new StrictHostnameVerifier();
HttpsURLConnection.setDefaultHostnameVerifier(newHV);
We can also verify and
limit the server certificates by creating our own HostNameVerifier class and
allow only few certificates that we need to allow.
Private client
server communications:
Client side
authentication
To have a private client server communications we ourselves generate a self
signed certificate in the server which will be valid for one year and it will
be stored in the certsjks in JKS format. We cannot use it directly in
our android application so we need to convert it onto a BKS key store.Once the
certificate is been produced we need to access in our application for the
secure authentication. We use key store object to do it.
Key store for
creating the server certificate.
KeyStore selfsignedKeys
= KeyStore.getInstance("BKS");
selfsignedKeys.load(context.getResources().openRawResource(R.raw.selfsignedcertsbks),
"genericPassword".toCharArray());
When the key store loads
the server certificate we call the trust manager to check it.
TrustManagerFactory
trustMgr =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustMgr.init(selfsignedKeys);
The trust manager
factory object will verify the self signed certificate.
Once we have the Trust
Manager Factory, we can create the SSLContext that we will need to make SSL/TLS
connections using our certificate.
SSLContext
selfsignedSSLcontext = SSLContext.getInstance("TLS");
selfsignedSSLcontext.init(null, trustMgr.getTrustManagers(), new
SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(selfsignedSSLcontext.getSocketFactory());
Then we call the init ()
with 3 parameters. The client side keys, trust manager factory and the secure
random.
Server- Side authentications:
The client will verify the server that it logs
in but the server does not check to which client it communicates. When we work
in a controlled environment the server needs to make sure it communicates with
the correct device.
To do this we need to
create a client certificate for the server to validate it and conform that it
is communicating to the correct device. This should be done in the web server.
The client certificate will be stored in the clientauthcertsBKS store .we have
two key stones for the client and the server, so we now create a authenticated
secure SSL/TLS connections.
Key store for the client
certificate. The code remains the same but instead of trust manager we use key
manager which sends the client certificate to the server for the client side
authentication.
KeyStore
clientauthKeys = KeyStore.getInstance("BKS");
clientauthKeys.load(context.getResources().openRawResource(R.raw.clientauthcertsbks),"genericPassword".toCharArray());
KeyManagerFactory KeyMgr=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyMgr.init(clientauthKeys, "genericPassword".toCharArray());
Then we create a key
manager factory similar to the trust manager factory to generate the key
manager which holds up the client certificates.
Next we will create a
SSLContext for the same as we did for the server authentication.
SSLContext
privateSSLcontext = SSLContext.getInstance("TLS");
privateSSLcontext.init(keyMgr.getKeyManagers(), trustMgr.getTrustManagers(),
new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(privateSSLcontext.getSocketFactory());
Once you have done with
the SSL Context we have to call the init() with the 3 parameters
We use key manager as
the first parameter , trust manager and then the secure Random function.
We now have an SSL/TLS
configuration that restricts which server certificates
we will accept and
includes client certificates that we can use to identify ourselves to those
servers. By making use of these constructs, we can fully specify how we want
our SSL/TLS communications to act for our application. The ability to specify
both who we are willing to talk to and to whom we will identify ourselves
allows the creation of private, secure communication tunnels that are both
mutually authenticated and encrypted.