KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > keystore > FileKeystoreInstance


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.geronimo.security.keystore;
18
19 import java.io.BufferedInputStream JavaDoc;
20 import java.io.BufferedOutputStream JavaDoc;
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.ByteArrayOutputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.FileOutputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.math.BigInteger JavaDoc;
30 import java.net.URI JavaDoc;
31 import java.security.InvalidKeyException JavaDoc;
32 import java.security.KeyPair JavaDoc;
33 import java.security.KeyPairGenerator JavaDoc;
34 import java.security.KeyStore JavaDoc;
35 import java.security.KeyStoreException JavaDoc;
36 import java.security.NoSuchAlgorithmException JavaDoc;
37 import java.security.NoSuchProviderException JavaDoc;
38 import java.security.PrivateKey JavaDoc;
39 import java.security.PublicKey JavaDoc;
40 import java.security.SignatureException JavaDoc;
41 import java.security.UnrecoverableKeyException JavaDoc;
42 import java.security.cert.Certificate JavaDoc;
43 import java.security.cert.CertificateEncodingException JavaDoc;
44 import java.security.cert.CertificateException JavaDoc;
45 import java.security.cert.CertificateFactory JavaDoc;
46 import java.security.cert.X509Certificate JavaDoc;
47 import java.util.ArrayList JavaDoc;
48 import java.util.Collection JavaDoc;
49 import java.util.Date JavaDoc;
50 import java.util.Enumeration JavaDoc;
51 import java.util.HashMap JavaDoc;
52 import java.util.Hashtable JavaDoc;
53 import java.util.Iterator JavaDoc;
54 import java.util.List JavaDoc;
55 import java.util.Map JavaDoc;
56 import java.util.Vector JavaDoc;
57 import javax.net.ssl.KeyManager;
58 import javax.net.ssl.KeyManagerFactory;
59 import javax.net.ssl.TrustManager;
60 import javax.net.ssl.TrustManagerFactory;
61 import org.apache.commons.logging.Log;
62 import org.apache.commons.logging.LogFactory;
63 import org.apache.geronimo.gbean.GBeanInfo;
64 import org.apache.geronimo.gbean.GBeanInfoBuilder;
65 import org.apache.geronimo.gbean.GBeanLifecycle;
66 import org.apache.geronimo.gbean.AbstractName;
67 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
68 import org.apache.geronimo.kernel.Kernel;
69 import org.apache.geronimo.management.geronimo.KeyNotFoundException;
70 import org.apache.geronimo.management.geronimo.KeystoreException;
71 import org.apache.geronimo.management.geronimo.KeystoreInstance;
72 import org.apache.geronimo.management.geronimo.KeystoreIsLocked;
73 import org.apache.geronimo.system.serverinfo.ServerInfo;
74 import org.apache.geronimo.util.asn1.ASN1InputStream;
75 import org.apache.geronimo.util.asn1.ASN1Sequence;
76 import org.apache.geronimo.util.asn1.ASN1Set;
77 import org.apache.geronimo.util.asn1.DEROutputStream;
78 import org.apache.geronimo.util.asn1.x509.X509CertificateStructure;
79 import org.apache.geronimo.util.asn1.x509.X509Name;
80 import org.apache.geronimo.util.encoders.Base64;
81 import org.apache.geronimo.util.jce.PKCS10CertificationRequest;
82 import org.apache.geronimo.util.jce.X509Principal;
83 import org.apache.geronimo.util.jce.X509V1CertificateGenerator;
84
85 /**
86  * Implementation of KeystoreInstance that accesses a keystore file on the
87  * local filesystem, identified by the file's name (the last component of
88  * the name only, not the full path).
89  *
90  * @version $Rev: 477213 $ $Date: 2006-11-20 10:00:20 -0500 (Mon, 20 Nov 2006) $
91  */

92 public class FileKeystoreInstance implements KeystoreInstance, GBeanLifecycle {
93     private static final Log log = LogFactory.getLog(FileKeystoreInstance.class);
94     final static String JavaDoc JKS = "JKS";
95     private URI JavaDoc keystorePath; // relative path
96
private ServerInfo serverInfo; // used to decode relative path
97
private File JavaDoc keystoreFile; // Only valid after startup
98
private String JavaDoc keystoreName;
99     private char[] keystorePassword; // Used to "unlock" the keystore for other services
100
private Map JavaDoc keyPasswords = new HashMap JavaDoc();
101     private Kernel kernel;
102     private AbstractName abstractName;
103     private char[] openPassword; // The password last used to open the keystore for editing
104
// The following variables are the state of the keystore, which should be chucked if the file on disk changes
105
private List JavaDoc privateKeys = new ArrayList JavaDoc();
106     private List JavaDoc trustCerts = new ArrayList JavaDoc();
107     private KeyStore JavaDoc keystore;
108     private long keystoreReadDate = Long.MIN_VALUE;
109
110     public FileKeystoreInstance(ServerInfo serverInfo, URI JavaDoc keystorePath, String JavaDoc keystoreName, String JavaDoc keystorePassword, String JavaDoc keyPasswords, Kernel kernel, AbstractName abstractName) {
111         this.serverInfo = serverInfo;
112         this.keystorePath = keystorePath;
113         this.keystoreName = keystoreName;
114         this.kernel = kernel;
115         this.abstractName = abstractName;
116         this.keystorePassword = keystorePassword == null ? null : keystorePassword.toCharArray();
117         if(keyPasswords != null) {
118             String JavaDoc[] keys = keyPasswords.split("\\]\\!\\[");
119             for (int i = 0; i < keys.length; i++) {
120                 String JavaDoc key = keys[i];
121                 int pos = key.indexOf('=');
122                 this.keyPasswords.put(key.substring(0, pos), key.substring(pos+1).toCharArray());
123             }
124         }
125     }
126
127     public void doStart() throws Exception JavaDoc {
128         keystoreFile = new File JavaDoc(serverInfo.resolveServer(keystorePath));
129         if(!keystoreFile.exists() || !keystoreFile.canRead()) {
130             throw new IllegalArgumentException JavaDoc("Invalid keystore file ("+keystorePath+" = "+keystoreFile.getAbsolutePath()+")");
131         }
132     }
133
134     public void doStop() throws Exception JavaDoc {
135     }
136
137     public void doFail() {
138     }
139
140     public static final GBeanInfo GBEAN_INFO;
141
142     static {
143         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(FileKeystoreInstance.class, NameFactory.KEYSTORE_INSTANCE);
144         infoFactory.addAttribute("keystorePath", URI JavaDoc.class, true, false);
145         infoFactory.addAttribute("keystoreName", String JavaDoc.class, true, false);
146         infoFactory.addAttribute("keystorePassword", String JavaDoc.class, true, true);
147         infoFactory.addAttribute("keyPasswords", String JavaDoc.class, true, true);
148         infoFactory.addAttribute("kernel", Kernel.class, false);
149         infoFactory.addAttribute("abstractName", AbstractName.class, false);
150         infoFactory.addReference("ServerInfo", ServerInfo.class, NameFactory.GERONIMO_SERVICE);
151         infoFactory.addInterface(KeystoreInstance.class);
152         infoFactory.setConstructor(new String JavaDoc[]{"ServerInfo","keystorePath", "keystoreName", "keystorePassword", "keyPasswords", "kernel", "abstractName"});
153
154         GBEAN_INFO = infoFactory.getBeanInfo();
155     }
156
157     public static GBeanInfo getGBeanInfo() {
158         return GBEAN_INFO;
159     }
160
161
162     // KeystoreInstnace interface
163

164     public String JavaDoc getKeystoreName() {
165         return keystoreName;
166     }
167
168     public void unlockKeystore(char[] password) throws KeystoreException {
169         if (password == null) {
170             throw new NullPointerException JavaDoc("password is null");
171         }
172         ensureLoaded(password);
173         try {
174             kernel.setAttribute(abstractName, "keystorePassword", new String JavaDoc(password));
175         } catch (Exception JavaDoc e) {
176             throw new KeystoreException("Unable to set attribute keystorePassword on myself!", e);
177         }
178     }
179
180     public void setKeystorePassword(String JavaDoc password) {
181         keystorePassword = password == null ? null : password.toCharArray();
182     }
183
184     public void lockKeystore(char[] password) throws KeystoreException {
185         try {
186             kernel.setAttribute(abstractName, "keystorePassword", null);
187             keyPasswords.clear();
188             storePasswords();
189         } catch (Exception JavaDoc e) {
190             throw new KeystoreException("Unable to set attribute keystorePassword on myself!", e);
191         }
192     }
193
194     public boolean isKeystoreLocked() {
195         return keystorePassword == null;
196     }
197
198     public String JavaDoc[] listPrivateKeys(char[] storePassword) throws KeystoreException {
199         ensureLoaded(storePassword);
200         return (String JavaDoc[]) privateKeys.toArray(new String JavaDoc[privateKeys.size()]);
201     }
202
203     public void unlockPrivateKey(String JavaDoc alias, char[] storePassword, char[] password) throws KeystoreException {
204         if (storePassword == null && keystorePassword == null) {
205             throw new KeystoreException("storePassword is null and keystore is locked for availability.");
206         }
207         if(storePassword != null)
208             getPrivateKey(alias, storePassword, password);
209         else
210             getPrivateKey(alias, keystorePassword, password);
211         keyPasswords.put(alias, password);
212         storePasswords();
213     }
214
215     public String JavaDoc[] getUnlockedKeys(char[] storePassword) throws KeystoreException {
216         ensureLoaded(storePassword);
217         return (String JavaDoc[]) keyPasswords.keySet().toArray(new String JavaDoc[keyPasswords.size()]);
218     }
219
220     public boolean isTrustStore(char[] storePassword) throws KeystoreException {
221         ensureLoaded(storePassword);
222         return trustCerts.size() > 0;
223     }
224
225     public void lockPrivateKey(String JavaDoc alias, char[] storePassword) throws KeystoreException {
226         if (storePassword == null) {
227             throw new NullPointerException JavaDoc("storePassword is null");
228         }
229         ensureLoaded(storePassword);
230         keyPasswords.remove(alias);
231         storePasswords();
232     }
233
234     private void storePasswords() throws KeystoreException {
235         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
236         for (Iterator JavaDoc it = keyPasswords.entrySet().iterator(); it.hasNext();) {
237             if(buf.length() > 0) {
238                 buf.append("]![");
239             }
240             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
241             buf.append(entry.getKey()).append("=").append((char[])entry.getValue());
242         }
243         try {
244             kernel.setAttribute(abstractName, "keyPasswords", buf.length() == 0 ? null : buf.toString());
245         } catch (Exception JavaDoc e) {
246             throw new KeystoreException("Unable to save key passwords in keystore '"+keystoreName+"'", e);
247         }
248     }
249
250     public void setKeyPasswords(String JavaDoc passwords) {} // Just so the kernel sees the new value
251

252     /**
253      * Checks whether the specified private key is locked, which is to say,
254      * available for other components to use to generate socket factories.
255      * Does not check whether the unlock password is actually correct.
256      */

257     public boolean isKeyLocked(String JavaDoc alias) {
258         return keyPasswords.get(alias) == null;
259     }
260
261     public String JavaDoc[] listTrustCertificates(char[] storePassword) throws KeystoreException {
262         ensureLoaded(storePassword);
263         return (String JavaDoc[]) trustCerts.toArray(new String JavaDoc[trustCerts.size()]);
264     }
265
266     public void importTrustCertificate(Certificate JavaDoc cert, String JavaDoc alias, char[] storePassword) throws KeystoreException {
267         if (storePassword == null) {
268             throw new NullPointerException JavaDoc("storePassword is null");
269         }
270         ensureLoaded(storePassword);
271         try {
272             keystore.setCertificateEntry(alias, cert);
273         } catch (KeyStoreException JavaDoc e) {
274             throw new KeystoreException("Unable to set certificate entry in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
275         }
276         trustCerts.add(alias);
277         saveKeystore(storePassword);
278     }
279
280     public void generateKeyPair(String JavaDoc alias, char[] storePassword, char[] keyPassword, String JavaDoc keyAlgorithm, int keySize, String JavaDoc signatureAlgorithm, int validity, String JavaDoc commonName, String JavaDoc orgUnit, String JavaDoc organization, String JavaDoc locality, String JavaDoc state, String JavaDoc country) throws KeystoreException {
281         if (storePassword == null) {
282             throw new NullPointerException JavaDoc("storePassword is null");
283         }
284         ensureLoaded(storePassword);
285         try {
286             KeyPairGenerator JavaDoc kpgen = KeyPairGenerator.getInstance(keyAlgorithm);
287             kpgen.initialize(keySize);
288             KeyPair JavaDoc keyPair = kpgen.generateKeyPair();
289             X509Certificate JavaDoc cert = generateCertificate(keyPair.getPublic(), keyPair.getPrivate(), signatureAlgorithm,
290                     validity, commonName, orgUnit, organization, locality, state, country);
291     
292             keystore.setKeyEntry(alias, keyPair.getPrivate(), keyPassword, new Certificate JavaDoc[] { cert });
293             privateKeys.add(alias);
294         } catch (KeyStoreException JavaDoc e) {
295             throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
296         } catch (InvalidKeyException JavaDoc e) {
297             throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
298         } catch (SignatureException JavaDoc e) {
299             throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
300         } catch (NoSuchAlgorithmException JavaDoc e) {
301             throw new KeystoreException("Unable to generate key pair in keystore '" + keystoreName + "'");
302         }
303         saveKeystore(storePassword);
304     }
305
306
307     public String JavaDoc generateCSR(String JavaDoc alias, char[] storePassword) throws KeystoreException {
308         ensureLoaded(storePassword);
309         try {
310             // find certificate by alias
311
X509Certificate JavaDoc cert = (X509Certificate JavaDoc) keystore.getCertificate(alias);
312             // find private key by alias
313
PrivateKey JavaDoc key = (PrivateKey JavaDoc) keystore.getKey(alias, (char[])keyPasswords.get(alias));
314             // generate csr
315
String JavaDoc csr = generateCSR(cert, key);
316             return csr;
317         } catch (KeyStoreException JavaDoc e) {
318             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
319         } catch (NoSuchAlgorithmException JavaDoc e) {
320             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
321         } catch (UnrecoverableKeyException JavaDoc e) {
322             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
323         } catch (InvalidKeyException JavaDoc e) {
324             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
325         } catch (NoSuchProviderException JavaDoc e) {
326             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
327         } catch (SignatureException JavaDoc e) {
328             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
329         } catch (IOException JavaDoc e) {
330             throw new KeystoreException("Unable to generate CSR in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
331         }
332     }
333
334     private String JavaDoc generateCSR(X509Certificate JavaDoc cert, PrivateKey JavaDoc signingKey) throws InvalidKeyException JavaDoc, NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc, SignatureException JavaDoc, KeyStoreException JavaDoc, IOException JavaDoc {
335         String JavaDoc sigalg = cert.getSigAlgName();
336         X509Name subject;
337         try{
338             ASN1InputStream ais = new ASN1InputStream(cert.getEncoded());
339             X509CertificateStructure x509Struct = new X509CertificateStructure((ASN1Sequence)ais.readObject());
340             ais.close();
341             subject = x509Struct.getSubject();
342         } catch(CertificateEncodingException JavaDoc e) {
343             log.warn(e.toString()+" while retrieving subject from certificate to create CSR. Using subjectDN instead.");
344             subject = new X509Name(cert.getSubjectDN().toString());
345         }
346         PublicKey JavaDoc publicKey = cert.getPublicKey();
347         ASN1Set attributes = null;
348
349         PKCS10CertificationRequest csr = new PKCS10CertificationRequest(sigalg,
350                 subject, publicKey, attributes, signingKey);
351
352         if (!csr.verify()) {
353             throw new KeyStoreException JavaDoc("CSR verification failed");
354         }
355
356         ByteArrayOutputStream JavaDoc os = new ByteArrayOutputStream JavaDoc();
357         DEROutputStream deros = new DEROutputStream(os);
358         deros.writeObject(csr.getDERObject());
359         String JavaDoc b64 = new String JavaDoc(Base64.encode(os.toByteArray()));
360
361         final String JavaDoc BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----";
362         final String JavaDoc END_CERT_REQ = "-----END CERTIFICATE REQUEST-----";
363         final int CERT_REQ_LINE_LENGTH = 70;
364
365         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(BEGIN_CERT_REQ).append('\n');
366
367         int idx = 0;
368         while (idx < b64.length()) {
369
370             int len = (idx + CERT_REQ_LINE_LENGTH > b64.length()) ? b64
371                     .length()
372                     - idx : CERT_REQ_LINE_LENGTH;
373
374             String JavaDoc chunk = b64.substring(idx, idx + len);
375
376             sbuf.append(chunk).append('\n');
377             idx += len;
378         }
379
380         sbuf.append(END_CERT_REQ);
381         return sbuf.toString();
382     }
383
384     public void importPKCS7Certificate(String JavaDoc alias, String JavaDoc certbuf, char[] storePassword) throws KeystoreException {
385         if (storePassword == null) {
386             throw new NullPointerException JavaDoc("storePassword is null");
387         }
388         ensureLoaded(storePassword);
389         InputStream JavaDoc is = null;
390         try {
391             is = new ByteArrayInputStream JavaDoc(certbuf.getBytes());
392             CertificateFactory JavaDoc cf = CertificateFactory.getInstance("X.509");
393             Collection JavaDoc certcoll = cf.generateCertificates(is);
394             Certificate JavaDoc[] chain = new Certificate JavaDoc[certcoll.size()];
395             Iterator JavaDoc iter = certcoll.iterator();
396             for (int i = 0; iter.hasNext(); i++) {
397                 chain[i] = (Certificate JavaDoc) iter.next();
398             }
399             if(keystore.getCertificate(alias).getPublicKey().equals(chain[0].getPublicKey())) {
400                 char[] keyPassword = (char[])keyPasswords.get(alias);
401                 keystore.setKeyEntry(alias, keystore.getKey(alias, keyPassword), keyPassword, chain);
402                 saveKeystore(keystorePassword);
403             } else {
404                 log.error("Error in importPKCS7Certificate. PublicKey in the certificate received is not related to the PrivateKey in the keystore. keystore = "+keystoreName+", alias = "+alias);
405             }
406         } catch (CertificateException JavaDoc e) {
407             throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
408         } catch (KeyStoreException JavaDoc e) {
409             throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
410         } catch (NoSuchAlgorithmException JavaDoc e) {
411             throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
412         } catch (UnrecoverableKeyException JavaDoc e) {
413             throw new KeystoreException("Unable to import PKCS7 certificat in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
414         } finally {
415             if (is != null) {
416                 try {
417                     is.close();
418                 } catch (Exception JavaDoc e) {
419                 }
420             }
421         }
422     }
423
424     public void deleteEntry(String JavaDoc alias, char[] storePassword) throws KeystoreException {
425         if (storePassword == null) {
426             throw new NullPointerException JavaDoc("storePassword is null");
427         }
428         ensureLoaded(storePassword);
429         try {
430             keystore.deleteEntry(alias);
431         } catch (KeyStoreException JavaDoc e) {
432             throw new KeystoreException("Unable to delete key in keystore '" + keystoreName + "' for alias '" + alias + "'", e);
433         }
434         privateKeys.remove(alias);
435         trustCerts.remove(alias);
436         if (keyPasswords.containsKey(alias)) {
437             keyPasswords.remove(alias);
438             storePasswords();
439         }
440         saveKeystore(storePassword);
441     }
442
443     public KeyManager[] getKeyManager(String JavaDoc algorithm, String JavaDoc alias, char[] storePassword) throws KeystoreException {
444         ensureLoaded(storePassword);
445         try {
446             KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(algorithm);
447             if(privateKeys.size() == 1) {
448                 keyFactory.init(keystore, (char[]) keyPasswords.get(alias));
449             } else {
450                 // When there is more than one private key in the keystore, we create a temporary "sub keystore"
451
// with only one entry of our interest and use it
452
KeyStore JavaDoc subKeystore = KeyStore.getInstance(keystore.getType(), keystore.getProvider());
453                 try {
454                     subKeystore.load(null, null);
455                 } catch (NoSuchAlgorithmException JavaDoc e) {
456                     // should not occur
457
} catch (CertificateException JavaDoc e) {
458                     // should not occur
459
} catch (IOException JavaDoc e) {
460                     // should not occur
461
}
462                 subKeystore.setKeyEntry(alias, keystore.getKey(alias, (char[]) keyPasswords.get(alias)),
463                                         (char[]) keyPasswords.get(alias), keystore.getCertificateChain(alias));
464                 keyFactory.init(subKeystore, (char[]) keyPasswords.get(alias));
465             }
466             return keyFactory.getKeyManagers();
467         } catch (KeyStoreException JavaDoc e) {
468             throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
469         } catch (NoSuchAlgorithmException JavaDoc e) {
470             throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
471         } catch (UnrecoverableKeyException JavaDoc e) {
472             throw new KeystoreException("Unable to retrieve key manager in keystore '" + keystoreName + "' for alias '" + alias + "'");
473         }
474     }
475
476     public TrustManager[] getTrustManager(String JavaDoc algorithm, char[] storePassword) throws KeystoreException {
477         ensureLoaded(storePassword);
478         try {
479             TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(algorithm);
480             trustFactory.init(keystore);
481             return trustFactory.getTrustManagers();
482         } catch (KeyStoreException JavaDoc e) {
483             throw new KeystoreException("Unable to retrieve trust manager in keystore '" + keystoreName + "'");
484         } catch (NoSuchAlgorithmException JavaDoc e) {
485             throw new KeystoreException("Unable to retrieve trust manager in keystore '" + keystoreName + "'");
486         }
487     }
488
489     /**
490      * Gets the private key with the specified alias.
491      * @param alias The alias of the private key to be retrieved
492      * @param storePassword The password used to access the keystore
493      * @param keyPassword The password to use to protect the new key
494      * @return PrivateKey with the alias specified
495      */

496     public PrivateKey JavaDoc getPrivateKey(String JavaDoc alias, char[] storePassword, char[] keyPassword) throws KeyNotFoundException, KeystoreException, KeystoreIsLocked {
497         ensureLoaded(storePassword);
498         try {
499             PrivateKey JavaDoc key = (PrivateKey JavaDoc) keystore.getKey(alias, keyPassword);
500             if (key == null) {
501                 throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a private key with alias'"+alias+"'.");
502             }
503             return key;
504         } catch (KeyStoreException JavaDoc e) {
505             throw new KeystoreException("Unable to retrieve private key from keystore", e);
506         } catch (NoSuchAlgorithmException JavaDoc e) {
507             throw new KeystoreException("Unable to retrieve private key from keystore", e);
508         } catch (UnrecoverableKeyException JavaDoc e) {
509             throw new KeystoreException("Unable to retrieve private key from keystore", e);
510         }
511     }
512
513     /**
514      * Gets a particular certificate from the keystore. This may be a trust
515      * certificate or the certificate corresponding to a particular private
516      * key.
517      * This only works if the keystore is unlocked.
518      * @param alias The certificate to look at
519      * @throws KeyNotFoundException
520      * @throws KeyStoreException
521      */

522     public Certificate JavaDoc getCertificate(String JavaDoc alias, char[] storePassword) throws KeystoreIsLocked, KeyNotFoundException, KeystoreException {
523         ensureLoaded(storePassword);
524         try {
525             Certificate JavaDoc cert = keystore.getCertificate(alias);
526             if (cert == null) {
527                 throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a certificate with alias'"+alias+"'.");
528             }
529             return cert;
530         } catch (KeyStoreException JavaDoc e) {
531             throw new KeystoreException("Unable to retrieve certificate from keystore", e);
532         }
533     }
534
535     public String JavaDoc getCertificateAlias(Certificate JavaDoc cert, char[] storePassword) throws KeystoreException {
536         ensureLoaded(storePassword);
537         try {
538             String JavaDoc alias = keystore.getCertificateAlias(cert);
539             if (alias == null) {
540                 throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain an alias corresponding to the given certificate.");
541             }
542             return alias;
543         } catch (KeyStoreException JavaDoc e) {
544             throw new KeystoreException("Unable to read certificate alias from keystore", e);
545         }
546     }
547
548     public Certificate JavaDoc[] getCertificateChain(String JavaDoc alias, char[] storePassword) throws KeystoreException {
549         ensureLoaded(storePassword);
550         try {
551             Certificate JavaDoc[] certs = keystore.getCertificateChain(alias);
552             if (certs == null) {
553                 throw new KeyNotFoundException("Keystore '"+keystoreName+"' does not contain a certificate chain with alias'"+alias+"'.");
554             }
555             return certs;
556         } catch (KeyStoreException JavaDoc e) {
557             throw new KeystoreException("Unable to read certificate chain from keystore", e);
558         }
559     }
560     
561     /**
562      * Gets a particular certificate from the keystore. This may be a trust
563      * certificate or the certificate corresponding to a particular private
564      * key.
565      * This only works if the keystore is unlocked.
566      * @param alias The certificate to look at
567      */

568     public Certificate JavaDoc getCertificate(String JavaDoc alias) {
569         if(isKeystoreLocked()) {
570             return null;
571         }
572         try {
573             return keystore.getCertificate(alias);
574         } catch (KeyStoreException JavaDoc e) {
575             log.error("Unable to read certificate from keystore", e);
576         }
577         return null;
578     }
579
580     // ==================== Internals =====================
581

582     private void loadKeystoreData(char[] password) throws KeystoreException {
583         InputStream JavaDoc in = null;
584         try {
585             // Make sure the keystore is loadable using the provided password before resetting the instance variables.
586
KeyStore JavaDoc tempKeystore = KeyStore.getInstance(JKS);
587             in = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(keystoreFile));
588             long readDate = System.currentTimeMillis();
589             tempKeystore.load(in, password);
590             // Keystore could be loaded successfully. Initialize the instance variables to reflect the new keystore.
591
keystore = tempKeystore;
592             keystoreReadDate = readDate;
593             privateKeys.clear();
594             trustCerts.clear();
595             openPassword = password;
596             Enumeration JavaDoc aliases = keystore.aliases();
597             while (aliases.hasMoreElements()) {
598                 String JavaDoc alias = (String JavaDoc) aliases.nextElement();
599                 if(keystore.isKeyEntry(alias)) {
600                     privateKeys.add(alias);
601                 } else if(keystore.isCertificateEntry(alias)) {
602                     trustCerts.add(alias);
603                 }
604             }
605         } catch (KeyStoreException JavaDoc e) {
606             throw new KeystoreException("Unable to open keystore with provided password", e);
607         } catch (IOException JavaDoc e) {
608             throw new KeystoreException("Unable to open keystore with provided password", e);
609         } catch (NoSuchAlgorithmException JavaDoc e) {
610             throw new KeystoreException("Unable to open keystore with provided password", e);
611         } catch (CertificateException JavaDoc e) {
612             throw new KeystoreException("Unable to open keystore with provided password", e);
613         } finally {
614             if(in != null) {
615                 try {
616                     in.close();
617                 } catch (IOException JavaDoc e) {
618                     log.error("Error while closing keystore file "+keystoreFile.getAbsolutePath(), e);
619                 }
620             }
621         }
622     }
623
624     private boolean isLoaded(char[] password) {
625         if(openPassword == null || openPassword.length != password.length) {
626             return false;
627         }
628         if(keystoreReadDate < keystoreFile.lastModified()) {
629             return false;
630         }
631         for (int i = 0; i < password.length; i++) {
632             if(password[i] != openPassword[i]) {
633                 return false;
634             }
635         }
636         return true;
637     }
638
639     private void ensureLoaded(char[] storePassword) throws KeystoreException {
640         char[] password;
641         if (storePassword == null) {
642             if (isKeystoreLocked()) {
643                 throw new KeystoreIsLocked("Keystore '"+keystoreName+"' is locked; please unlock it in the console.");
644             }
645             password = keystorePassword;
646         } else {
647             password = storePassword;
648         }
649         if (!isLoaded(password)) {
650             loadKeystoreData(password);
651         }
652     }
653     
654     private X509Certificate JavaDoc generateCertificate(PublicKey JavaDoc publicKey, PrivateKey JavaDoc privateKey, String JavaDoc algorithm, int validity, String JavaDoc commonName, String JavaDoc orgUnit, String JavaDoc organization, String JavaDoc locality, String JavaDoc state, String JavaDoc country) throws SignatureException JavaDoc, InvalidKeyException JavaDoc {
655         X509V1CertificateGenerator certgen = new X509V1CertificateGenerator();
656         Vector JavaDoc order = new Vector JavaDoc();
657         Hashtable JavaDoc attrmap = new Hashtable JavaDoc();
658
659         if (commonName != null) {
660             attrmap.put(X509Principal.CN, commonName);
661             order.add(X509Principal.CN);
662         }
663
664         if (orgUnit != null) {
665             attrmap.put(X509Principal.OU, orgUnit);
666             order.add(X509Principal.OU);
667         }
668
669         if (organization != null) {
670             attrmap.put(X509Principal.O, organization);
671             order.add(X509Principal.O);
672         }
673
674         if (locality != null) {
675             attrmap.put(X509Principal.L, locality);
676             order.add(X509Principal.L);
677         }
678
679         if (state != null) {
680             attrmap.put(X509Principal.ST, state);
681             order.add(X509Principal.ST);
682         }
683
684         if (country != null) {
685             attrmap.put(X509Principal.C, country);
686             order.add(X509Principal.C);
687         }
688
689         X509Principal issuerDN = new X509Principal(order, attrmap);
690
691         // validity
692
long curr = System.currentTimeMillis();
693         long untill = curr + (long) validity * 24 * 60 * 60 * 1000;
694
695         certgen.setNotBefore(new Date JavaDoc(curr));
696         certgen.setNotAfter(new Date JavaDoc(untill));
697         certgen.setIssuerDN(issuerDN);
698         certgen.setSubjectDN(issuerDN);
699         certgen.setPublicKey(publicKey);
700         certgen.setSignatureAlgorithm(algorithm);
701         certgen.setSerialNumber(new BigInteger JavaDoc(String.valueOf(curr)));
702
703         // make certificate
704
return certgen.generateX509Certificate(privateKey);
705     }
706
707     private void saveKeystore(char[] password) throws KeystoreException {
708         try {
709             BufferedOutputStream JavaDoc out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(keystoreFile));
710             keystore.store(out, password);
711             out.flush();
712             out.close();
713             keystoreReadDate = System.currentTimeMillis();
714         } catch (KeyStoreException JavaDoc e) {
715             throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
716         } catch (FileNotFoundException JavaDoc e) {
717             throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
718         } catch (IOException JavaDoc e) {
719             throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
720         } catch (NoSuchAlgorithmException JavaDoc e) {
721             throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
722         } catch (CertificateException JavaDoc e) {
723             throw new KeystoreException("Unable to save keystore '" + keystoreName + "'", e);
724         }
725     }
726
727 }
728
Popular Tags