//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/security/cert/CertificateManager.java,v 1.1 2012/04/18 14:10:47 heller Exp $ package de.mendelson.util.security.cert; import de.mendelson.util.MecResourceBundle; import java.security.Key; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; import java.util.Iterator; import java.util.logging.Logger; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import javax.security.auth.x500.X500Principal; /* * Copyright (C) mendelson-e-commerce GmbH Berlin Germany * * This software is subject to the license agreement set forth in the license. * Please read and agree to all terms before using this software. * Other product and brand names are trademarks of their respective owners. */ /** * Helper class to store * @author S.Heller * @version $Revision: 1.1 $ */ public class CertificateManager { private Logger logger = null; private final List<KeystoreCertificate> keyStoreCertificateList = Collections.synchronizedList(new ArrayList<KeystoreCertificate>()); private MecResourceBundle rb = null; private KeystoreStorage storage = null; public CertificateManager(Logger logger) { this.logger = logger; //load resource bundle try { this.rb = (MecResourceBundle) ResourceBundle.getBundle( ResourceBundleCertificateManager.class.getName()); } catch (MissingResourceException e) { throw new RuntimeException("Oops..resource bundle " + e.getClassName() + " not found."); } } public CertificateManager() { this(null); } /**Returns the cert alias that is assigned to the cert/key of the passed fingerprint (SHA1)*/ public String getAliasByFingerprint(byte[] fingerprintSHA1) { KeystoreCertificate cert = this.getKeystoreCertificateByFingerprintSHA1(fingerprintSHA1); //fingerprint not found if (cert == null) { return (null); } else { return (cert.getAlias()); } } /**Returns the cert alias that is assigned to the cert/key of the passed fingerprint (SHA1)*/ public String getAliasByFingerprint(String fingerprintSHA1) { KeystoreCertificate cert = this.getKeystoreCertificateByFingerprintSHA1(fingerprintSHA1); //fingerprint not found if (cert == null) { return (null); } else { return (cert.getAlias()); } } /**Returns the certificate chain for a special alias */ public Certificate[] getCertificateChain(String alias) throws Exception { Certificate[] chain = this.storage.getCertificateChain(alias); return (chain); } /**Returns the X509 certificate assigned to the passed alias */ public X509Certificate getX509Certificate(String alias) throws Exception { X509Certificate certificate = this.storage.getCertificate(alias); if (certificate == null) { throw new Exception(this.rb.getResourceString("alias.notfound", alias)); } return (certificate); } /**Returns the list of available X509 certificates */ public List<X509Certificate> getX509CertificateList() { List<X509Certificate> certList = new ArrayList<X509Certificate>(); synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { certList.add(cert.getX509Certificate()); } } return (certList); } /**Returns the private key for an alias. If the assigned certificate *does not contain a private key an exception is thrown */ public PrivateKey getPrivateKey(String alias) throws Exception { PrivateKey key = (PrivateKey) this.storage.getKey(alias); if (key == null) { throw new Exception(this.rb.getResourceString("alias.hasno.privatekey", alias)); } else { return (key); } } /**Returns the public key for an alias. */ public PublicKey getPublicKey(String alias) throws Exception { return (this.storage.getCertificate(alias).getPublicKey()); } /**Returns the private key for a passed fingerprint (SHA1). If the assigned certificate *does not contain a private key an exception is thrown */ public PrivateKey getPrivateKeyByFingerprintSHA1(byte[] fingerprintStrSHA1) throws Exception { //this will always return the private key if there is a public and a private key entry with the same serial in //the keystore KeystoreCertificate certificate = this.getKeystoreCertificateByFingerprintSHA1(fingerprintStrSHA1); return (this.getPrivateKey(certificate.getAlias())); } /**Returns the private key for a passed fingerprint (SHA1). If the assigned certificate *does not contain a private key an exception is thrown */ public PrivateKey getPrivateKeyByFingerprintSHA1(String fingerprintStrSHA1) throws Exception { //this will always return the private key if there is a public and a private key entry with the same serial in //the keystore KeystoreCertificate certificate = this.getKeystoreCertificateByFingerprintSHA1(fingerprintStrSHA1); return (this.getPrivateKey(certificate.getAlias())); } /**Returns the public key or the private key for an alias. */ public Key getKey(String alias) throws Exception { Key key = this.storage.getKey(alias); if (key == null) { throw new Exception(this.rb.getResourceString("alias.hasno.key", alias)); } else { return (key); } } /**Stores the manages keystore */ public void saveKeystore() throws Throwable { this.storage.save(); //refresh the cert list this.rereadKeystoreCertificates(); } /**Deletes an entry from the actual keystore*/ public void deleteKeystoreEntry(String alias) throws Throwable { this.storage.deleteEntry(alias); } /**Renames an entry in the underlaying keystore. Please remember that PKCS#12 contains no * key pair password, pass null in this case * */ public void renameAlias(String oldAlias, String newAlias, char[] keypairPass) throws Exception { this.storage.renameEntry(oldAlias, newAlias, keypairPass); //rename alias in cert list synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { if (cert.getAlias().equals(oldAlias)) { cert.setAlias(newAlias); break; } } } } /**Refreshes the data */ public void rereadKeystoreCertificates() throws Exception { synchronized (this.keyStoreCertificateList) { Map<String, Certificate> newCertificateMap = this.storage.loadCertificatesFromKeystore(); this.keyStoreCertificateList.clear(); Iterator<String> iterator = newCertificateMap.keySet().iterator(); while (iterator.hasNext()) { KeystoreCertificate certificate = new KeystoreCertificate(); String alias = iterator.next(); certificate.setAlias(alias); X509Certificate foundCertificate = (X509Certificate) newCertificateMap.get(alias); certificate.setCertificate(foundCertificate); try { certificate.setIsKeyPair(getKeystore().isKeyEntry(alias)); } catch (Exception e) { //no problem, thats what we wanted to know certificate.setIsKeyPair(false); if (this.logger != null) { this.logger.warning(e.getMessage()); } } this.keyStoreCertificateList.add(certificate); } } } /**Called from external if the certificate storage has been changed. This method *calls the normal rereadkeystore method but logs the step */ public void rereadKeystoreCertificatesLogged() { try { this.rereadKeystoreCertificates(); if (this.logger != null) { this.logger.fine(this.rb.getResourceString("keystore.reloaded")); } } catch (Exception e) { if (this.logger != null) { this.rb.getResourceString("keystore.read.failure", new Object[]{e.getMessage()}); } } } /**Reads the certificates of the actual key store * @param type keystore typ as defined in the class BCCryptoHelper */ public void loadKeystoreCertificates(KeystoreStorage storage) { this.storage = storage; try { this.rereadKeystoreCertificates(); } catch (Exception e) { if (this.logger != null) { this.rb.getResourceString("keystore.read.failure", new Object[]{e.getMessage()}); } } } /**returns null if the alias does not exist*/ public KeystoreCertificate getKeystoreCertificate(String alias) { synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { if (cert.getAlias().equalsIgnoreCase(alias)) { return (cert); } } } return (null); } /**returns null if a certificate with the issuerDN and the serial does not exist*/ public KeystoreCertificate getKeystoreCertificateByIssuerAndSerial(String issuerDN, String serial) { //it could happen that a cert and a key with the same fingerprint are in the keystore. //Always return the key in this case. KeystoreCertificate foundCert = null; synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { if (cert.getSerialNumberDEC().equals(serial) && cert.getIssuerDN().equals(issuerDN)) { //no entry found so far: always store the found one if (foundCert == null) { foundCert = cert; } else { //entry already found: overwrite it only if the found entry is a key if (cert.getIsKeyPair()) { foundCert = cert; } } } } } return (foundCert); } /**returns null if a certificate with the issuerDN and the serial does not exist*/ public KeystoreCertificate getKeystoreCertificateByIssuerAndSerial(X500Principal issuer, String serialDEC) { //it could happen that a cert and a key with the same fingerprint are in the keystore. //Always return the key in this case. KeystoreCertificate foundCert = null; synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { if (cert.getSerialNumberDEC().equals(serialDEC) && cert.getX509Certificate().getIssuerX500Principal().equals(issuer)) { //no entry found so far: always store the found one if (foundCert == null) { foundCert = cert; } else { //entry already found: overwrite it only if the found entry is a key if (cert.getIsKeyPair()) { foundCert = cert; } } } } } return (foundCert); } /**Throws an exception if the requested certificate does not exist in the keystore*/ public KeystoreCertificate getKeystoreCertificateByFingerprintSHA1NonNull(String fingerprintSHA1) throws Exception { KeystoreCertificate certificate = this.getKeystoreCertificateByFingerprintSHA1(fingerprintSHA1); if (certificate == null) { throw new Exception(this.rb.getResourceString("certificate.not.found.fingerprint", fingerprintSHA1)); } else { return (certificate); } } /**Throws an exception if the requested certificate does not exist in the keystore*/ public KeystoreCertificate getKeystoreCertificateByFingerprintSHA1NonNull(byte[] fingerprintSHA1) throws Exception { KeystoreCertificate certificate = this.getKeystoreCertificateByFingerprintSHA1(fingerprintSHA1); if (certificate == null) { throw new Exception(this.rb.getResourceString("certificate.not.found.fingerprint", KeystoreCertificate.fingerprintBytesToStr(fingerprintSHA1))); } else { return (certificate); } } /**returns null if the fingerprint does not exist*/ public KeystoreCertificate getKeystoreCertificateByFingerprintSHA1(byte[] fingerprintSHA1) { //if there is a prio in the partners certificates, e.g. for AS2/CEM it could happen that //a null request happends here. sample: A decryption request fails, the program tries //a fallback with a second certificate (prio 2) ..but this one is not set --> a null is passed if (fingerprintSHA1 == null) { return (null); } //it could happen that a cert and a key with the same fingerprint are in the keystore. //Always return the key in this case. KeystoreCertificate foundCert = null; synchronized (this.keyStoreCertificateList) { for (KeystoreCertificate cert : this.keyStoreCertificateList) { if (Arrays.equals(fingerprintSHA1, cert.getFingerPrintBytesSHA1())) { //no entry found so far: always store the found one if (foundCert == null) { foundCert = cert; } else { //entry already found: overwrite it only if the found entry is a key if (cert.getIsKeyPair()) { foundCert = cert; } } } } } return (foundCert); } /**returns null if the fingerprint does not exist*/ public KeystoreCertificate getKeystoreCertificateByFingerprintSHA1(String fingerprintSHA1) { //if there is a prio in the partners certificates, e.g. for AS2/CEM it could happen that //a null request happends here. sample: A decryption request fails, the program tries //a fallback with a second certificate (prio 2) ..but this one is not set --> a null is passed if (fingerprintSHA1 == null) { return (null); } byte[] fingerprintSHA1Bytes = KeystoreCertificate.fingerprintStrToBytes(fingerprintSHA1); return (this.getKeystoreCertificateByFingerprintSHA1(fingerprintSHA1Bytes)); } /**Returns the list of certificates*/ public List<KeystoreCertificate> getKeyStoreCertificateList() { synchronized (this.keyStoreCertificateList) { return (this.keyStoreCertificateList); } } /**Passes a logger to the certificate manager. There will be no logging if no logger has been passed*/ public void setLogger(Logger logger) { this.logger = logger; } public char[] getKeystorePass() { return this.storage.getKeystorePass(); } public KeyStore getKeystore() { return (this.storage.getKeystore()); } /** * Returns a map with issuer as key and the available certs as value */ public Map<X500Principal, List<X509Certificate>> getIssuerCertificateMap() throws Exception { Map<X500Principal, List<X509Certificate>> map = new HashMap<X500Principal, List<X509Certificate>>(); synchronized (this.keyStoreCertificateList) { List<KeystoreCertificate> certList = this.getKeyStoreCertificateList(); for (KeystoreCertificate keystoreCertificate : certList) { X509Certificate foundCert = (X509Certificate) keystoreCertificate.getX509Certificate(); if (foundCert != null) { X500Principal subjectDN = foundCert.getSubjectX500Principal(); List<X509Certificate> foundCertList = map.get(subjectDN); if (foundCertList == null) { foundCertList = new ArrayList<X509Certificate>(); foundCertList.add(foundCert); } else { if (!foundCertList.contains(foundCert)) { foundCertList.add(foundCert); } } map.put(subjectDN, foundCertList); } } return map; } } public void setKeyEntry(String alias, Key key, Certificate[] chain) throws Throwable { KeyStore keystore = this.getKeystore(); keystore.setKeyEntry(alias, key, this.getKeystorePass(), chain); this.saveKeystore(); } }