package org.cagrid.gaards.dorian.ca; import gov.nih.nci.cagrid.common.FaultHelper; import java.io.ByteArrayInputStream; import java.security.Key; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.security.cert.X509Certificate; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import org.cagrid.gaards.pki.CertUtil; import org.cagrid.gaards.pki.KeyUtil; public class EracomCertificateAuthority extends CertificateAuthority implements WrappingCertificateAuthority { public static final String CA_ALIAS = "dorianca"; public static final String WRAPPER_KEY_ALIAS = "dorian-wrapper-key"; public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA"; public static final String SLOT_PROPERTY = "slot"; private Provider provider; private KeyStore keyStore; private Key wrapper; private boolean isInit = false; public EracomCertificateAuthority(EracomCertificateAuthorityProperties properties) throws CertificateAuthorityFault { super(properties); try { int slot = properties.getSlot(); provider = (Provider) Class.forName("au.com.eracom.crypto.provider.slot" + slot + ".ERACOMProvider") .newInstance(); Security.addProvider(provider); keyStore = KeyStore.getInstance("CRYPTOKI", provider.getName()); keyStore.load(null, properties.getCertificateAuthorityPassword().toCharArray()); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Error initializing the Dorian Certificate Authority."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public String getSignatureAlgorithm() { return SIGNATURE_ALGORITHM; } public String getCACredentialsProvider() { return getProvider().getName(); } protected Provider getProvider() { return provider; } protected KeyStore getKeyStore() { return keyStore; } protected X509Certificate convert(X509Certificate cert) throws Exception { String str = CertUtil.writeCertificate(cert); return CertUtil.loadCertificate(str); } public void deleteCACredentials() throws CertificateAuthorityFault { try { getKeyStore().deleteEntry(CA_ALIAS); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not delete the CA credentials."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } protected X509Certificate getCertificate() throws CertificateAuthorityFault { try { if (!hasCACredentials()) { CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("The CA certificate does not exist."); throw fault; } else { return convert((X509Certificate) getKeyStore().getCertificate(CA_ALIAS)); } } catch (CertificateAuthorityFault f) { throw f; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not obtain the certificate."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public PrivateKey getPrivateKey(String password) throws CertificateAuthorityFault, NoCACredentialsFault { try { if (!hasCACredentials()) { CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("The CA private key does not exist."); throw fault; } else { return (PrivateKey) getKeyStore().getKey(CA_ALIAS, null); } } catch (CertificateAuthorityFault f) { throw f; } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not obtain the private key."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public String getUserCredentialsProvider() { return getProvider().getName(); } public boolean hasCACredentials() throws CertificateAuthorityFault { try { return getKeyStore().containsAlias(CA_ALIAS); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("An unexpected error occurred, could determin if credentials exist."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public void setCACredentials(X509Certificate cert, PrivateKey key, String password) throws CertificateAuthorityFault { try { getKeyStore().setKeyEntry(CA_ALIAS, key, null, new X509Certificate[]{cert}); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("Unexpected Error, could not store CA credentials."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } protected void init() throws CertificateAuthorityFault { try { if (!isInit) { if (keyStore.containsAlias(WRAPPER_KEY_ALIAS)) { wrapper = keyStore.getKey(WRAPPER_KEY_ALIAS, null); } else { KeyGenerator generator1 = KeyGenerator.getInstance("AES", provider); generator1.init(256, new SecureRandom()); keyStore.setKeyEntry(WRAPPER_KEY_ALIAS, generator1.generateKey(), null, null); wrapper = keyStore.getKey(WRAPPER_KEY_ALIAS, null); } isInit = true; } } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("An unexpected error occurred, could not add certificate."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public PrivateKey unwrap(WrappedKey key) throws CertificateAuthorityFault { try { init(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); IvParameterSpec dps = new IvParameterSpec(key.getIV()); cipher.init(Cipher.DECRYPT_MODE, wrapper, dps); byte[] output = cipher.doFinal(key.getWrappedKeyData()); return KeyUtil.loadPrivateKey(new ByteArrayInputStream(output), null); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("An unexpected error occurred unwrapping a key."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } public WrappedKey wrap(PrivateKey key) throws CertificateAuthorityFault { try { init(); byte[] input = KeyUtil.writePrivateKey(key, (String) null).getBytes(); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", provider); cipher.init(Cipher.ENCRYPT_MODE, wrapper); byte[] wrappedKey = cipher.doFinal(input); byte[] iv = cipher.getIV(); return new WrappedKey(wrappedKey, iv); } catch (Exception e) { logError(e.getMessage(), e); CertificateAuthorityFault fault = new CertificateAuthorityFault(); fault.setFaultString("An unexpected error occurred wrapping a key."); FaultHelper helper = new FaultHelper(fault); helper.addFaultCause(e); fault = (CertificateAuthorityFault) helper.getFault(); throw fault; } } }