All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.james.mailet.crypto.SMIMEKeyHolder Maven / Gradle / Ivy

/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you 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 org.apache.james.mailet.crypto;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertificateException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;

import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.bouncycastle.mail.smime.SMIMEException;
import org.bouncycastle.mail.smime.SMIMESignedGenerator;

/**
 * 

Loads a {@link java.security.KeyStore} in memory and keeps it ready for the * cryptographic activity.

*

It has the role of being a simpler intermediate to the crypto libraries. * Uses specifically the Legion of the Bouncy Castle * libraries, particularly for the SMIME activity.

* @version CVS $Revision: 1415429 $ $Date: 2012-11-30 00:52:55 +0200 (Vi, 30 nov 2012) $ * @since 3.0 */ public class SMIMEKeyHolder implements KeyHolder{ /** * Returns the default keystore type as specified in the Java security properties file, * or the string "jks" (acronym for "Java keystore") if no such property exists. * @return The defaultType, issuing a KeyStore.getDefaultType(). */ public static String getDefaultType() { return KeyStore.getDefaultType(); } /** * Holds value of property privateKey. */ private PrivateKey privateKey; /** * Holds value of property certificate. */ private X509Certificate certificate; /** * Holds value of property certStore. */ private CertStore certStore; /** * Creates a new instance of KeyHolder using {@link java.security.KeyStore} related parameters. * @param keyStoreFileName The (absolute) file name of the .keystore file to load the keystore from. * @param keyStorePassword The (optional) password used to check the integrity of the keystore. * If given, it is used to check the integrity of the keystore data, * otherwise, if null, the integrity of the keystore is not checked. * @param keyAlias The alias name of the key. * If missing (is null) and if there is only one key in the keystore, will default to it. * @param keyAliasPassword The password of the alias for recovering the key. * If missing (is null) will default to keyStorePassword. At least one of the passwords must be provided. * @param keyStoreType The type of keystore. * If missing (is null) will default to the keystore type as specified in the Java security properties file, * or the string "jks" (acronym for "Java keystore") if no such property exists. * @throws java.security.KeyStoreException Thrown when the keyAlias is specified and not found, * or is not specified and either no alias is found or more than one is found. * @see java.security.KeyStore#getDefaultType * @see java.security.KeyStore#getInstance(String) * @see java.security.KeyStore#load * @see java.security.KeyStore#getKey * @see java.security.KeyStore#getCertificate */ public SMIMEKeyHolder(String keyStoreFileName, String keyStorePassword, String keyAlias, String keyAliasPassword, String keyStoreType) throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, CertificateException, UnrecoverableKeyException, NoSuchProviderException { 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 = KeyStore.getInstance(keyStoreType); keyStore.load(new BufferedInputStream(new FileInputStream(keyStoreFileName)), keyStorePassword.toCharArray()); Enumeration aliases = keyStore.aliases(); if (keyAlias == null) { if(aliases.hasMoreElements()) { keyAlias = aliases.nextElement(); } else { throw new KeyStoreException("No alias was found in keystore."); } if (aliases.hasMoreElements()) { throw new KeyStoreException("No was given and more than one alias was found in keystore."); } } if (keyAliasPassword == null) { keyAliasPassword = keyStorePassword; } this.privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyAliasPassword.toCharArray()); if (this.privateKey == null) { throw new KeyStoreException("The \"" + keyAlias + "\" PrivateKey alias was not found in keystore."); } this.certificate = (X509Certificate) keyStore.getCertificate(keyAlias); if (this.certificate == null) { throw new KeyStoreException("The \"" + keyAlias + "\" X509Certificate alias was not found in keystore."); } java.security.cert.Certificate[] certificateChain = keyStore.getCertificateChain(keyAlias); ArrayList certList = new ArrayList(); if (certificateChain == null) { certList.add(this.certificate); } else { Collections.addAll(certList, certificateChain); } // create a CertStore containing the certificates we want carried // in the signature this.certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC"); } /** * Getter for property privateKey. * @return Value of property privateKey. */ public PrivateKey getPrivateKey() { return this.privateKey; } /** * Getter for property certificate. * @return Value of property certificate. */ public X509Certificate getCertificate() { return this.certificate; } /** * Getter for property certStore. * @return Value of property certStore. */ public CertStore getCertStore() { return this.certStore; } /** * Creates an SMIMESignedGenerator. Includes a signer private key and certificate, * and a pool of certs and cerls (if any) to go with the signature. * @return The generated SMIMESignedGenerator. */ public SMIMESignedGenerator createGenerator() throws CertStoreException, SMIMEException { // create the generator for creating an smime/signed message SMIMESignedGenerator generator = new SMIMESignedGenerator(); // add a signer to the generator - this specifies we are using SHA1 // the encryption algorithm used is taken from the key generator.addSigner(this.privateKey, this.certificate, SMIMESignedGenerator.DIGEST_SHA1); // add our pool of certs and cerls (if any) to go with the signature generator.addCertificatesAndCRLs(this.certStore); return generator; } /** * Generates a signed MimeMultipart from a MimeMessage. * @param message The message to sign. * @return The signed MimeMultipart. */ public MimeMultipart generate(MimeMessage message) throws CertStoreException, NoSuchAlgorithmException, NoSuchProviderException, SMIMEException { // create the generator for creating an smime/signed MimeMultipart SMIMESignedGenerator generator = createGenerator(); // do it return generator.generate(message, "BC"); } /** * Generates a signed MimeMultipart from a MimeBodyPart. * @param content The content to sign. * @return The signed MimeMultipart. */ public MimeMultipart generate(MimeBodyPart content) throws CertStoreException, NoSuchAlgorithmException, NoSuchProviderException, SMIMEException { // create the generator for creating an smime/signed MimeMultipart SMIMESignedGenerator generator = createGenerator(); // do it return generator.generate(content, "BC"); } /** * Extracts the signer distinguished name (DN) from an X509Certificate. * @param certificate The certificate to extract the information from. * @return The requested information. */ public static String getSignerDistinguishedName(X509Certificate certificate) { return certificate.getSubjectDN().toString(); } /** * Extracts the signer common name (CN=) from an X509Certificate distinguished name. * @param certificate The certificate to extract the information from. * @return The requested information. * @see #getSignerDistinguishedName(X509Certificate) */ public static String getSignerCN(X509Certificate certificate) { return extractAttribute(certificate.getSubjectDN().toString(), "CN="); } /** * Extracts the signer email address (EMAILADDRESS=) from an X509Certificate distinguished name. * @param certificate The certificate to extract the information from. * @return The requested information. * @see #getSignerDistinguishedName(X509Certificate) */ public static String getSignerAddress(X509Certificate certificate) { return extractAttribute(certificate.getSubjectDN().toString(), "EMAILADDRESS="); } /** * Getter for property signerDistinguishedName. * @return Value of property signerDistinguishedName. * @see #getSignerDistinguishedName(X509Certificate) */ public String getSignerDistinguishedName() { return getSignerDistinguishedName(getCertificate()); } /** * Getter for property signerCN. * @return Value of property signerCN. * @see #getSignerCN(X509Certificate) */ public String getSignerCN() { return getSignerCN(getCertificate()); } /** * Getter for property signerAddress. * @return Value of property signerMailAddress. * @see #getSignerAddress(X509Certificate) */ public String getSignerAddress() { return getSignerAddress(getCertificate()); } private static String extractAttribute(String DistinguishedName, String attributeName) { int i = DistinguishedName.indexOf(attributeName); if (i < 0) { return null; } i += attributeName.length(); int j = DistinguishedName.indexOf(",", i); if (j - 1 <= 0) { return null; } return DistinguishedName.substring(i, j).trim(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy