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

org.simplejavamail.utils.mail.smime.SmimeKeyStore Maven / Gradle / Ivy

There is a newer version: 2.3.11
Show newest version
/*
 * Copyright © 2021 Benny Bottema ([email protected])
 *
 * Licensed 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.simplejavamail.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 final KeyStore keyStore;

	/**
	 * Creates a new {@code SmimeKeyStore} by loading a PKCS12 keystore from
	 * 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 * 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