/** * Copyright 2016 Sean Kavanagh - sean.p.kavanagh6@gmail.com * * 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. */ package com.keybox.manage.util; import com.keybox.common.util.AppConfig; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.KeyStore; /** * Utility class for creating entries in keystore */ public class KeyStoreUtil { private static Logger log = LoggerFactory.getLogger(KeyStoreUtil.class); private static KeyStore keyStore = null; private static final String keyStoreFile = KeyStoreUtil.class.getClassLoader().getResource(".").getPath() + "/keybox.jceks"; private static final char[] KEYSTORE_PASS = new char[]{ 'G', '~', 'r', 'x', 'Z', 'E', 'w', 'f', 'a', '[', '!', 'f', 'Z', 'd', '*', 'L', '8', 'm', 'h', 'u', '#', 'j', '9', ':', '~', ';', 'U', '>', 'O', 'i', '8', 'r', 'C', '}', 'f', 't', '%', '[', 'H', 'h', 'M', '&', 'K', ':', 'l', '5', 'c', 'H', '6', 'r', 'A', 'E', '.', 'F', 'Y', 'W', '}', '{', '*', '8', 'd', 'E', 'C', 'A', '6', 'F', 'm', 'j', 'u', 'A', 'Q', '%', '{', '/', '@', 'm', '&', '5', 'S', 'q', '4', 'Q', '+', 'Y', '|', 'X', 'W', 'z', '8', '<', 'j', 'd', 'a', '}', '`', '0', 'N', 'B', '3', 'i', 'v', '5', 'U', ' ', '2', 'd', 'd', '(', '&', 'J', '_', '9', 'o', '(', '2', 'I', '`', ';', '>', '#', '$', 'X', 'j', '&', '&', '%', '>', '#', '7', 'q', '>', ')', 'L', 'A', 'v', 'h', 'j', 'i', '8', '~', ')', 'a', '~', 'W', '/', 'l', 'H', 'L', 'R', '+', '\\', 'i', 'R', '_', '+', 'y', 's', '0', 'n', '\'', '=', '{', 'B', ':', 'l', '1', '%', '^', 'd', 'n', 'H', 'X', 'B', '$', 'f', '"', '#', ')', '{', 'L', '/', 'q', '\'', 'O', '%', 's', 'M', 'Q', ']', 'D', 'v', ';', 'L', 'C', 'd', '?', 'D', 'l', 'h', 'd', 'i', 'N', '4', 'R', '>', 'O', ';', '$', '(', '4', '-', '0', '^', 'Y', ')', '5', 'V', 'M', '7', 'S', 'a', 'c', 'D', 'C', 'w', 'A', 'o', 'n', 's', 'r', '*', 'G', '[', 'l', 'h', '$', 'U', 's', '_', 'D', 'f', 'X', '~', '.', '7', 'B', 'A', 'E', '(', '#', ']', ':', '`', ',', 'k', 'y'}; private static int KEYLENGTH = AppConfig.getProperty("use256EncryptionKey").equals("true") ? 256 :128; //Alias for encryption keystore public static final String ENCRYPTION_KEY_ALIAS = "KEYBOX-ENCRYPTION_KEY"; static { File f = new File(keyStoreFile); //load or create keystore if (f.isFile() && f.canRead()) { try { //load existing keystore keyStore = KeyStore.getInstance("JCEKS"); FileInputStream keyStoreInputStream = new FileInputStream(f); keyStore.load(keyStoreInputStream, KEYSTORE_PASS); } catch (Exception ex) { log.error(ex.toString(), ex); } //create keystore } else { initializeKeyStore(); } } /** * get secret entry for alias * * @param alias keystore secret alias * @return secret byte array */ public static byte[] getSecretBytes(String alias) { byte[] value = null; try { KeyStore.SecretKeyEntry entry = (KeyStore.SecretKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(KEYSTORE_PASS)); value = entry.getSecretKey().getEncoded(); } catch (Exception ex) { log.error(ex.toString(), ex); } return value; } /** * get secret entry for alias * * @param alias keystore secret alias * @return secret string */ public static String getSecretString(String alias) { String value = null; try { KeyStore.SecretKeyEntry entry = (KeyStore.SecretKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(KEYSTORE_PASS)); value = new String(entry.getSecretKey().getEncoded()); } catch (Exception ex) { log.error(ex.toString(), ex); } return value; } /** * set secret in keystore * * @param alias keystore secret alias * @param secret keystore entry */ public static void setSecret(String alias, byte[] secret) { KeyStore.ProtectionParameter protectionParameter = new KeyStore.PasswordProtection(KEYSTORE_PASS); try { SecretKeySpec secretKey = new SecretKeySpec(secret, 0, secret.length, "AES"); KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(secretKey); keyStore.setEntry(alias, secretKeyEntry, protectionParameter); } catch (Exception ex) { log.error(ex.toString(), ex); } } /** * set secret in keystore * * @param alias keystore secret alias * @param secret keystore entry */ public static void setSecret(String alias, String secret) { setSecret(alias, secret.getBytes()); } /** * delete existing and create new keystore */ public static void resetKeyStore() { File file = new File(keyStoreFile); try { if (file.exists()) { FileUtils.forceDelete(file); } } catch (Exception ex) { log.error(ex.toString(), ex); } //create new keystore initializeKeyStore(); } /** * create new keystore */ private static void initializeKeyStore() { try { keyStore = KeyStore.getInstance("JCEKS"); //create keystore keyStore.load(null, KEYSTORE_PASS); //set encryption key KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(KEYLENGTH); KeyStoreUtil.setSecret(KeyStoreUtil.ENCRYPTION_KEY_ALIAS, keyGenerator.generateKey().getEncoded()); //write keystore FileOutputStream fos = new FileOutputStream(keyStoreFile); keyStore.store(fos, KEYSTORE_PASS); fos.close(); } catch (Exception ex) { log.error(ex.toString(), ex); } } }