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

net.markenwerk.utils.mail.smime.SmimeKeyStore Maven / Gradle / Ivy

/*
 * Copyright (C) 2015 Torsten Krause.
 * 
 * This file is part of 'A S/MIME library for JavaMail', hereafter
 * called 'this library', identified by the following coordinates:
 * 
 *    groupID: net.markenwerk
 *    artifactId: utils-mail-smime
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 * 
 * See the LICENSE and NOTICE files in the root directory for further
 * information.
 */
package net.markenwerk.utils.mail.smime;

import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

/**
 * A wrapper around a {@link KeyStore} that can be initialized with a PKCS12
 * keystore and is used to obtain {@link SmimeKey SmimeKeys}.
 * 
 * @author Allen Petersen (akp at sourceforge dot net)
 * @author Torsten Krause (tk at markenwerk dot net)
 * @since 1.0.0
 */
public class SmimeKeyStore {

	private KeyStore keyStore = null;

	/**
	 * Creates a new {@code SmimeKeyStore} by loading a PKCS12 keystore from a
	 * the given input stream.
	 * 
	 * 

* The character array holding the password is overwritten with {@code 0s} * after it has been used. * * @param stream * The {@link InputStream} to read the PKCS12 keystore from. * @param password * The password to unlock the PKCS12 keystore with. */ public SmimeKeyStore(InputStream stream, char[] password) { this(stream, password, true); } /** * Creates a new {@code SmimeKeyStore} by loading a PKCS12 keystore from a * the given input stream. * *

* If {@code discardPassword} is set to {@code true}, the character array * holding the password is overwritten with {@code 0s} after it has been * used. * * @param stream * The {@link InputStream} to read the PKCS12 keystore from. * @param password * The password to unlock the PKCS12 keystore with. * @param discardPassword * Whether to overwrite the {@code char[]} holding the password * after it has been used. */ public SmimeKeyStore(InputStream stream, char[] password, boolean discardPassword) { try { keyStore = KeyStore.getInstance("PKCS12", "BC"); keyStore.load(stream, password); } catch (Exception e) { throw new SmimeException("Couldn't initialize SmimeKeyStore", e); } finally { if (discardPassword) { overwrite(password); } } } private void overwrite(char[] password) { if (null != password) { for (int i = 0, n = password.length; i < n; i++) { password[i] = 0; } } } /** * Returns the number of entries in the underlying PKCS12 keystore. * * @return The number of entries in the underlying {@link KeyStore}. * */ public int size() { try { return keyStore.size(); } catch (KeyStoreException e) { throw new SmimeException("Couldn't retrieve the number of entries from SmimeKeyStore", e); } } /** * Returns the S/MIME key associated with the given alias, using the given * password to recover it. * *

* The character array holding the password is overwritten with {@code 0s} * after it has been used. * * @param alias * The alias. * @param password * The password to unlock the {@link PrivateKey} keystore with. * * @return The requested {@link SmimeKey}, or null if the given alias does * not exist or does not identify a private key entry. */ public SmimeKey getPrivateKey(String alias, char[] password) { return getPrivateKey(alias, password, true); } /** * Returns the S/MIME key associated with the given alias, using the given * password to recover it. * *

* If {@code discardPassword} is set to {@code true}, the character array * holding the password is overwritten with {@code 0s} after it has been * used. * * @param alias * The alias. * @param password * The password to unlock the {@link PrivateKey} keystore with. * @param discardPassword * Whether to overwrite the {@code char[]} holding the password * after it has been used. * * @return The requested {@link SmimeKey}, or null if the given alias does * not exist or does not identify a private key entry. */ public SmimeKey getPrivateKey(String alias, char[] password, boolean discardPassword) { try { if (containsPrivateKeyAlias(alias)) { PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password); Certificate[] certificateChain = keyStore.getCertificateChain(alias); return new SmimeKey(privateKey, copy(certificateChain)); } return null; } catch (Exception e) { throw new SmimeException("Couldn't recover SmimeKey from SmimeKeyStore", e); } finally { if (discardPassword) { overwrite(password); } } } private X509Certificate[] copy(Certificate[] certificateChain) { X509Certificate[] x509certificateChain = new X509Certificate[certificateChain.length]; for (int i = 0, n = certificateChain.length; i < n; i++) { x509certificateChain[i] = (X509Certificate) certificateChain[i]; } return x509certificateChain; } /** * Returns a set containing all aliases listed in the PKCS12 keystore. * * @return A {@link Collections#unmodifiableSet(Set) unmodifiable set} of * aliases. */ public Set getPrivateKeyAliases() { try { Enumeration aliases = keyStore.aliases(); Set aliasSet = new HashSet(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); if (keyStore.isKeyEntry(alias)) aliasSet.add(alias); } return Collections.unmodifiableSet(aliasSet); } catch (Exception e) { throw new SmimeException("Couldn't recover aliases from SmimeKeyStore", e); } } /** * Checks if the given alias exists in the PKCS12 keystore. * * @param alias * The alias to look for. * * @return {@code true} if the alias exists, {@code false} otherwise. */ public boolean containsPrivateKeyAlias(String alias) { try { return keyStore.isKeyEntry(alias); } catch (Exception e) { throw new SmimeException("Couldn't recover aliases from SmimeKeyStore", e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy