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

panda.net.ssl.KeyManagers Maven / Gradle / Ivy

package panda.net.ssl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import javax.net.ssl.KeyManager;
import javax.net.ssl.X509ExtendedKeyManager;

import panda.net.io.Util;

/**
 * General KeyManager utilities
 * 

* How to use with a client certificate: * *

 * KeyManager km = KeyManagerUtils.createClientKeyManager("JKS",
 *     "/path/to/privatekeystore.jks","storepassword",
 *     "privatekeyalias", "keypassword");
 * FTPSClient cl = new FTPSClient();
 * cl.setKeyManager(km);
 * cl.connect(...);
 * 
* * If using the default store type and the key password is the same as the store password, these * parameters can be omitted.
* If the desired key is the first or only key in the keystore, the keyAlias parameter can be * omitted, in which case the code becomes: * *
 * KeyManager km = KeyManagerUtils.createClientKeyManager(
 *     "/path/to/privatekeystore.jks","storepassword");
 * FTPSClient cl = new FTPSClient();
 * cl.setKeyManager(km);
 * cl.connect(...);
 * 
*/ public final class KeyManagers { private static final String DEFAULT_STORE_TYPE = KeyStore.getDefaultType(); private KeyManagers() { // Not instantiable } /** * Create a client key manager which returns a particular key. Does not handle server keys. * * @param ks the keystore to use * @param keyAlias the alias of the key to use, may be {@code null} in which case the first key * entry alias is used * @param keyPass the password of the key to use * @return the customised KeyManager * @throws GeneralSecurityException if there is a problem creating the keystore */ public static KeyManager createClientKeyManager(KeyStore ks, String keyAlias, String keyPass) throws GeneralSecurityException { ClientKeyStore cks = new ClientKeyStore(ks, keyAlias != null ? keyAlias : findAlias(ks), keyPass); return new X509KeyManager(cks); } /** * Create a client key manager which returns a particular key. Does not handle server keys. * * @param storeType the type of the keyStore, e.g. "JKS" * @param storePath the path to the keyStore * @param storePass the keyStore password * @param keyAlias the alias of the key to use, may be {@code null} in which case the first key * entry alias is used * @param keyPass the password of the key to use * @return the customised KeyManager * @throws GeneralSecurityException if there is a problem creating the keystore * @throws IOException if there is a problem creating the keystore */ public static KeyManager createClientKeyManager(String storeType, File storePath, String storePass, String keyAlias, String keyPass) throws IOException, GeneralSecurityException { KeyStore ks = loadStore(storeType, storePath, storePass); return createClientKeyManager(ks, keyAlias, keyPass); } /** * Create a client key manager which returns a particular key. Does not handle server keys. Uses * the default store type and assumes the key password is the same as the store password * * @param storePath the path to the keyStore * @param storePass the keyStore password * @param keyAlias the alias of the key to use, may be {@code null} in which case the first key * entry alias is used * @return the customised KeyManager * @throws IOException if there is a problem creating the keystore * @throws GeneralSecurityException if there is a problem creating the keystore */ public static KeyManager createClientKeyManager(File storePath, String storePass, String keyAlias) throws IOException, GeneralSecurityException { return createClientKeyManager(DEFAULT_STORE_TYPE, storePath, storePass, keyAlias, storePass); } /** * Create a client key manager which returns a particular key. Does not handle server keys. Uses * the default store type and assumes the key password is the same as the store password. The * key alias is found by searching the keystore for the first private key entry * * @param storePath the path to the keyStore * @param storePass the keyStore password * @return the customised KeyManager * @throws IOException if there is a problem creating the keystore * @throws GeneralSecurityException if there is a problem creating the keystore */ public static KeyManager createClientKeyManager(File storePath, String storePass) throws IOException, GeneralSecurityException { return createClientKeyManager(DEFAULT_STORE_TYPE, storePath, storePass, null, storePass); } private static KeyStore loadStore(String storeType, File storePath, String storePass) throws KeyStoreException, IOException, GeneralSecurityException { KeyStore ks = KeyStore.getInstance(storeType); FileInputStream stream = null; try { stream = new FileInputStream(storePath); ks.load(stream, storePass.toCharArray()); } finally { Util.closeQuietly(stream); } return ks; } private static String findAlias(KeyStore ks) throws KeyStoreException { Enumeration e = ks.aliases(); while (e.hasMoreElements()) { String entry = e.nextElement(); if (ks.isKeyEntry(entry)) { return entry; } } throw new KeyStoreException("Cannot find a private key entry"); } private static class ClientKeyStore { private final X509Certificate[] certChain; private final PrivateKey key; private final String keyAlias; ClientKeyStore(KeyStore ks, String keyAlias, String keyPass) throws GeneralSecurityException { this.keyAlias = keyAlias; this.key = (PrivateKey)ks.getKey(this.keyAlias, keyPass.toCharArray()); Certificate[] certs = ks.getCertificateChain(this.keyAlias); X509Certificate[] X509certs = new X509Certificate[certs.length]; for (int i = 0; i < certs.length; i++) { X509certs[i] = (X509Certificate)certs[i]; } this.certChain = X509certs; } final X509Certificate[] getCertificateChain() { return this.certChain; } final PrivateKey getPrivateKey() { return this.key; } final String getAlias() { return this.keyAlias; } } private static class X509KeyManager extends X509ExtendedKeyManager { private final ClientKeyStore keyStore; X509KeyManager(final ClientKeyStore keyStore) { this.keyStore = keyStore; } // Call sequence: 1 // @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return keyStore.getAlias(); } // Call sequence: 2 // @Override public X509Certificate[] getCertificateChain(String alias) { return keyStore.getCertificateChain(); } // @Override public String[] getClientAliases(String keyType, Principal[] issuers) { return new String[] { keyStore.getAlias() }; } // Call sequence: 3 // @Override public PrivateKey getPrivateKey(String alias) { return keyStore.getPrivateKey(); } // @Override public String[] getServerAliases(String keyType, Principal[] issuers) { return null; } // @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { return null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy