/*
* Copyright (c) Members of the EGEE Collaboration. 2006-2010.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* 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.
*
* $Id$
*/
package org.glite.authz.common.security;
import java.io.IOException;
import java.net.Socket;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.X509KeyManager;
/**
* PKIKeyManager is a {@link X509KeyManager} to manage which X509
* certificate-based key pairs is used to authenticate the local side (client)
* of a secure socket.
*
* @author Valery Tschopp <valery.tschopp@switch.ch>
*/
public class PKIKeyManager implements X509KeyManager {
/** Delegate */
private X509KeyManager keyManager_= null;
/**
* Constructor where the key material is contained in PEM encoded
* certificate and private key files. (OpenSSL compatible)
*
* @param certfile
* PEM encoded certificate(s) filename
* @param keyfile
* PEM encoded private key filename
* @param password
* private key and keystore password, can not be
* <code>null</code>. If the private key is not encrypted, choose
* a password for the keystore.
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws CertificateException
*/
public PKIKeyManager(String certfile, String keyfile, String password)
throws IOException, NoSuchAlgorithmException, KeyStoreException,
UnrecoverableKeyException, CertificateException {
KeyStore keystore= createKeyStore(certfile, keyfile, password);
keyManager_= createX509KeyManager(keystore, password);
}
/**
* Constructor based on a {@link KeyStore} containing the certificate and
* the private key.
*
* @param keystore
* the keystore containing the certificate and private key
* @param password
* the keystore password, can not be <code>null</code>.
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
*/
public PKIKeyManager(KeyStore keystore, String password)
throws UnrecoverableKeyException, NoSuchAlgorithmException,
KeyStoreException {
keyManager_= createX509KeyManager(keystore, password);
}
/**
* Creates and initializes a {@link KeyStore} with key material from PEM
* encoded files.
*
* @param certfile
* PEM encoded certificate filename
* @param keyfile
* PEM encoded private key filename
* @param password
* password for the encrypted private key and the resulting
* keystore, can not be <code>null</code>
* @return the KeyStore containing the key material
* @throws IOException
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws CertificateException
*/
protected KeyStore createKeyStore(String certfile, String keyfile,
String password) throws IOException, KeyStoreException,
NoSuchAlgorithmException, CertificateException {
PEMFileReader reader= new PEMFileReader();
PrivateKey pkey= reader.readPrivateKey(keyfile, password);
X509Certificate[] certs= reader.readCertificates(certfile);
char passwd[]= password.toCharArray();
KeyStore keystore= KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, passwd);
keystore.setKeyEntry("keycreds", pkey, passwd, certs);
return keystore;
}
/**
*
* @param keystore
* @param password
* @return
* @throws NoSuchAlgorithmException
* @throws UnrecoverableKeyException
* @throws KeyStoreException
*/
protected X509KeyManager createX509KeyManager(KeyStore keystore,
String password) throws NoSuchAlgorithmException,
UnrecoverableKeyException, KeyStoreException {
KeyManagerFactory kmfactory= KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(keystore, password.toCharArray());
X509KeyManager keyManager= (X509KeyManager) kmfactory.getKeyManagers()[0];
return keyManager;
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#chooseClientAlias(java.lang.String[],
* java.security.Principal[], java.net.Socket)
*/
public String chooseClientAlias(String[] keyType, Principal[] issuers,
Socket socket) {
return keyManager_.chooseClientAlias(keyType, issuers, socket);
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#chooseServerAlias(java.lang.String,
* java.security.Principal[], java.net.Socket)
*/
public String chooseServerAlias(String keyType, Principal[] issuers,
Socket socket) {
return keyManager_.chooseServerAlias(keyType, issuers, socket);
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#getCertificateChain(java.lang.String)
*/
public X509Certificate[] getCertificateChain(String alias) {
return keyManager_.getCertificateChain(alias);
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#getClientAliases(java.lang.String,
* java.security.Principal[])
*/
public String[] getClientAliases(String keyType, Principal[] issuers) {
return keyManager_.getClientAliases(keyType, issuers);
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#getPrivateKey(java.lang.String)
*/
public PrivateKey getPrivateKey(String alias) {
return keyManager_.getPrivateKey(alias);
}
/*
* (non-Javadoc)
*
* @see javax.net.ssl.X509KeyManager#getServerAliases(java.lang.String,
* java.security.Principal[])
*/
public String[] getServerAliases(String keyType, Principal[] issuers) {
return keyManager_.getServerAliases(keyType, issuers);
}
}