KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > ca > GeronimoCertificationAuthority


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

18 package org.apache.geronimo.security.ca;
19
20 import java.io.ByteArrayInputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.math.BigInteger JavaDoc;
23 import java.security.PrivateKey JavaDoc;
24 import java.security.PublicKey JavaDoc;
25 import java.security.Signature JavaDoc;
26 import java.security.cert.Certificate JavaDoc;
27 import java.security.cert.CertificateFactory JavaDoc;
28 import java.util.Date JavaDoc;
29
30 import javax.security.auth.x500.X500Principal JavaDoc;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.geronimo.gbean.AbstractName;
35 import org.apache.geronimo.gbean.GBeanInfo;
36 import org.apache.geronimo.gbean.GBeanInfoBuilder;
37 import org.apache.geronimo.gbean.GBeanLifecycle;
38 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
39 import org.apache.geronimo.kernel.Kernel;
40 import org.apache.geronimo.management.geronimo.CertificateRequestStore;
41 import org.apache.geronimo.management.geronimo.CertificateStore;
42 import org.apache.geronimo.management.geronimo.CertificateStoreException;
43 import org.apache.geronimo.management.geronimo.CertificationAuthority;
44 import org.apache.geronimo.management.geronimo.CertificationAuthorityException;
45 import org.apache.geronimo.management.geronimo.KeystoreException;
46 import org.apache.geronimo.management.geronimo.KeystoreInstance;
47 import org.apache.geronimo.system.serverinfo.ServerInfo;
48 import org.apache.geronimo.util.CaUtils;
49 import org.apache.geronimo.util.asn1.ASN1InputStream;
50 import org.apache.geronimo.util.asn1.DERBitString;
51 import org.apache.geronimo.util.asn1.DEREncodableVector;
52 import org.apache.geronimo.util.asn1.DERInteger;
53 import org.apache.geronimo.util.asn1.DERObject;
54 import org.apache.geronimo.util.asn1.DERSequence;
55 import org.apache.geronimo.util.asn1.pkcs.PKCSObjectIdentifiers;
56 import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier;
57 import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo;
58 import org.apache.geronimo.util.asn1.x509.TBSCertificateStructure;
59 import org.apache.geronimo.util.asn1.x509.Time;
60 import org.apache.geronimo.util.asn1.x509.V3TBSCertificateGenerator;
61 import org.apache.geronimo.util.asn1.x509.X509Name;
62
63 /**
64  * A Certification Authority implementation using KeystoreInstance to store CA's private key,
65  * CertificateStore to store issued certificates and CertificateRequestStore to store certificate requests
66  *
67  * @version $Rev: 476291 $ $Date: 2006-11-17 15:05:24 -0500 (Fri, 17 Nov 2006) $
68  */

69 public class GeronimoCertificationAuthority implements CertificationAuthority, GBeanLifecycle {
70     private final static Log log = LogFactory.getLog(GeronimoCertificationAuthority.class);
71
72     private ServerInfo serverInfo;
73     private Kernel kernel;
74     private AbstractName abstractName;
75
76     // KeystoreInstance with CA's private key and certificate
77
private KeystoreInstance caKeystore = null;
78     // CertificateStore used to store all certificates issued by the CA
79
private CertificateStore certStore = null;
80     // Password for CA's keystore and private-key
81
private char[] password;
82     // CertificateRequestStore used to store certificate requests
83
private CertificateRequestStore certReqStore = null;
84     
85     // Cache variables
86
// Key alias
87
private String JavaDoc alias;
88     // CA's private key
89
private PrivateKey JavaDoc caPrivateKey;
90     // CA's public key
91
private PublicKey JavaDoc caPublicKey;
92     // CA's own certificate
93
private Certificate JavaDoc caCert;
94     // CA's name
95
private X509Name caName;
96     
97     /**
98      * Constructor
99      *
100      * @param instance KeystoreInstance containing CA's private-key and certificate
101      * @param certStore CertificateStore for storing certificates issued by this CA
102      * @param certReqStore CeetificateRequestStore for storing certificates requests
103      */

104     public GeronimoCertificationAuthority(ServerInfo serverInfo, KeystoreInstance caKeystore, CertificateStore certStore, CertificateRequestStore certReqStore, Kernel kernel, AbstractName abstractName) {
105         if(caKeystore == null) throw new IllegalArgumentException JavaDoc("caKeystore is null.");
106         if(certStore == null) throw new IllegalArgumentException JavaDoc("certStore is null");
107         if(certReqStore == null) throw new IllegalArgumentException JavaDoc("certReqStore is null");
108         this.serverInfo = serverInfo;
109         this.kernel = kernel;
110         this.abstractName = abstractName;
111         this.caKeystore = caKeystore;
112         this.certStore = certStore;
113         this.certReqStore = certReqStore;
114     }
115
116     /**
117      * This method checks if the CA is locked.
118      * @return true if CA is locked, false otherwise.
119      */

120     public boolean isLocked() {
121         return password == null;
122     }
123     
124     /**
125      * This method locks the CA.
126      */

127      public void lock() {
128         try {
129             caKeystore.lockKeystore(password);
130         } catch (KeystoreException e) {
131             log.error("Error locking CA.", e);
132         }
133         password = null;
134         caName = null;
135         caCert = null;
136         caPrivateKey = null;
137         alias = null;
138     }
139     
140      /**
141       * This method unlocks the CA.
142       * @param password Password to unlock the CA.
143       */

144     public void unlock(char[] password) throws CertificationAuthorityException{
145         try {
146             this.password = password;
147             caKeystore.unlockKeystore(password);
148             alias = caKeystore.listPrivateKeys(password)[0];
149             caKeystore.unlockPrivateKey(alias, password, password);
150             caCert = caKeystore.getCertificate(alias, password);
151             caName = CaUtils.getSubjectX509Name(caCert);
152             caPrivateKey = caKeystore.getPrivateKey(alias, password, password);
153             caPublicKey = caCert.getPublicKey();
154         } catch(Exception JavaDoc e) {
155             throw new CertificationAuthorityException("Errors in unlocking CA.", e);
156         }
157     }
158     
159     /**
160      * This method returns CA's name.
161      * @throws Exception if CA is locked.
162      */

163     public X500Principal JavaDoc getName() throws CertificationAuthorityException {
164         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
165         try {
166             return new X500Principal JavaDoc(caName.getEncoded());
167         } catch (IOException JavaDoc e) {
168             throw new CertificationAuthorityException("Error in getting CA name.", e);
169         }
170     }
171
172     /**
173      * This method returns CA's own certificate.
174      * @throws Exception if CA is locked.
175      */

176     public Certificate JavaDoc getCertificate() throws CertificationAuthorityException {
177         if(caCert == null) throw new CertificationAuthorityException("CA Certificate is null. CA may be locked.");
178         try {
179             return caCert = caKeystore.getCertificate(alias, password);
180         } catch (KeystoreException e) {
181             log.error("Error getting CA's certificate.", e);
182         }
183         return null;
184     }
185     
186     /**
187      * This method makes the CA issue a self-signed certificate with given details. This method is usually
188      * called while initializing the CA.
189      *
190      * @param sNo Serial number for self-signed certificate
191      * @param validFromDate Certificate validity period start date
192      * @param validToDate Certificate validity period end date
193      * @param algorithm Signature algorithm for self-signed certificate
194      */

195     public void issueOwnCertificate(BigInteger JavaDoc sNo, Date JavaDoc validFromDate, Date JavaDoc validToDate, String JavaDoc algorithm) throws CertificationAuthorityException{
196         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
197         try {
198             PublicKey JavaDoc publicKey = caCert.getPublicKey();
199             Certificate JavaDoc cert = issueCertificate(getName(), publicKey, sNo, validFromDate, validToDate, algorithm);
200             caKeystore.importPKCS7Certificate(alias, CaUtils.base64Certificate(cert), password);
201             caCert = cert;
202         } catch(Exception JavaDoc e) {
203             throw new CertificationAuthorityException("Error in issuing own certificate.", e);
204         }
205     }
206     
207     /**
208      * This method issues a certificate.
209      *
210      * @param subject Subject X500Principal
211      * @param publicKey Subject's public key
212      * @param sNo Serial number for the certificate to be issued
213      * @param validFromDate Certificate validity period start date
214      * @param validToDate Certificate validity period end date
215      * @param algorithm Signature algorithm for the certificate
216      * @return newly issued certificate
217      */

218     public Certificate JavaDoc issueCertificate(X500Principal JavaDoc subject, PublicKey JavaDoc publicKey, BigInteger JavaDoc sNo, Date JavaDoc validFromDate, Date JavaDoc validToDate, String JavaDoc algorithm) throws CertificationAuthorityException{
219         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
220         try {
221             X509Name subName = CaUtils.getX509Name(subject);
222             Certificate JavaDoc cert = issueCertificate(subName, caName, sNo, publicKey, caPrivateKey, validFromDate, validToDate, algorithm);
223             cert.verify(caPublicKey);
224             certStore.storeCertificate(cert);
225             return cert;
226         } catch(Exception JavaDoc e) {
227             throw new CertificationAuthorityException("Error in issuing certificate.", e);
228         }
229     }
230     
231     /**
232      * This method returns the highest serial number used by the CA.
233      */

234     public BigInteger JavaDoc getHighestSerialNumber() throws CertificationAuthorityException {
235         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
236         try {
237             return certStore.getHighestSerialNumber();
238         } catch (CertificateStoreException e) {
239             throw new CertificationAuthorityException("Error in getting highest serial number for CA.", e);
240         }
241     }
242     
243     /**
244      * This method checks if a Certificate with a given serial number is already issued.
245      * @param sNo The serial number of the the certificate to be looked for
246      * @return true if a certificate with the specified serial number has already been issued
247      */

248     public boolean isCertificateIssued(BigInteger JavaDoc sNo) throws CertificationAuthorityException {
249         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
250         return certStore.containsCertificate(sNo);
251     }
252     
253     /**
254      * This method returns the next serial number that can be used to issue a certificate and increments the
255      * highest serial number.
256      */

257     public BigInteger JavaDoc getNextSerialNumber() throws CertificationAuthorityException {
258         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
259         try {
260             return certStore.getNextSerialNumber();
261         } catch (CertificateStoreException e) {
262             throw new CertificationAuthorityException("Error in getting next serial number for CA.", e);
263         }
264     }
265     
266     /**
267      * This method retrieves a certificate with the specified serial number.
268      * @param sNo The serial number of the certificate to be retrieved
269      * @return java.security.cert.Certificate instance of the certificate
270      */

271     public Certificate JavaDoc getCertificate(BigInteger JavaDoc sNo) throws CertificationAuthorityException {
272         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
273         try {
274             return certStore.getCertificate(sNo);
275         } catch (CertificateStoreException e) {
276             throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e);
277         }
278     }
279
280     /**
281      * This method retrieves a certificate with the specified serial number.
282      * @param sNo The serial number of the certificate to be retrieved
283      * @return base64 encoded certificate text
284      */

285      public String JavaDoc getCertificateBase64Text(BigInteger JavaDoc sNo) throws CertificationAuthorityException {
286         if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
287         try {
288             return certStore.getCertificateBase64Text(sNo);
289         } catch (CertificateStoreException e) {
290             throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e);
291         }
292     }
293     
294     /**
295      * This method issues a certificate.
296      * @param subName Subject's name
297      * @param caName Issuer's name
298      * @param serialNum Serial number for the certificate
299      * @param subPubKey Subject's public key
300      * @param caPriKey Issuer's private key
301      * @param validFromDate Certificate validity period start date
302      * @param validToDate Certificate validity period end date
303      * @param algorithm Signature algorithm for the certificate
304      * @return issued certificate
305      */

306     private Certificate JavaDoc issueCertificate(X509Name subName, X509Name caName, BigInteger JavaDoc serialNum, PublicKey JavaDoc subPubKey, PrivateKey JavaDoc caPriKey, Date JavaDoc validFromDate, Date JavaDoc validToDate, String JavaDoc algorithm) throws Exception JavaDoc {
307         AlgorithmIdentifier algId = null;
308         if("MD2withRSA".equalsIgnoreCase(algorithm))
309             algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md2WithRSAEncryption);
310         else if("MD5withRSA".equalsIgnoreCase(algorithm))
311             algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
312         else if("SHA1withRSA".equalsIgnoreCase(algorithm))
313             algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
314         else
315             throw new CertificationAuthorityException("Signature algorithm "+algorithm+" is not supported.");
316         
317         ASN1InputStream ais = new ASN1InputStream(subPubKey.getEncoded());
318         DERObject subPubkeyDerObj = ais.readObject();
319         SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(subPubkeyDerObj);
320         
321         // Create certificate generator and initialize fields
322
// Certificate version is v3
323
V3TBSCertificateGenerator v3certGen = new V3TBSCertificateGenerator();
324         // Subject info
325
v3certGen.setSubject(subName);
326         v3certGen.setSubjectPublicKeyInfo(subPubKeyInfo);
327         // Issuer info
328
v3certGen.setIssuer(caName);
329         // serial number
330
v3certGen.setSerialNumber(new DERInteger(serialNum));
331         // validity
332
v3certGen.setStartDate(new Time(validFromDate));
333         v3certGen.setEndDate(new Time(validToDate));
334         // signature algorithm
335
v3certGen.setSignature(algId);
336         
337         // Get the certificate info to be signed
338
TBSCertificateStructure tbsCert = v3certGen.generateTBSCertificate();
339         byte[] tobesigned = tbsCert.getEncoded();
340         
341         // Create the signature
342
Signature JavaDoc signatureObj = Signature.getInstance(algorithm);
343         signatureObj.initSign(caPriKey);
344         signatureObj.update(tobesigned);
345         byte[] signature = signatureObj.sign();
346         
347         // Compose tbsCert, algId and signature into a DER sequence.
348
// This will be the certificate in DER encoded form
349
DEREncodableVector certDerVec = new DEREncodableVector();
350         certDerVec.add(tbsCert);
351         certDerVec.add(algId);
352         certDerVec.add(new DERBitString(signature));
353         DERSequence certDerSeq = new DERSequence(certDerVec);
354         byte[] certData = certDerSeq.getEncoded();
355         
356         // Create a java.security.cert.Certificate object
357
Certificate JavaDoc certificate = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream JavaDoc(certData));
358
359         return certificate;
360     }
361
362     public void doFail() {
363     }
364
365     public void doStart() throws Exception JavaDoc {
366         if(caKeystore.isKeystoreLocked()) {
367             lock();
368         }
369     }
370
371     public void doStop() throws Exception JavaDoc {
372     }
373     public static final GBeanInfo GBEAN_INFO;
374
375     static {
376         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(GeronimoCertificationAuthority.class, "CertificationAuthority");
377         infoFactory.addAttribute("kernel", Kernel.class, false);
378         infoFactory.addAttribute("abstractName", AbstractName.class, false);
379         infoFactory.addReference("ServerInfo", ServerInfo.class, NameFactory.GERONIMO_SERVICE);
380         infoFactory.addReference("KeystoreInstance", KeystoreInstance.class, NameFactory.KEYSTORE_INSTANCE);
381         infoFactory.addReference("CertificateStore", CertificateStore.class, "CertificateStore");
382         infoFactory.addReference("CertificateRequestStore", CertificateRequestStore.class, "CertificateRequestStore");
383         infoFactory.addInterface(CertificationAuthority.class);
384         infoFactory.setConstructor(new String JavaDoc[]{"ServerInfo", "KeystoreInstance", "CertificateStore", "CertificateRequestStore", "kernel", "abstractName"});
385
386         GBEAN_INFO = infoFactory.getBeanInfo();
387     }
388     public static GBeanInfo getGBeanInfo() {
389         return GBEAN_INFO;
390     }
391 }
392
Popular Tags