org.soyatec.windowsazure.internal.util.ssl.SslUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.soyatec.windowsazure.internal.util.ssl.SslUtil.java

Source

/**
 * Copyright  2006-2010 Soyatec
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *
 * $Id$
 */
package org.soyatec.windowsazure.internal.util.ssl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLSocketFactory;

/**
 * A collection of SSL-protocol related functions.
 */
public class SslUtil {
    public static final String CERT_ALIAS = "soyatec";
    public static final String KEYSTORE_PASS = "soyatec";
    public static final String KEYSTORE = ".keystore";

    /**
     * Return the file's absolute path name string
     * 
     * @param x509Cert
     * @return Path name string
     * @throws Exception
     */
    public static String importCertificate(String x509Cert) throws Exception {
        // CREATE A KEYSTORE OF TYPE "Java Key Store"
        KeyStore ks = KeyStore.getInstance("JKS");
        /*
         * LOAD THE STORE The first time you're doing this (i.e. the keystore
         * does not yet exist - you're creating it), you HAVE to load the
         * keystore from a null source with null password. Before any methods
         * can be called on your keystore you HAVE to load it first. Loading it
         * from a null source and null password simply creates an empty
         * keystore. At a later time, when you want to verify the keystore or
         * get certificates (or whatever) you can load it from the file with
         * your password.
         */
        ks.load(null, null);
        // GET THE FILE CONTAINING YOUR CERTIFICATE
        File x509 = new File(x509Cert);
        FileInputStream fis = new FileInputStream(x509);
        BufferedInputStream bis = new BufferedInputStream(fis);
        // I USE x.509 BECAUSE THAT'S WHAT keytool CREATES
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        // NOTE: THIS IS java.security.cert.Certificate NOT
        // java.security.Certificate
        X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);

        ks.setCertificateEntry(CERT_ALIAS, cert);
        // SAVE THE KEYSTORE TO A FILE
        /*
         * After this is saved, I believe you can just do setCertificateEntry to
         * add entries and then not call store. I believe it will update the
         * existing store you load it from and not just in memory.
         */
        File storeFile = new File(x509.getParentFile().getAbsolutePath(), KEYSTORE);
        ks.store(new FileOutputStream(storeFile), KEYSTORE_PASS.toCharArray());

        return storeFile.getAbsolutePath();
    }

    /**
     * Get a certificate object from given file.
     * 
     * @param cert
     *            the file name.
     * @return a certificate object
     * @throws Exception
     */
    public static X509Certificate getAbsolutePath(String cert) throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        FileInputStream in = new FileInputStream(cert);
        X509Certificate c = (X509Certificate) cf.generateCertificate(in);
        return c;
    }

    /**
     * Returns the certificate associated with the given alias ,store and
     * password.
     * 
     * @param store
     *            the storePath
     * @param alias
     *            the alias name
     * @param password
     *            the password
     * @return the certificate, or null if the given alias does not exist or
     *         does not contain a certificate.
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public static X509Certificate getCertificateFromStore(String store, String alias, String password)
            throws Exception {
        KeyStore ks = getKeyStore(new File(store).toURL(), password);
        X509Certificate c = (X509Certificate) ks.getCertificate(alias);
        return c;
    }

    /**
     * Returns the key associated with the given alias, using the given password
     * to recover it.
     * 
     * @param storePath
     *            the storePath
     * @param password
     *            the password
     * @param alias
     *            the alias name
     * @return the requested key, or null if the given alias does not exist or
     *         does not identify a key-related entry.
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public static PrivateKey getPrivateKey(String storePath, String password, String alias) throws Exception {
        KeyStore store = getKeyStore(new File(storePath).toURL(), password);
        return (PrivateKey) store.getKey(password, password.toCharArray());
    }

    /**
     * Return the KeyStore by given URL and password
     * 
     * @param url
     * @param password
     * @return KeyStore
     * @throws Exception
     */
    public static KeyStore getKeyStore(final URL url, final String password) throws Exception {
        if (url == null) {
            throw new IllegalArgumentException("Keystore url may not be null");
        }
        KeyStore keystore = KeyStore.getInstance("jks");
        InputStream is = null;
        try {
            is = url.openStream();
            keystore.load(is, password != null ? password.toCharArray() : null);
        } finally {
            if (is != null)
                is.close();
        }
        return keystore;
    }

    private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password) throws Exception {
        if (keystore == null) {
            throw new IllegalArgumentException("Keystore may not be null");
        }
        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmfactory.init(keystore, password != null ? password.toCharArray() : null);
        return kmfactory.getKeyManagers();
    }

    private static TrustManager[] createTrustManagers(final KeyStore keystore)
            throws KeyStoreException, NoSuchAlgorithmException {
        if (keystore == null) {
            throw new IllegalArgumentException("Keystore may not be null");
        }
        TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmfactory.init(keystore);
        TrustManager[] trustmanagers = tmfactory.getTrustManagers();
        return trustmanagers;
    }

    /**
     * Create SSLContext by given
     * keyStoreUrl,keyStorePassword,trustStoreUrl,trustStorePassword,certAlias
     * 
     * @param keyStoreUrl
     *            the keyStore URL
     * @param keyStorePassword
     *            the keyStore password
     * @param trustStoreUrl
     *            the trustStore URL
     * @param trustStorePassword
     *            the trustStore password
     * @param certAlias
     *            the alias name
     * @return the new SSLContext object
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public static SSLContext createSSLContext(String keyStoreUrl, String keyStorePassword, String trustStoreUrl,
            String trustStorePassword, String certAlias) throws Exception {

        KeyManager[] keymanagers = null;
        TrustManager[] trustmanagers = null;

        KeyStore keystore = getKeyStore(new File(keyStoreUrl).toURL(), keyStorePassword);

        PrivateKey privateKey = (PrivateKey) keystore.getKey(certAlias, keyStorePassword.toCharArray());
        X509Certificate cert = (X509Certificate) keystore.getCertificate(certAlias);

        keymanagers = createKeyManagers(keystore, keyStorePassword);
        for (int i = 0; i < keymanagers.length; i++) {

            if (keymanagers[i] instanceof X509ExtendedKeyManager) {
                keymanagers[i] = new HttpsX509KeyManager((X509ExtendedKeyManager) keymanagers[i], certAlias,
                        privateKey, cert);
            }

        }
        SSLContext sslcontext = SSLContext.getInstance("TLS");
        KeyStore trustStore = getKeyStore(new File(trustStoreUrl).toURL(), trustStorePassword);
        trustmanagers = createTrustManagers(trustStore);
        for (int i = 0; i < trustmanagers.length; i++) {
            if (trustmanagers[i] instanceof X509TrustManager) {
                trustmanagers[i] = new HttpsX509TrustManager((X509TrustManager) trustmanagers[i]);
            }
        }
        sslcontext.init(keymanagers, trustmanagers, null);

        return sslcontext;
    }

    @SuppressWarnings("unused")
    private static void loadWindowsCert() throws Exception {
        KeyStore ks = KeyStore.getInstance("Windows-MY");// "Windows-ROOT"
        ks.load(null, null);
        Enumeration<String> en = ks.aliases();
        while (en.hasMoreElements()) {
            String key = en.nextElement();
            Certificate[] certs = ks.getCertificateChain(key);
            X509Certificate cert = (X509Certificate) certs[0];
        }
    }

    /**
     * Get the SSLSocketFactory by given SSLContext
     * 
     * @param context
     *            the SSLContext object
     * @return the SSLSocketFactory object
     */
    public static SSLSocketFactory getSSLSocketFactory(SSLContext context) {
        SSLSocketFactory factory = new SSLSocketFactory(context);
        factory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return factory;
    }

    /**
     * Create SSLSocketFactory by given
     * keyStoreUrl,keyStorePassword,trustStoreUrl,trustStorePassword,certAlias
     * 
     * @param keyStoreUrl
     *            the keyStore URL
     * @param keyStorePassword
     *            the keyStore password
     * @param trustStoreUrl
     *            the trustStore URL
     * @param trustStorePassword
     *            the trustStore password
     * @param certAlias
     *            the alias name
     * @return the new SSLSocketFactory object
     * @throws Exception
     */
    public static SSLSocketFactory createSSLSocketFactory(String keyStoreUrl, String keyStorePassword,
            String trustStoreUrl, String trustStorePassword, String certAlias) throws Exception {

        SSLContext context = createSSLContext(keyStoreUrl, keyStorePassword, trustStoreUrl, trustStorePassword,
                certAlias);
        return getSSLSocketFactory(context);
    }
}