FileDocCategorySizeDatePackage
KeyStoreHolder.javaAPI DocApache James 2.3.19667Fri Jan 12 12:56:26 GMT 2007org.apache.james.security

KeyStoreHolder

public class KeyStoreHolder extends Object
This class is used to handle in a simple way a keystore that contains a set of trusted certificates. It loads the set from the specified keystore (type, location and password are supplied during the object's creation) and it is able to verify a s/mime signature, also checking if the signer's certificate is trusted or not.

Fields Summary
protected KeyStore
keyStore
Constructors Summary
public KeyStoreHolder()

        // this is the default password of the sun trusted certificate store.
        this("changeit");
    
public KeyStoreHolder(String password)

        this(System.getProperty("java.home")+"/lib/security/cacerts".replace('/", File.separatorChar), password, KeyStore.getDefaultType());
    
public KeyStoreHolder(String keyStoreFileName, String keyStorePassword, String keyStoreType)

        
        if (keyStorePassword == null) keyStorePassword = "";

        try {
            InitJCE.init();
        } catch (InstantiationException e) {
            NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
            ex.initCause(e);
            throw ex;
        } catch (IllegalAccessException e) {
            NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
            ex.initCause(e);
            throw ex;
        } catch (ClassNotFoundException e) {
            NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
            ex.initCause(e);
            throw ex;
        }
        
        if (keyStoreType == null) {
            keyStoreType = KeyStore.getDefaultType();
        }
        
        keyStore = KeyStore.getInstance(keyStoreType);        
        keyStore.load(new BufferedInputStream(new FileInputStream(keyStoreFileName)), keyStorePassword.toCharArray());
        if (keyStore.size() == 0) throw new KeyStoreException("The keystore must be not empty");
    
Methods Summary
private static java.security.cert.CertPathverifyCertificate(java.security.cert.X509Certificate cert, java.security.cert.CertStore store, java.security.KeyStore trustedStore)
Verifies the validity of the given certificate, checking its signature against the issuer's certificate.

param
cert the certificate to validate
param
certStore other certificates that can be used to create a chain of trust to a known trusted certificate.
param
trustedStore list of trusted (usually self-signed) certificates.
return
true if the certificate's signature is valid and can be validated using a trustedCertficated, false otherwise.

        
        if (cert == null || store == null || trustedStore == null) throw new IllegalArgumentException("cert == "+cert+", store == "+store+", trustedStore == "+trustedStore);
        
        CertPathBuilder pathBuilder;
        
        // I create the CertPathBuilder object. It will be used to find a
        // certification path that starts from the signer's certificate and
        // leads to a trusted root certificate.
        try {
            pathBuilder = CertPathBuilder.getInstance("PKIX", "BC");
        } catch (Exception e) {
            throw new MessagingException("Error during the creation of the certpathbuilder.", e);
        }
        
        X509CertSelector xcs = new X509CertSelector();
        xcs.setCertificate(cert);
        PKIXBuilderParameters params = new PKIXBuilderParameters(trustedStore, xcs);
        params.addCertStore(store);
        params.setRevocationEnabled(false);
        
        try {
            CertPathBuilderResult result = pathBuilder.build(params);
            CertPath path = result.getCertPath();
            return path;
        } catch (CertPathBuilderException e) {
            // A certification path is not found, so null is returned.
            return null;
        } catch (InvalidAlgorithmParameterException e) {
            // If this exception is thrown an error has occured during
            // certification path search. 
            throw new MessagingException("Error during the certification path search.", e);
        }
    
public java.util.ListverifySignatures(org.bouncycastle.mail.smime.SMIMESigned signed)
Verifies the signature of a SMIME message. It checks also if the signer's certificate is trusted using the loaded keystore as trusted certificate store.

param
signed the signed mail to check.
return
a list of SMIMESignerInfo which keeps the data of each mail signer.
throws
Exception
throws
MessagingException

        CertStore certs = signed.getCertificatesAndCRLs("Collection", "BC");
        SignerInformationStore siginfo = signed.getSignerInfos();
        Collection sigCol = siginfo.getSigners();
        Iterator sigIterator = sigCol.iterator();
        List result = new ArrayList(sigCol.size());
        // I iterate over the signer collection 
        // checking if the signatures put
        // on the message are valid.
        for (int i=0;sigIterator.hasNext();i++) {
            SignerInformation info = (SignerInformation) sigIterator.next();
            // I get the signer's certificate
            Collection certCollection = certs.getCertificates(info.getSID());
            Iterator certIter  =certCollection.iterator();
            if (certIter.hasNext()) {
                X509Certificate signerCert = (X509Certificate) certIter.next();
                // The issuer's certifcate is searched in the list of trusted certificate.
                CertPath path = verifyCertificate(signerCert, certs, keyStore);

                try {
                    // if the signature is valid the SMIMESignedInfo is 
                    // created using "true" as last argument. If it is  
                    // invalid an exception is thrown by the "verify" method
                    // and the SMIMESignerInfo is created with "false".
                    //
                    // The second argument "path" is not null if the 
                    // certificate can be trusted (it can be connected 
                    // by a chain of trust to a trusted certificate), null
                    // otherwise.
                    if (info.verify(signerCert, "BC")) {
                        result.add(new SMIMESignerInfo(signerCert, path, true));
                    }
                } catch (Exception e) { 
                    result.add(new SMIMESignerInfo(signerCert,path, false)); 
                }
            }
        }
        return result;