001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015 ForgeRock AS. 015 */ 016package org.forgerock.audit.secure; 017 018import java.security.KeyStore; 019import java.security.KeyStoreException; 020import java.security.NoSuchAlgorithmException; 021import java.security.PrivateKey; 022import java.security.PublicKey; 023import java.security.UnrecoverableEntryException; 024import java.security.cert.Certificate; 025 026import javax.crypto.SecretKey; 027 028/** 029 * Decorate a {@link KeyStoreHandler} in order to add some commons utility methods to read or write keystore's entries. 030 */ 031public class KeyStoreHandlerDecorator implements KeyStoreHandler { 032 033 private final KeyStoreHandler delegate; 034 035 /** 036 * Constructs a new {@literal KeyStoreHandlerDecorator} 037 * @param delegate the {@literal KeyStoreHandler} to decorate. 038 */ 039 public KeyStoreHandlerDecorator(KeyStoreHandler delegate) { 040 this.delegate = delegate; 041 } 042 043 /** 044 * Writes to the secret storage using the same password than the {@literal KeyStoreHandler}. 045 * 046 * @param secretKey 047 * The data to be written to the secret storage 048 * @param alias 049 * The kind of cryptoMaterial, whether it is a signature or a key 050 * @throws SecureStorageException 051 * if it fails to write secret data from secret store 052 */ 053 public void writeToKeyStore(SecretKey secretKey, String alias) throws SecureStorageException { 054 writeToKeyStore(secretKey, alias, getPassword()); 055 } 056 057 /** 058 * Writes to the secret storage. 059 * 060 * @param secretKey 061 * The data to be written to the secret storage 062 * @param alias 063 * The kind of cryptoMaterial, whether it is a signature or a key 064 * @param password 065 * The password to read the key 066 * @throws SecureStorageException 067 * if it fails to write secret data from secret store 068 */ 069 public void writeToKeyStore(SecretKey secretKey, String alias, String password) throws SecureStorageException { 070 // Note that it need JCEKS to support secret keys. 071 try { 072 KeyStore store = getStore(); 073 if (store.containsAlias(alias)) { 074 store.deleteEntry(alias); 075 } 076 KeyStore.SecretKeyEntry secKeyEntry = new KeyStore.SecretKeyEntry(secretKey); 077 KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password.toCharArray()); 078 store.setEntry(alias, secKeyEntry, params); 079 } catch (Exception ex) { 080 throw new SecureStorageException(ex); 081 } 082 } 083 084 public PublicKey readPublicKeyFromKeyStore(String alias) throws SecureStorageException { 085 try { 086 KeyStore store = getStore(); 087 Certificate certificate = store.getCertificate(alias); 088 return certificate.getPublicKey(); 089 } catch (KeyStoreException ex) { 090 throw new SecureStorageException("Error when reading public key: " + alias, ex); 091 } 092 } 093 094 public PrivateKey readPrivateKeyFromKeyStore(String alias) throws SecureStorageException { 095 return readPrivateKeyFromKeyStore(alias, getPassword()); 096 } 097 098 public PrivateKey readPrivateKeyFromKeyStore(String alias, String password) throws SecureStorageException { 099 try { 100 KeyStore store = getStore(); 101 KeyStore.ProtectionParameter params = password != null ? 102 new KeyStore.PasswordProtection(password.toCharArray()) : null; 103 KeyStore.PrivateKeyEntry keyentry = (KeyStore.PrivateKeyEntry) store.getEntry(alias, params); 104 return keyentry != null ? keyentry.getPrivateKey() : null; 105 } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException ex) { 106 throw new SecureStorageException(ex); 107 } 108 } 109 110 public SecretKey readSecretKeyFromKeyStore(String alias) throws SecureStorageException { 111 return readSecretKeyFromKeyStore(alias, getPassword()); 112 } 113 114 public SecretKey readSecretKeyFromKeyStore(String alias, String password) throws SecureStorageException { 115 try { 116 KeyStore store = getStore(); 117 KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password.toCharArray()); 118 KeyStore.SecretKeyEntry keyentry = (KeyStore.SecretKeyEntry) store.getEntry(alias, params); 119 return keyentry != null ? keyentry.getSecretKey() : null; 120 } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) { 121 throw new SecureStorageException(e); 122 } 123 } 124 125 @Override 126 public KeyStore getStore() { 127 return delegate.getStore(); 128 } 129 130 @Override 131 public void setStore(KeyStore keystore) throws Exception { 132 delegate.setStore(keystore); 133 } 134 135 @Override 136 public String getPassword() { 137 return delegate.getPassword(); 138 } 139 140 @Override 141 public String getLocation() { 142 return delegate.getLocation(); 143 } 144 145 @Override 146 public String getType() { 147 return delegate.getType(); 148 } 149 150 @Override 151 public void store() throws Exception { 152 delegate.store(); 153 } 154 155}