org.pepstock.jem.node.security.keystore.KeyStoreUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.pepstock.jem.node.security.keystore.KeyStoreUtil.java

Source

/**
JEM, the BEE - Job Entry Manager, the Batch Execution Environment
Copyright (C) 2012-2015   Simone "Busy" Businaro
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.pepstock.jem.node.security.keystore;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;

import org.apache.commons.io.FileUtils;
import org.bouncycastle.operator.OperatorCreationException;
import org.pepstock.jem.log.LogAppl;
import org.pepstock.jem.node.Main;
import org.pepstock.jem.node.security.Crypto;

import com.hazelcast.config.SocketInterceptorConfig;

/**
 * Utility to manage the keystores and keys, managed inside the JEM node.<br>
 * 
 * @author Simone "Busy" Businaro
 * @version 1.0
 * 
 */
public class KeyStoreUtil {

    private static KeyStoresInfo INFO = null;

    /**
     * Private constructor to avoid any instantiation 
     */
    private KeyStoreUtil() {
    }

    /**
     * Returns the keystores with symmetric keys of used for socket interceptor.
     * 
     * @return return keystore info
     */
    public static synchronized KeyStoresInfo getKeyStoresInfo() {
        if (INFO == null) {
            // gets key store properteis from HC configuration
            SocketInterceptorConfig config = Main.getHazelcast().getConfig().getNetworkConfig()
                    .getSocketInterceptorConfig();
            // creates keystore
            INFO = Factory.createKeyStoresInfo(config.getProperties());
        }
        return INFO;
    }

    /**
     * Returns a SSL socket factory creating asymmetric keys at runtime.
     * 
     * @return a SSL socket factory for HTTPS listener 
     * @throws KeyStoreException if any errors occurs to get keys
     */
    public static SSLServerSocketFactory getSSLServerSocketFactory() throws KeyStoreException {
        try {
            // gets a key stores created at runtime
            ByteArrayInputStream baos = SelfSignedCertificate.getCertificate();
            KeyStore keystore = KeyStore.getInstance("jks");
            // loads the keystore
            keystore.load(baos, SelfSignedCertificate.CERTIFICATE_PASSWORD.toCharArray());
            KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

            // initialiazes the key manager
            kmfactory.init(keystore, SelfSignedCertificate.CERTIFICATE_PASSWORD.toCharArray());
            KeyManager[] keymanagers = kmfactory.getKeyManagers();
            // creates SSL socket factory
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(keymanagers, null, null);
            return sslcontext.getServerSocketFactory();
        } catch (UnrecoverableKeyException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (KeyManagementException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (CertificateException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (SecurityException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (IOException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (OperatorCreationException e) {
            throw new KeyStoreException(e.getMessage(), e);
        }
    }

    /**
     * Gets a key store using a entity with teh information where it has to read and 
     * load into the keystore
     * 
     * @param keystoreInfo entity with information about keystore
     * @return a new keystore
     * @throws KeyStoreException if any error occurs during the keystore creation
     */
    static KeyStore getKeystore(KeyStoreInfo keystoreInfo) throws KeyStoreException {
        // gets keystore
        KeyStore keystore = KeyStore.getInstance(keystoreInfo.getType());
        InputStream is = null;
        try {
            // if the entity must read the keystore from memory
            // used the bytes of the entity and
            if (keystoreInfo.getBytes() != null) {
                is = new ByteArrayInputStream(keystoreInfo.getBytes().toByteArray());
            } else {
                // otherwise it reads the keystore from the file system 
                is = new FileInputStream(keystoreInfo.getFile());
            }
            // loads the key store
            keystore.load(is, keystoreInfo.getPassword().toCharArray());
        } catch (FileNotFoundException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (CertificateException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (IOException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } finally {
            // if inputstream is not null
            // it closes
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    // ignore
                    LogAppl.getInstance().ignore(e.getMessage(), e);
                }
            }
        }
        return keystore;
    }

    /**
     * Generate an empty key store where will be store the X509 certificate of
     * the user
     * <p>
     * This key store will be used when the client will used a private key to
     * connect to the cluster and the cluster will used the relative public key
     * present in the x509 certificate to verify the identity of the client.
     * @param keystoreInfo entity with information about keystore
     * @throws KeyStoreException if any exception occurs during key store creation
     * 
     */
    public static void generate(KeyStoreInfo keystoreInfo) throws KeyStoreException {
        try {
            // if the keystore exist load it else create a new one
            KeyStore keystore = null;
            if (keystoreInfo.getFile().exists()) {
                keystore = getKeystore(keystoreInfo);
            } else {
                keystore = KeyStore.getInstance(keystoreInfo.getType());
                keystore.load(null, null);
                save(keystore, keystoreInfo);
            }
            // if the keystore does not contain the given alias, create a new key
            // with that alias otherwise does nothing
            if (keystoreInfo.getSymmetricKeyAlias() != null && keystoreInfo.getSymmetricKeyPwd() != null
                    && keystore.getKey(keystoreInfo.getSymmetricKeyAlias(),
                            keystoreInfo.getSymmetricKeyPwd().toCharArray()) == null) {
                // creates simmetricKey
                Key secretKey = Crypto.generateSymmetricKey();
                // adds the key
                keystore.setKeyEntry(keystoreInfo.getSymmetricKeyAlias(), secretKey,
                        keystoreInfo.getSymmetricKeyPwd().toCharArray(), null);
                // saves the keystore
                save(keystore, keystoreInfo);
            }
        } catch (UnrecoverableKeyException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (CertificateException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (IOException e) {
            throw new KeyStoreException(e.getMessage(), e);
        }
    }

    /**
     * Saves the kwystore on the file
     * @param keystore keystore to be saved
     * @param info Key store info with all necessary info to save it 
     * @throws KeyStoreException if any error occurs saving the key store
     */
    static void save(KeyStore keystore, KeyStoreInfo info) throws KeyStoreException {
        OutputStream os = null;
        try {
            // creates the file stream
            os = new FileOutputStream(info.getFile());
            // stores the file 
            keystore.store(os, info.getPassword().toCharArray());
            // checks if it must be backuped
            if (info.getBackupFile() != null) {
                // read keystore to check if is consistent
                getKeystore(info);
                FileUtils.copyFile(info.getFile(), info.getBackupFile());
            }
        } catch (FileNotFoundException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (IOException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } catch (CertificateException e) {
            throw new KeyStoreException(e.getMessage(), e);
        } finally {
            // always it closes the outut stream
            if (os != null) {
                try {
                    os.close();
                } catch (Exception e) {
                    // ignore
                    LogAppl.getInstance().ignore(e.getMessage(), e);
                }
            }
        }
    }
}