/** * This file is part of Waarp Project. * * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the * COPYRIGHT.txt in the distribution for a full listing of individual contributors. * * All Waarp Project 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 (at your option) any later version. * * Waarp 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 Waarp . If not, see * <http://www.gnu.org/licenses/>. */ package org.waarp.common.crypto.ssl; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; import org.waarp.common.exception.CryptoException; import org.waarp.common.logging.WaarpLogger; import org.waarp.common.logging.WaarpLoggerFactory; /** * SecureKeyStore for SLL * * @author Frederic Bregier * */ public class WaarpSecureKeyStore { /** * Internal Logger */ private static final WaarpLogger logger = WaarpLoggerFactory .getLogger(WaarpSecureKeyStore.class); private String keyStoreFilename; private KeyStore keyStore; private KeyManagerFactory keyManagerFactory; private String keyStorePasswd; private String keyPassword; private WaarpSecureTrustManagerFactory secureTrustManagerFactory; private String trustStoreFilename; private KeyStore keyTrustStore; private String trustStorePasswd; /** * Initialize empty KeyStore. No TrustStore is internally created. * * @param _keyStorePasswd * @param _keyPassword * @throws CryptoException */ public WaarpSecureKeyStore(String _keyStorePasswd, String _keyPassword) throws CryptoException { keyStorePasswd = _keyStorePasswd; keyPassword = _keyPassword; try { keyStore = KeyStore.getInstance("JKS"); } catch (KeyStoreException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } try { // Empty keyStore created so null for the InputStream keyStore.load(null, getKeyStorePassword()); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (CertificateException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (FileNotFoundException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (IOException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } initKeyManagerFactory(); } /** * Initialize the SecureKeyStore with no TrustStore from file * * @param keyStoreFilename * @param _keyStorePasswd * @param _keyPassword * @throws CryptoException */ public WaarpSecureKeyStore( String keyStoreFilename, String _keyStorePasswd, String _keyPassword) throws CryptoException { initKeyStore(keyStoreFilename, _keyStorePasswd, _keyPassword); } /** * Initialize the SecureKeyStore and TrustStore from files * * @param keyStoreFilename * @param _keyStorePasswd * @param _keyPassword * @param trustStoreFilename * if Null, no TrustKeyStore will be created * @param _trustStorePasswd * @param needClientAuthent * True if the TrustStore is also used for Client Authentication * @throws CryptoException */ public WaarpSecureKeyStore( String keyStoreFilename, String _keyStorePasswd, String _keyPassword, String trustStoreFilename, String _trustStorePasswd, boolean needClientAuthent) throws CryptoException { // Create the KeyStore initKeyStore(keyStoreFilename, _keyStorePasswd, _keyPassword); // Now create the TrustKeyStore if (trustStoreFilename != null) { initTrustStore(trustStoreFilename, _trustStorePasswd, needClientAuthent); } else { initEmptyTrustStore(); } } /** * Initialize the SecureKeyStore with no TrustStore from file * * @param _keyStoreFilename * @param _keyStorePasswd * @param _keyPassword * @throws CryptoException */ public void initKeyStore(String _keyStoreFilename, String _keyStorePasswd, String _keyPassword) throws CryptoException { keyStoreFilename = _keyStoreFilename; keyStorePasswd = _keyStorePasswd; keyPassword = _keyPassword; // First keyStore itself try { keyStore = KeyStore.getInstance("JKS"); } catch (KeyStoreException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } FileInputStream inputStream = null; try { inputStream = new FileInputStream(keyStoreFilename); keyStore.load(inputStream, getKeyStorePassword()); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (CertificateException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (FileNotFoundException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } catch (IOException e) { logger.error("Cannot create KeyStore Instance", e); throw new CryptoException("Cannot create KeyStore Instance", e); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { } } initKeyManagerFactory(); } /** * Init KeyManagerFactory * * @throws CryptoException */ void initKeyManagerFactory() throws CryptoException { try { keyManagerFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); // "SunX509"); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create KeyManagerFactory Instance", e); throw new CryptoException("Cannot create KeyManagerFactory Instance", e); } try { keyManagerFactory.init(keyStore, getCertificatePassword()); } catch (UnrecoverableKeyException e) { logger.error("Cannot create KeyManagerFactory Instance", e); throw new CryptoException("Cannot create KeyManagerFactory Instance", e); } catch (KeyStoreException e) { logger.error("Cannot create KeyManagerFactory Instance", e); throw new CryptoException("Cannot create KeyManagerFactory Instance", e); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create KeyManagerFactory Instance", e); throw new CryptoException("Cannot create KeyManagerFactory Instance", e); } } /** * Delete a Key from the KeyStore based on its alias * * @param alias * @return True if entry is deleted */ public boolean deleteKeyFromKeyStore(String alias) { try { keyStore.deleteEntry(alias); } catch (KeyStoreException e) { logger.error("Cannot delete Key from KeyStore Instance", e); return false; } return true; } /** * Add a Key and its certificates into the KeyStore based on its alias * * @param alias * @param key * @param chain * @return True if entry is added */ public boolean setKeytoKeyStore(String alias, Key key, Certificate[] chain) { try { keyStore.setKeyEntry(alias, key, getCertificatePassword(), chain); } catch (KeyStoreException e) { logger.error("Cannot add Key and Certificates to KeyStore Instance", e); return false; } return true; } /** * Save a KeyStore to a file * * @param filename * @return True if keyStore is saved to file */ public boolean saveKeyStore(String filename) { FileOutputStream fos = null; try { fos = new FileOutputStream(filename); try { keyStore.store(fos, getKeyStorePassword()); } catch (KeyStoreException e) { logger.error("Cannot save to file KeyStore Instance", e); return false; } catch (NoSuchAlgorithmException e) { logger.error("Cannot save to file KeyStore Instance", e); return false; } catch (CertificateException e) { logger.error("Cannot save to file KeyStore Instance", e); return false; } catch (IOException e) { logger.error("Cannot save to file KeyStore Instance", e); return false; } } catch (FileNotFoundException e) { logger.error("Cannot save to file KeyStore Instance", e); return false; } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { } } return true; } /** * Initialize the TrustStore from a filename and its password * * @param _trustStoreFilename * @param _trustStorePasswd * @param needClientAuthent * True if the TrustStore is also to authenticate clients * @throws CryptoException */ public void initTrustStore(String _trustStoreFilename, String _trustStorePasswd, boolean needClientAuthent) throws CryptoException { trustStoreFilename = _trustStoreFilename; trustStorePasswd = _trustStorePasswd; try { keyTrustStore = KeyStore.getInstance("JKS"); } catch (KeyStoreException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } FileInputStream inputStream = null; try { inputStream = new FileInputStream(trustStoreFilename); keyTrustStore.load(inputStream, getKeyTrustStorePassword()); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } catch (CertificateException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } catch (FileNotFoundException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } catch (IOException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e2) { } } TrustManagerFactory trustManagerFactory = null; try { trustManagerFactory = TrustManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); } catch (NoSuchAlgorithmException e1) { logger.error("Cannot create TrustManagerFactory Instance", e1); throw new CryptoException("Cannot create TrustManagerFactory Instance", e1); } try { trustManagerFactory.init(keyTrustStore); } catch (KeyStoreException e1) { logger.error("Cannot create TrustManagerFactory Instance", e1); throw new CryptoException("Cannot create TrustManagerFactory Instance", e1); } try { secureTrustManagerFactory = new WaarpSecureTrustManagerFactory(trustManagerFactory, needClientAuthent); } catch (CryptoException e) { logger.error("Cannot create TrustManagerFactory Instance", e); throw new CryptoException("Cannot create TrustManagerFactory Instance", e); } } /** * Initialize an empty TrustStore * * @return True if correctly initialized empty */ public boolean initEmptyTrustStore() { trustStorePasswd = "secret"; try { keyTrustStore = KeyStore.getInstance("JKS"); } catch (KeyStoreException e) { logger.error("Cannot create keyTrustStore Instance", e); return false; } try { // Empty keyTrustStore created so null for the InputStream keyTrustStore.load(null, getKeyTrustStorePassword()); } catch (NoSuchAlgorithmException e) { logger.error("Cannot create keyTrustStore Instance", e); return false; } catch (CertificateException e) { logger.error("Cannot create keyTrustStore Instance", e); return false; } catch (FileNotFoundException e) { logger.error("Cannot create keyTrustStore Instance", e); return false; } catch (IOException e) { logger.error("Cannot create keyTrustStore Instance", e); return false; } secureTrustManagerFactory = new WaarpSecureTrustManagerFactory(); return true; } /** * Delete a Key from the TrustStore based on its alias * * @param alias * @return True if entry is deleted */ public boolean deleteKeyFromTrustStore(String alias) { try { keyStore.deleteEntry(alias); } catch (KeyStoreException e) { logger.error("Cannot delete Key from keyTrustStore Instance", e); return false; } return true; } /** * Add a Certificate into the TrustStore based on its alias * * @param alias * @param cert * @return True if entry is added */ public boolean setKeytoTrustStore(String alias, Certificate cert) { try { keyStore.setCertificateEntry(alias, cert); } catch (KeyStoreException e) { logger.error("Cannot add Certificate to keyTrustStore Instance", e); return false; } return true; } /** * Save the TrustStore to a file * * @param filename * @return True if keyTrustStore is saved to file */ public boolean saveTrustStore(String filename) { FileOutputStream fos = null; try { fos = new FileOutputStream(filename); try { keyTrustStore.store(fos, getKeyTrustStorePassword()); } catch (KeyStoreException e) { logger.error("Cannot save to file keyTrustStore Instance", e); return false; } catch (NoSuchAlgorithmException e) { logger.error("Cannot save to file keyTrustStore Instance", e); return false; } catch (CertificateException e) { logger.error("Cannot save to file keyTrustStore Instance", e); return false; } catch (IOException e) { logger.error("Cannot save to file keyTrustStore Instance", e); return false; } } catch (FileNotFoundException e) { logger.error("Cannot save to file keyTrustStore Instance", e); return false; } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { } } return true; } /** * Load a certificate from a filename * * @param filename * @return the X509 Certificate from filename * @throws CertificateException * @throws FileNotFoundException */ public static Certificate loadX509Certificate(String filename) throws CertificateException, FileNotFoundException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(filename); try { return cf.generateCertificate(in); } finally { try { in.close(); } catch (IOException e) { } } } /** * @return the certificate Password */ public char[] getCertificatePassword() { if (keyPassword != null) { return keyPassword.toCharArray(); } return "secret".toCharArray(); } /** * @return the KeyStore Password */ public char[] getKeyStorePassword() { if (keyStorePasswd != null) { return keyStorePasswd.toCharArray(); } return "secret".toCharArray(); } /** * @return the KeyTrustStore Password */ public char[] getKeyTrustStorePassword() { if (trustStorePasswd != null) { return trustStorePasswd.toCharArray(); } return "secret".toCharArray(); } /** * @return the secureTrustManagerFactory */ public WaarpSecureTrustManagerFactory getSecureTrustManagerFactory() { return secureTrustManagerFactory; } /** * @return the keyManagerFactory */ public KeyManagerFactory getKeyManagerFactory() { return keyManagerFactory; } }