pl.baczkowicz.spy.security.SecureSocketUtils.java Source code

Java tutorial

Introduction

Here is the source code for pl.baczkowicz.spy.security.SecureSocketUtils.java

Source

/***********************************************************************************
 * 
 * Copyright (c) 2015 Kamil Baczkowicz
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 *    
 * The Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 * 
 *    Kamil Baczkowicz - initial API and implementation and/or initial documentation
 *    
 */
package pl.baczkowicz.spy.security;

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;

import org.bouncycastle.util.io.pem.PemReader;

import pl.baczkowicz.spy.common.generated.KeyStoreTypeEnum;
import pl.baczkowicz.spy.files.FileUtils;

/**
 * Utility class for handling SSL/TLS connections.
 */
public class SecureSocketUtils {
    private final static String ALGORITHM = "RSA";

    /**
     * Loads a PEM file from the specified location.
     * 
     * @param file Location of the file to load
     * 
     * @return Content of the PEM file
     * 
     * @throws IOException Thrown when cannot read the file
     */
    public static byte[] loadPemFile(final String file) throws IOException {
        final PemReader pemReader = new PemReader(new FileReader(file));
        final byte[] content = pemReader.readPemObject().getContent();
        pemReader.close();
        return content;
    }

    /**
     * Loads a key file from the specified location.
     * 
     * @param file Location of the file to load
     * 
     * @return Content of the key file
     * 
     * @throws IOException Thrown when cannot read the file
     */
    public static byte[] loadBinaryFile(final String file) throws IOException {
        final FileInputStream inputStream = new FileInputStream(file);
        final byte[] data = new byte[inputStream.available()];
        inputStream.read(data);
        inputStream.close();
        return data;
    }

    /**
     * Loads a private key from the specified location.
     */
    public static PrivateKey loadPrivateKeyFromPemFile(final String keyFile)
            throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
        final PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(loadPemFile(keyFile));
        final PrivateKey privateKey = KeyFactory.getInstance(ALGORITHM).generatePrivate(privateKeySpec);
        return privateKey;
    }

    /**
     * Loads a private key from the specified location.
     */
    public static PrivateKey loadPrivateKeyFromBinaryFile(final String keyFile)
            throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
        final PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(loadBinaryFile(keyFile));
        final PrivateKey privateKey = KeyFactory.getInstance(ALGORITHM).generatePrivate(privateKeySpec);
        return privateKey;
    }

    /**
     * Loads an X509 certificate from the given location.
     */
    public static X509Certificate loadX509Certificate(final String certificateFile)
            throws IOException, CertificateException {
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final InputStream inputStream = FileUtils.loadFileByName(certificateFile);
        final X509Certificate certificate = (X509Certificate) cf.generateCertificate(inputStream);
        inputStream.close();
        return certificate;
    }

    /**
     * Creates a trust manager factory.
     */
    public static TrustManagerFactory getTrustManagerFactory(final String caCertificateFile)
            throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
        // Load CA certificate
        final X509Certificate caCertificate = (X509Certificate) loadX509Certificate(caCertificateFile);

        // CA certificate is used to authenticate server
        final KeyStore keyStore = getKeyStoreInstance(KeyStoreTypeEnum.DEFAULT);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca-certificate", caCertificate);

        final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        return tmf;
    }

    /**
     * Creates a trust manager factory.
     */
    public static TrustManagerFactory getTrustManagerFactory(final String keyStoreFile,
            final String keyStorePassword, final KeyStoreTypeEnum keyStoreType)
            throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
        // Load key store
        final KeyStore keyStore = loadKeystore(keyStoreFile, keyStorePassword, keyStoreType);

        final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        return tmf;
    }

    /**
     * Creates a key manager factory using a key store.
     */
    public static KeyManagerFactory getKeyManagerFactory(final String keyStoreFile, final String keyStorePassword,
            final String keyPassword, final KeyStoreTypeEnum keyStoreType)
            throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException,
            UnrecoverableKeyException, InvalidKeySpecException {
        // Load key store
        final KeyStore keyStore = loadKeystore(keyStoreFile, keyStorePassword, keyStoreType);

        final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, keyPassword.toCharArray());

        return kmf;
    }

    /**
     * Creates a key manager factory.
     */
    public static KeyManagerFactory getKeyManagerFactory(final String clientCertificateFile,
            final String clientKeyFile, final String clientKeyPassword, final boolean pemFormat)
            throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException,
            UnrecoverableKeyException, InvalidKeySpecException {
        // Load client certificate
        final X509Certificate clientCertificate = loadX509Certificate(clientCertificateFile);

        // Load private client key
        final PrivateKey privateKey = pemFormat ? loadPrivateKeyFromPemFile(clientKeyFile)
                : loadPrivateKeyFromBinaryFile(clientKeyFile);

        // Client key and certificate are sent to server
        final KeyStore keyStore = getKeyStoreInstance(KeyStoreTypeEnum.DEFAULT);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("certificate", clientCertificate);
        keyStore.setKeyEntry("private-key", privateKey, clientKeyPassword.toCharArray(),
                new Certificate[] { clientCertificate });

        final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, clientKeyPassword.toCharArray());

        return kmf;
    }

    /**
     * Loads a key store from the specified location and using the given password.
     */
    public static KeyStore loadKeystore(final String keyStoreFile, final String keyStorePassword,
            final KeyStoreTypeEnum keyStoreType)
            throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
        final FileInputStream inputStream = new FileInputStream(keyStoreFile);

        KeyStore keyStore;

        try {
            keyStore = getKeyStoreInstance(keyStoreType);
            keyStore.load(inputStream, keyStorePassword.toCharArray());
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }

        return keyStore;
    }

    public static KeyStore getKeyStoreInstance(final KeyStoreTypeEnum type) throws KeyStoreException {
        if (type == null || KeyStoreTypeEnum.DEFAULT.equals(type)) {
            return KeyStore.getInstance(KeyStore.getDefaultType());
        }

        return KeyStore.getInstance(type.value());
    }

    public static KeyStore getKeyStoreInstance(final KeyStoreTypeEnum type, final Provider provider)
            throws KeyStoreException {
        if (type == null || KeyStoreTypeEnum.DEFAULT.equals(type)) {
            return KeyStore.getInstance(KeyStore.getDefaultType());
        }

        return KeyStore.getInstance(type.value(), provider);
    }

    public static KeyStoreTypeEnum getTypeFromFilename(final String filename) {
        if (filename == null || filename.isEmpty()) {
            return KeyStoreTypeEnum.DEFAULT;
        } else if (filename.toLowerCase().endsWith("jks")) {
            return KeyStoreTypeEnum.JKS;
        } else if (filename.toLowerCase().endsWith("jceks")) {
            return KeyStoreTypeEnum.JCEKS;
        } else if (filename.toLowerCase().endsWith("p12")) {
            return KeyStoreTypeEnum.PKCS_12;
        } else if (filename.toLowerCase().endsWith("pfx")) {
            return KeyStoreTypeEnum.PKCS_12;
        } else if (filename.toLowerCase().endsWith("bks")) {
            return KeyStoreTypeEnum.BKS;
        } else {
            return KeyStoreTypeEnum.DEFAULT;
        }
    }
}