/**
* 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.geronimo.security.keystore;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.management.geronimo.KeyNotFoundException;
import org.apache.geronimo.management.geronimo.KeystoreException;
import org.apache.geronimo.management.geronimo.KeystoreInstance;
import org.apache.geronimo.management.geronimo.KeystoreIsLocked;
import org.apache.geronimo.system.serverinfo.ServerInfo;
import org.apache.geronimo.util.asn1.ASN1InputStream;
import org.apache.geronimo.util.asn1.ASN1Sequence;
import org.apache.geronimo.util.asn1.ASN1Set;
import org.apache.geronimo.util.asn1.DEROutputStream;
import org.apache.geronimo.util.asn1.x509.X509CertificateStructure;
import org.apache.geronimo.util.asn1.x509.X509Name;
import org.apache.geronimo.util.encoders.Base64;
import org.apache.geronimo.util.jce.PKCS10CertificationRequest;
import org.apache.geronimo.util.jce.X509Principal;
import org.apache.geronimo.util.jce.X509V1CertificateGenerator;
/**
* Implementation of KeystoreInstance that accesses a keystore file on the
* local filesystem, identified by the file's name (the last component of
* the name only, not the full path).
*
* @version $Rev: 477213 $ $Date: 2006-11-20 10:00:20 -0500 (Mon, 20 Nov 2006) $
*/
public class FileKeystoreInstance implements KeystoreInstance, GBeanLifecycle {
private static final Log log = LogFactory.getLog(FileKeystoreInstance.class);
final static String JKS = "JKS";
private URI keystorePath; // relative path
private ServerInfo serverInfo; // used to decode relative path
private File keystoreFile; // Only valid after startup
private String keystoreName;
private char[] keystorePassword; // Used to "unlock" the keystore for other services
private Map keyPasswords = new HashMap();
private Kernel kernel;
private AbstractName abstractName;
private char[] openPassword; // The password last used to open the keystore for editing
// The following variables are the state of the keystore, which should be chucked if the file on disk changes
private List privateKeys = new ArrayList();
private List trustCerts = new ArrayList();
private KeyStore keystore;
private long keystoreReadDate = Long.MIN_VALUE;
public FileKeystoreInstance(ServerInfo serverInfo, URI keystorePath, String keystoreName, String keystorePassword, String keyPasswords, Kernel kernel, AbstractName abstractName) {
this.serverInfo = serverInfo;
this.keystorePath = keystorePath;
this.keystoreName = keystoreName;
this.kernel = kernel;
this.abstractName = abstractName;
this.keystorePassword = keystorePassword == null ? null : keystorePassword.toCharArray();
if(keyPasswords != null) {
String[] keys = keyPasswords.split("\\]\\!\\[");
for (int i = 0; i < keys.length; i++) {
String key = keys[i];
int pos = key.indexOf('=');
this.keyPasswords.put(key.substring(0, pos), key.substring(pos+1).toCharArray());
}
}
}
public void doStart() throws Exception {
keystoreFile = new File(serverInfo.resolveServer(keystorePath));
if(!keystoreFile.exists() || !keystoreFile.canRead()) {
throw new IllegalArgumentException("Invalid keystore file ("+keystorePath+" = "+keystoreFile.getAbsolutePath()+")");
}
}
public void doStop() throws Exception {
}
public void doFail() {
}
public static final GBeanInfo GBEAN_INFO;
static {
GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(FileKeystoreInstance.class, NameFactory.KEYSTORE_INSTANCE);
infoFactory.addAttribute("keystorePath", URI.class, true, false);
infoFactory.addAttribute("keystoreName", String.class, true, false);
infoFactory.addAttribute("keystorePassword", String.class, true, true);
infoFactory.addAttribute("keyPasswords", String.class, true, true);
infoFactory.addAttribute("kernel", Kernel.class, false);
infoFactory.addAttribute("abstractName", AbstractName.class, false);
infoFactory.addReference("ServerInfo", ServerInfo.class, NameFactory.GERONIMO_SERVICE);
infoFactory.addInterface(KeystoreInstance.class);
infoFactory.setConstructor(new String[]{"ServerInfo","keystorePath", "keystoreName", "keystorePassword", "keyPasswords", "kernel", "abstractName"});
GBEAN_INFO = infoFactory.getBeanInfo();
}
public static GBeanInfo getGBeanInfo() {
return GBEAN_INFO;
}
// KeystoreInstnace interface
public String getKeystoreName() {
return keystoreName;
}
public void unlockKeystore(char[] password) throws KeystoreException {
if (password == null) {
throw new NullPointerException("password is null");
}
ensureLoaded(password);
try {
kernel.setAttribute(abstractName, "keystorePassword", new String(password));
} catch (Exception e) {
throw new KeystoreException("Unable to set attribute keystorePassword on myself!", e);
}
}
public void setKeystorePassword(String password) {
keystorePassword = password == null ? null : password.toCharArray();
}
public void lockKeystore(char[] password) throws KeystoreException {
try {
kernel.setAttribute(abstractName, "keystorePassword", null);
keyPasswords.clear();
storePasswords();
} catch (Exception e) {
throw new KeystoreException("Unable to set attribute keystorePassword on myself!", e);
}
}
public boolean isKeystoreLocked() {
return keystorePassword == null;
}
public String[] listPrivateKeys(char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
return (String[]) privateKeys.toArray(new String[privateKeys.size()]);
}
public void unlockPrivateKey(String alias, char[] storePassword, char[] password) throws KeystoreException {
if (storePassword == null && keystorePassword == null) {
throw new KeystoreException("storePassword is null and keystore is locked for availability.");
}
if(storePassword != null)
getPrivateKey(alias, storePassword, password);
else
getPrivateKey(alias, keystorePassword, password);
keyPasswords.put(alias, password);
storePasswords();
}
public String[] getUnlockedKeys(char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
return (String[]) keyPasswords.keySet().toArray(new String[keyPasswords.size()]);
}
public boolean isTrustStore(char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
return trustCerts.size() > 0;
}
public void lockPrivateKey(String alias, char[] storePassword) throws KeystoreException {
if (storePassword == null) {
throw new NullPointerException("storePassword is null");
}
ensureLoaded(storePassword);
keyPasswords.remove(alias);
storePasswords();
}
private void storePasswords() throws KeystoreException {
StringBuffer buf = new StringBuffer();
for (Iterator it = keyPasswords.entrySet().iterator(); it.hasNext();) {
if(buf.length() > 0) {
buf.append("]![");
}
Map.Entry entry = (Map.Entry) it.next();
buf.append(entry.getKey()).append("=").append((char[])entry.getValue());
}
try {
kernel.setAttribute(abstractName, "keyPasswords", buf.length() == 0 ? null : buf.toString());
} catch (Exception e) {
throw new KeystoreException("Unable to save key passwords in keystore '"+keystoreName+"'", e);
}
}
public void setKeyPasswords(String passwords) {} // Just so the kernel sees the new value
/**
* Checks whether the specified private key is locked, which is to say,
* available for other components to use to generate socket factories.
* Does not check whether the unlock password is actually correct.
*/
public boolean isKeyLocked(String alias) {
return keyPasswords.get(alias) == null;
}
public String[] listTrustCertificates(char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
return (String[]) trustCerts.toArray(new String[trustCerts.size()]);
}
public void importTrustCertificate(Certificate cert, String alias, char[] storePassword) throws KeystoreException {
if (storePassword == null) {
throw new NullPointerException("storePassword is null");
}
ensureLoaded(storePassword);
try {
keystore.setCertificateEntry(alias, cert);
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to set certificate entry in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
}
trustCerts.add(alias);
saveKeystore(storePassword);
}
public void generateKeyPair(String alias, char[] storePassword, char[] keyPassword, String keyAlgorithm, int keySize, String signatureAlgorithm, int validity, String commonName, String orgUnit, String organization, String locality, String state, String country) throws KeystoreException {
if (storePassword == null) {
throw new NullPointerException("storePassword is null");
}
ensureLoaded(storePassword);
try {
KeyPairGenerator kpgen = KeyPairGenerator.getInstance(keyAlgorithm);
kpgen.initialize(keySize);
KeyPair keyPair = kpgen.generateKeyPair();
X509Certificate cert = generateCertificate(keyPair.getPublic(), keyPair.getPrivate(), signatureAlgorithm,
validity, commonName, orgUnit, organization, locality, state, country);
keystore.setKeyEntry(alias, keyPair.getPrivate(), keyPassword, new Certificate[] { cert });
privateKeys.add(alias);
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
} catch (InvalidKeyException e) {
throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
} catch (SignatureException e) {
throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
}
saveKeystore(storePassword);
}
public String generateCSR(String alias, char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
try {
// find certificate by alias
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
// find private key by alias
PrivateKey key = (PrivateKey) keystore.getKey(alias, (char[])keyPasswords.get(alias));
// generate csr
String csr = generateCSR(cert, key);
return csr;
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (UnrecoverableKeyException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (InvalidKeyException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (NoSuchProviderException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (SignatureException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (IOException e) {
throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
}
}
private String generateCSR(X509Certificate cert, PrivateKey signingKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, KeyStoreException, IOException {
String sigalg = cert.getSigAlgName();
X509Name subject;
try{
ASN1InputStream ais = new ASN1InputStream(cert.getEncoded());
X509CertificateStructure x509Struct = new X509CertificateStructure((ASN1Sequence)ais.readObject());
ais.close();
subject = x509Struct.getSubject();
} catch(CertificateEncodingException e) {
log.warn(e.toString()+" while retrieving subject from certificate to create CSR. Using subjectDN instead.");
subject = new X509Name(cert.getSubjectDN().toString());
}
PublicKey publicKey = cert.getPublicKey();
ASN1Set attributes = null;
PKCS10CertificationRequest csr = new PKCS10CertificationRequest(sigalg,
subject, publicKey, attributes, signingKey);
if (!csr.verify()) {
throw new KeyStoreException("CSR verification failed");
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
DEROutputStream deros = new DEROutputStream(os);
deros.writeObject(csr.getDERObject());
String b64 = new String(Base64.encode(os.toByteArray()));
final String BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
final String END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
final int CERT_REQ_LINE_LENGTH = 70;
StringBuffer sbuf = new StringBuffer(BEGIN_CERT_REQ).append('\n');
int idx = 0;
while (idx < b64.length()) {
int len = (idx + CERT_REQ_LINE_LENGTH > b64.length()) ? b64
.length()
- idx : CERT_REQ_LINE_LENGTH;
String chunk = b64.substring(idx, idx + len);
sbuf.append(chunk).append('\n');
idx += len;
}
sbuf.append(END_CERT_REQ);
return sbuf.toString();
}
public void importPKCS7Certificate(String alias, String certbuf, char[] storePassword) throws KeystoreException {
if (storePassword == null) {
throw new NullPointerException("storePassword is null");
}
ensureLoaded(storePassword);
InputStream is = null;
try {
is = new ByteArrayInputStream(certbuf.getBytes());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection certcoll = cf.generateCertificates(is);
Certificate[] chain = new Certificate[certcoll.size()];
Iterator iter = certcoll.iterator();
for (int i = 0; iter.hasNext(); i++) {
chain[i] = (Certificate) iter.next();
}
if(keystore.getCertificate(alias).getPublicKey().equals(chain[0].getPublicKey())) {
char[] keyPassword = (char[])keyPasswords.get(alias);
keystore.setKeyEntry(alias, keystore.getKey(alias, keyPassword), keyPassword, chain);
saveKeystore(keystorePassword);
} else {
log.error("Error in importPKCS7Certificate. PublicKey in the certificate received is not related to the PrivateKey in the keystore. keystore = "+keystoreName+", alias = "+alias);
}
} catch (CertificateException e) {
throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} catch (UnrecoverableKeyException e) {
throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
}
}
}
}
public void deleteEntry(String alias, char[] storePassword) throws KeystoreException {
if (storePassword == null) {
throw new NullPointerException("storePassword is null");
}
ensureLoaded(storePassword);
try {
keystore.deleteEntry(alias);
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to delete key in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
}
privateKeys.remove(alias);
trustCerts.remove(alias);
if (keyPasswords.containsKey(alias)) {
keyPasswords.remove(alias);
storePasswords();
}
saveKeystore(storePassword);
}
public KeyManager[] getKeyManager(String algorithm, String alias, char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
try {
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(algorithm);
if(privateKeys.size() == 1) {
keyFactory.init(keystore, (char[]) keyPasswords.get(alias));
} else {
// When there is more than one private key in the keystore, we create a temporary "sub keystore"
// with only one entry of our interest and use it
KeyStore subKeystore = KeyStore.getInstance(keystore.getType(), keystore.getProvider());
try {
subKeystore.load(null, null);
} catch (NoSuchAlgorithmException e) {
// should not occur
} catch (CertificateException e) {
// should not occur
} catch (IOException e) {
// should not occur
}
subKeystore.setKeyEntry(alias, keystore.getKey(alias, (char[]) keyPasswords.get(alias)),
(char[]) keyPasswords.get(alias), keystore.getCertificateChain(alias));
keyFactory.init(subKeystore, (char[]) keyPasswords.get(alias));
}
return keyFactory.getKeyManagers();
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
} catch (UnrecoverableKeyException e) {
throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
}
}
public TrustManager[] getTrustManager(String algorithm, char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
try {
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(algorithm);
trustFactory.init(keystore);
return trustFactory.getTrustManagers();
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to retrieve trust manager in keystore '" + keystoreName + "'");
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to retrieve trust manager in keystore '" + keystoreName + "'");
}
}
/**
* Gets the private key with the specified alias.
* @param alias The alias of the private key to be retrieved
* @param storePassword The password used to access the keystore
* @param keyPassword The password to use to protect the new key
* @return PrivateKey with the alias specified
*/
public PrivateKey getPrivateKey(String alias, char[] storePassword, char[] keyPassword) throws KeyNotFoundException, KeystoreException, KeystoreIsLocked {
ensureLoaded(storePassword);
try {
PrivateKey key = (PrivateKey) keystore.getKey(alias, keyPassword);
if (key == null) {
throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a private key with alias'"+alias+"'.");
}
return key;
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to retrieve private key from keystore", e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to retrieve private key from keystore", e);
} catch (UnrecoverableKeyException e) {
throw new KeystoreException("Unable to retrieve private key from keystore", e);
}
}
/**
* Gets a particular certificate from the keystore. This may be a trust
* certificate or the certificate corresponding to a particular private
* key.
* This only works if the keystore is unlocked.
* @param alias The certificate to look at
* @throws KeyNotFoundException
* @throws KeyStoreException
*/
public Certificate getCertificate(String alias, char[] storePassword) throws KeystoreIsLocked, KeyNotFoundException, KeystoreException {
ensureLoaded(storePassword);
try {
Certificate cert = keystore.getCertificate(alias);
if (cert == null) {
throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a certificate with alias'"+alias+"'.");
}
return cert;
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to retrieve certificate from keystore", e);
}
}
public String getCertificateAlias(Certificate cert, char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
try {
String alias = keystore.getCertificateAlias(cert);
if (alias == null) {
throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain an alias corresponding to the given certificate.");
}
return alias;
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to read certificate alias from keystore", e);
}
}
public Certificate[] getCertificateChain(String alias, char[] storePassword) throws KeystoreException {
ensureLoaded(storePassword);
try {
Certificate[] certs = keystore.getCertificateChain(alias);
if (certs == null) {
throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a certificate chain with alias'"+alias+"'.");
}
return certs;
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to read certificate chain from keystore", e);
}
}
/**
* Gets a particular certificate from the keystore. This may be a trust
* certificate or the certificate corresponding to a particular private
* key.
* This only works if the keystore is unlocked.
* @param alias The certificate to look at
*/
public Certificate getCertificate(String alias) {
if(isKeystoreLocked()) {
return null;
}
try {
return keystore.getCertificate(alias);
} catch (KeyStoreException e) {
log.error("Unable to read certificate from keystore", e);
}
return null;
}
// ==================== Internals =====================
private void loadKeystoreData(char[] password) throws KeystoreException {
InputStream in = null;
try {
// Make sure the keystore is loadable using the provided password before resetting the instance variables.
KeyStore tempKeystore = KeyStore.getInstance(JKS);
in = new BufferedInputStream(new FileInputStream(keystoreFile));
long readDate = System.currentTimeMillis();
tempKeystore.load(in, password);
// Keystore could be loaded successfully. Initialize the instance variables to reflect the new keystore.
keystore = tempKeystore;
keystoreReadDate = readDate;
privateKeys.clear();
trustCerts.clear();
openPassword = password;
Enumeration aliases = keystore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if(keystore.isKeyEntry(alias)) {
privateKeys.add(alias);
} else if(keystore.isCertificateEntry(alias)) {
trustCerts.add(alias);
}
}
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to open keystore with provided password", e);
} catch (IOException e) {
throw new KeystoreException("Unable to open keystore with provided password", e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to open keystore with provided password", e);
} catch (CertificateException e) {
throw new KeystoreException("Unable to open keystore with provided password", e);
} finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
log.error("Error while closing keystore file "+keystoreFile.getAbsolutePath(), e);
}
}
}
}
private boolean isLoaded(char[] password) {
if(openPassword == null || openPassword.length != password.length) {
return false;
}
if(keystoreReadDate < keystoreFile.lastModified()) {
return false;
}
for (int i = 0; i < password.length; i++) {
if(password[i] != openPassword[i]) {
return false;
}
}
return true;
}
private void ensureLoaded(char[] storePassword) throws KeystoreException {
char[] password;
if (storePassword == null) {
if (isKeystoreLocked()) {
throw new KeystoreIsLocked("Keystore '"+keystoreName+"' is locked; please unlock it in the console.");
}
password = keystorePassword;
} else {
password = storePassword;
}
if (!isLoaded(password)) {
loadKeystoreData(password);
}
}
private X509Certificate generateCertificate(PublicKey publicKey, PrivateKey privateKey, String algorithm, int validity, String commonName, String orgUnit, String organization, String locality, String state, String country) throws SignatureException, InvalidKeyException {
X509V1CertificateGenerator certgen = new X509V1CertificateGenerator();
Vector order = new Vector();
Hashtable attrmap = new Hashtable();
if (commonName != null) {
attrmap.put(X509Principal.CN, commonName);
order.add(X509Principal.CN);
}
if (orgUnit != null) {
attrmap.put(X509Principal.OU, orgUnit);
order.add(X509Principal.OU);
}
if (organization != null) {
attrmap.put(X509Principal.O, organization);
order.add(X509Principal.O);
}
if (locality != null) {
attrmap.put(X509Principal.L, locality);
order.add(X509Principal.L);
}
if (state != null) {
attrmap.put(X509Principal.ST, state);
order.add(X509Principal.ST);
}
if (country != null) {
attrmap.put(X509Principal.C, country);
order.add(X509Principal.C);
}
X509Principal issuerDN = new X509Principal(order, attrmap);
// validity
long curr = System.currentTimeMillis();
long untill = curr + (long) validity * 24 * 60 * 60 * 1000;
certgen.setNotBefore(new Date(curr));
certgen.setNotAfter(new Date(untill));
certgen.setIssuerDN(issuerDN);
certgen.setSubjectDN(issuerDN);
certgen.setPublicKey(publicKey);
certgen.setSignatureAlgorithm(algorithm);
certgen.setSerialNumber(new BigInteger(String.valueOf(curr)));
// make certificate
return certgen.generateX509Certificate(privateKey);
}
private void saveKeystore(char[] password) throws KeystoreException {
try {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(keystoreFile));
keystore.store(out, password);
out.flush();
out.close();
keystoreReadDate = System.currentTimeMillis();
} catch (KeyStoreException e) {
throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
} catch (FileNotFoundException e) {
throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
} catch (IOException e) {
throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
} catch (NoSuchAlgorithmException e) {
throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
} catch (CertificateException e) {
throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
}
}
}