/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * 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. * * Initial developer(s): Ludovic Launer * Contributor(s): */ package com.continuent.tungsten.common.security; import java.io.FileInputStream; import java.security.Key; import java.security.KeyPair; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; import java.text.MessageFormat; import java.util.Enumeration; import javax.crypto.Cipher; import javax.xml.bind.DatatypeConverter; import org.apache.log4j.Logger; import com.continuent.tungsten.common.config.cluster.ConfigurationException; import com.continuent.tungsten.common.jmx.ServerRuntimeException; /** * Utility class to cipher / uncipher critical information based on public / * private key encryption * * @author <a href="mailto:ludovic.launer@continuent.com">Ludovic Launer</a> * @version 1.0 */ public class Encryptor { private static final Logger logger = Logger.getLogger(Encryptor.class); private AuthenticationInfo authenticationInfo = null; /** * Creates a new <code>Encryptor</code> object * * @param authenticationInfo * @throws ConfigurationException * @throws ServerRuntimeException */ public Encryptor(AuthenticationInfo authenticationInfo) throws ServerRuntimeException, ConfigurationException { this.authenticationInfo = authenticationInfo; // --- Check parameters --- this.authenticationInfo.checkAndCleanAuthenticationInfo(); } /** * Retrieve public and/or private keys from Keystore/Strustore Uses the * first Alias found in the keystore * * @return KeyPair */ public KeyPair getKeys(String storeLocation, String storePassword) { FileInputStream storeFile; KeyPair keyPair = null; try { storeFile = new FileInputStream(storeLocation); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(storeFile, storePassword.toCharArray()); Enumeration<String> listAliases = keystore.aliases(); // --- Get first alias --- String alias = null; if (listAliases.hasMoreElements()) alias = listAliases.nextElement(); else { // Store does not contain any aliases String errorMessage = MessageFormat.format( "Store is empty. Does not contain any aliases: {0}", storeLocation); throw new ConfigurationException(errorMessage); } // Get certificate of public key Certificate cert = keystore.getCertificate(alias); // Get public key PublicKey publicKey = cert.getPublicKey(); Key key = keystore.getKey(alias, storePassword.toCharArray()); if (key instanceof PrivateKey) { keyPair = new KeyPair(publicKey, (PrivateKey) key); } else { keyPair = new KeyPair(publicKey, null); } } catch (Exception e) { String msg = MessageFormat.format( "Cannot retrieve key from: {0} Reason={1}", storeLocation, e.getMessage()); logger.error(msg); throw new ServerRuntimeException(msg, e); } return keyPair; } /** * Get the Public key from a TrustStore * * @return Public key from the Truststore */ public PublicKey getPublicKey_from_Truststore() { KeyPair keyPair = this.getKeys( this.authenticationInfo.getTruststoreLocation(), this.authenticationInfo.getTruststorePassword()); return keyPair.getPublic(); } /** * Get the Public and Private key from a KeyStore * * @return PrivateKey extracted from the Keystore */ public PrivateKey getPrivateKey_from_KeyStore() { KeyPair keyPair = this.getKeys( this.authenticationInfo.getKeystoreLocation(), this.authenticationInfo.getKeystorePassword()); return keyPair.getPrivate(); } /** * Encrypt a String using public key located in truststore. * * @param message to be encrypted * @return Base64 encoded and encryoted message */ public String encrypt(String message) { String base64 = null; PublicKey publicKey = this.getPublicKey_from_Truststore(); try { Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // Gets the raw bytes to encrypt, UTF8 is needed for // having a standard character set byte[] stringBytes = message.getBytes("UTF8"); // Encrypt using the cypher byte[] raw = cipher.doFinal(stringBytes); // Converts to base64 for easier display. base64 = DatatypeConverter.printBase64Binary(raw); } catch (Exception e) { String msg = MessageFormat.format( "Cannot encrypt message. Error= {0}", e.getMessage()); logger.error(msg); throw new ServerRuntimeException(msg, e); } return base64; } /** * Decrypt a String using private key located in KeyStore. * * @param encryptedMessage * @return Decrypted String * @throws ConfigurationException */ public String decrypt(String encryptedMessage) throws ConfigurationException { if (encryptedMessage == null) return null; String clearMessage = null; PrivateKey privateKey = this.getPrivateKey_from_KeyStore(); try { Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); // Decode the BASE64 coded message byte[] raw = DatatypeConverter.parseBase64Binary(encryptedMessage); // Decode the message byte[] stringBytes = cipher.doFinal(raw); // converts the decoded message to a String clearMessage = new String(stringBytes, "UTF8"); } catch (Exception e) { String msg = MessageFormat.format( "Cannot decrypt message. Error= {0}",e); logger.error(msg); throw new ConfigurationException(msg); } return clearMessage; } }