10/02/2014

How to do SSL connection using .pfx key file and password in java (HTTPClient)

How to do SSL connection using .pfx key file and password in java (HTTPClient)
If you are going to use HTTPClient to extract the java understanding TrustStore, KeyStore are very impotent.
KeyStore: Is nothing but private key (.pfx and its password) information that client is used to connect remote machine. Used by client.
Truststore : Which contains trusted certificates  chain. Used by server.  
   Why we need these certificates while connecting from HTTP client/java?
In client server communication first client send “hello” request. Server would replay to this with “hello” response. The response also contains the certificate usually “singed by CA” and ask the client something say do you trust this certificate?  Then client (java) looks for this certificate in the truststore (certificate chain) whether this certificate can be trusted or not?   If this certificate in trust store, client send “true” to Server.  Once client trust the certificate, server allows accessing to server method.  If server method access restricted it looks for private key and its password.  
This is all happens in fraction of mile seconds and this is called a HAND-SHAKE.    If anything goes wrong in handshake we get handshake exception.  
Connecting to server using httpclient is all about configuring the right sslcontext.

Below is the abstract java class you can use this directly by extending to your own class. This class would create write client for you.

If you don’t have “truststore” and just need to trust all certificates blindly use below method to create client.
getHttpClientWithoutTrustKey()
If you created trust store than use below method to get client
DefaultHttpClient getHttpClient()
In both methods it is important to understand how I am creating  keystore,truststore, and SSLContext.


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package com.my.downloaders;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.util.Assert;


/*
 * keytool -keystore <trustore name> -import -alias <alias name >-file certificate.cer -trustcacerts
 */
public abstract class AbstractHTTPSWithPrivateKeyDownloader {
       private static Logger logger = Logger.getLogger(AbstractHTTPSWithPrivateKeyDownloader.class.getName());
      
       public String trustStoreKey;//="truststore location";
       public String trustStorePass;//="trustostore";
       public String keyStoreKey;//=”absolute path to .pfx file”;
       public String keyStorePassowrd;//="";
       public String privatePassWord;//="it is same as keyStorePassowrd ";
      
       public void afterPropertiesSet() throws Exception {

              Assert.notNull(keyStorePassowrd, "keyStorePassowrd property cannot be NULL.");
              Assert.notNull(keyStoreKey, "keyStore property cannot be NULL.");
             
       }
      
       public abstract void doExecute() throws Exception;

       public void setTrustStoreKey(String trustStoreKey) {
              this.trustStoreKey = trustStoreKey;
       }
       public void setTrustStorePass(String trustStorePass) {
              this.trustStorePass = trustStorePass;
       }
       public void setKeyStoreKey(String keyStoreKey) {
              this.keyStoreKey = keyStoreKey;
       }
       public void setKeyStorePassowrd(String keyStorePassowrd) {
              this.keyStorePassowrd = keyStorePassowrd;
              this.privatePassWord=keyStorePassowrd;
       }

       protected  DefaultHttpClient getHttpClient() throws Exception{
             
              try
              {
              KeyStore trustStore = getTrustoStore(new File(trustStoreKey),
                           trustStorePass);
              KeyStore keyStore = getKeyStore(new File(keyStoreKey), keyStorePassowrd);
              SSLSocketFactory socketFactory = getSSLSocketFactory(
                           privatePassWord, trustStore, keyStore);

              Scheme sch = new Scheme("https", 443, socketFactory);
              DefaultHttpClient httpclient = new DefaultHttpClient();
              httpclient.getConnectionManager().getSchemeRegistry().register(sch);
              return httpclient;
              }
              catch(Exception e)
              {
                     logger.log(Level.WARNING, e.getMessage(), e);
                     return getHttpClientWithoutTrustKey();
              }
             
       }
      
       protected  DefaultHttpClient getHttpClientWithoutTrustKey() throws Exception{
             
             
              KeyStore keyStore = getKeyStore(new File(keyStoreKey), keyStorePassowrd);
             
              KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
              kmfactory.init(keyStore, keyStorePassowrd.toCharArray());
             
              SSLContext sslContext = SSLContext.getInstance("SSL");

              // set up a TrustManager that trusts everything
              sslContext.init(kmfactory.getKeyManagers(), new TrustManager[] { new X509TrustManager() {
                          public X509Certificate[] getAcceptedIssuers() {
                            logger.info("getAcceptedIssuers =============");
                                  return null;
                          }

                          public void checkClientTrusted(X509Certificate[] certs,
                                          String authType) {
                            logger.info("checkClientTrusted =============");
                          }

                          public void checkServerTrusted(X509Certificate[] certs,
                                          String authType) {
                            logger.info("checkServerTrusted =============");
                          }
              } }, new SecureRandom());
             
              SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
              Scheme sch = new Scheme("https", 443, socketFactory);
              DefaultHttpClient httpclient = new DefaultHttpClient();
              httpclient.getConnectionManager().getSchemeRegistry().register(sch);
              return httpclient;
       }

       protected  SSLSocketFactory getSSLSocketFactory(
                     String privateKeyPassword, KeyStore trustStore, KeyStore keyStore)
                     throws NoSuchAlgorithmException, KeyManagementException,
                     KeyStoreException {
              SSLSocketFactory socketFactory = null;
              try {
                    
                     socketFactory = new SSLSocketFactory(keyStore, privateKeyPassword,
                                  trustStore);
              } catch (UnrecoverableKeyException ke) {
                     logger.severe("Failed to create SSLSocketFactory, possible wrong password on client private key");
              }
              return socketFactory;
       }

       protected static KeyStore getTrustoStore(File truststoreFile,
                     String truststorePassword) throws Exception {
              KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
              FileInputStream trustStream = new FileInputStream(truststoreFile);
              try {
                     logger.info("Loading server truststore from file "
                                  + truststoreFile.getPath());
                     trustStore.load(trustStream, truststorePassword.toCharArray());
                     logger.info("Truststore certificate count: "
                                  + trustStore.size());
              } catch (Exception ex) {
                     logger.severe("Failed to load truststore: " + ex.toString());
                     throw ex;
              } finally {
                     try {
                           trustStream.close();
                     } catch (Exception ignore) {
                     }
              }
              return trustStore;
       }

       protected static KeyStore getKeyStore(File keystoreFile,
                     String keystorePassword) throws KeyStoreException,
                     NoSuchProviderException, FileNotFoundException {
              KeyStore keyStore = KeyStore.getInstance("PKCS12", "SunJSSE");
              FileInputStream keyStream = new FileInputStream(keystoreFile);
              try {
                     logger.info("Loading client keystore from file "
                                  + keystoreFile.getPath());
                     keyStore.load(keyStream, keystorePassword.toCharArray());
                     logger.info("Keystore certificate count: " + keyStore.size());
              } catch (Exception e) {
                     System.err.println("Failed to load keystore: " + e.toString());
                     logger.log(Level.SEVERE, e.getMessage(), e);

              } finally {
                     try {
                           keyStream.close();
                     } catch (Exception e) {
                           logger.log(Level.WARNING, e.getMessage(), e);
                     }
              }
              return keyStore;
       }

}


How to use the above class?
Create a URI and override the doExcecute() method.  

public class CliendDownloader extends AbstractHTTPSWithPrivateKeyDownloader implements Tasklet, InitializingBean {
      
       static {
              System.setProperty("sun.security.ssl.allowUnsafeRenegotiation","true");
       }
      
       private static Logger logger = Logger.getLogger(CliendDownloader.class.getName());
       public String url;
             
      
       public void setUrl(String url) {
              this.url = url;
       }

       public void doExecute() throws Exception {
              URI targetURI = new URI(url.trim());
              String protocol = targetURI.getScheme();
              if (!"https".equals(protocol)) {
                     logger.severe("URI does not begin with expected protocol name");
                     return;
              }
              logger.info("URI to fetch is " + targetURI.toString());

              DefaultHttpClient httpclient =null;
              try {
                    
                     if(trustStoreKey!=null && trustStorePass!=null)
                     {
                           httpclient = getHttpClient();
                     }
                     else
                     {
                           httpclient = getHttpClientWithoutTrustKey();
                     }
                    
                     HttpGet httpget = new HttpGet(targetURI);
                     HttpResponse response = null;
                     try {
                           response = httpclient.execute(httpget);
                            -----------
                           -------
                    
}



 }

How to create trust store?

If you would like to have trustore
Import the certificate from IE browser download in .cer format and run the below command.  

keytool -keystore <trustore name> -import -alias <alias name > -file certificate.cer -trustcacerts


3 comments:

  1. Thanks Santosh. Very Nice Article. It really helpful for me

    ReplyDelete
  2. Prove your skills with CCA 175 certification exam. Getting through this exam is not easy. It requires hard work and hands on training on projects related or relevant to CCA 175 certification program. Get passed in CCA 175 certification exam through our intensive training and hands on experience on projects.
    cca 175 certification
    cloudera hadoop developer certification
    cca 175 spark and hadoop developer certification
    hadoop developer certification

    ReplyDelete
  3. Thank you very much for this example!

    ReplyDelete