KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > util > CaUtils


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.util;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.ByteArrayInputStream JavaDoc;
22 import java.io.ByteArrayOutputStream JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStreamReader JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.security.InvalidKeyException JavaDoc;
29 import java.security.KeyFactory JavaDoc;
30 import java.security.NoSuchAlgorithmException JavaDoc;
31 import java.security.NoSuchProviderException JavaDoc;
32 import java.security.PublicKey JavaDoc;
33 import java.security.Signature JavaDoc;
34 import java.security.SignatureException JavaDoc;
35 import java.security.cert.Certificate JavaDoc;
36 import java.security.cert.CertificateEncodingException JavaDoc;
37 import java.security.spec.RSAPublicKeySpec JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.Hashtable JavaDoc;
40 import java.util.Map JavaDoc;
41 import java.util.Vector JavaDoc;
42
43 import javax.security.auth.x500.X500Principal JavaDoc;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.apache.geronimo.util.asn1.ASN1InputStream;
48 import org.apache.geronimo.util.asn1.ASN1Sequence;
49 import org.apache.geronimo.util.asn1.DERBitString;
50 import org.apache.geronimo.util.asn1.DERObject;
51 import org.apache.geronimo.util.asn1.DERSequence;
52 import org.apache.geronimo.util.asn1.DERString;
53 import org.apache.geronimo.util.asn1.pkcs.CertificationRequestInfo;
54 import org.apache.geronimo.util.asn1.pkcs.PKCSObjectIdentifiers;
55 import org.apache.geronimo.util.asn1.x509.RSAPublicKeyStructure;
56 import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo;
57 import org.apache.geronimo.util.asn1.x509.X509CertificateStructure;
58 import org.apache.geronimo.util.asn1.x509.X509Name;
59 import org.apache.geronimo.util.encoders.Base64;
60 import org.apache.geronimo.util.jce.PKCS10CertificationRequest;
61
62 /**
63  * This class implements some utility methods used by CA
64  *
65  * @version $Rev: 476291 $ $Date: 2006-11-17 15:05:24 -0500 (Fri, 17 Nov 2006) $
66  */

67 public class CaUtils {
68     private static final Log log = LogFactory.getLog(CaUtils.class);
69     public static final String JavaDoc CERT_HEADER = "-----BEGIN CERTIFICATE-----";
70     public static final String JavaDoc CERT_FOOTER = "-----END CERTIFICATE-----";
71     public static final String JavaDoc CERT_REQ_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
72     public static final int B64_LINE_SIZE = 76;
73     public static final String JavaDoc CERT_REQ_SUBJECT = "subject";
74     public static final String JavaDoc CERT_REQ_PUBLICKEY = "publickey";
75     public static final String JavaDoc CERT_REQ_PUBLICKEY_OBJ = "publickeyObj";
76     public static final String JavaDoc CERT_REQ_VERSION = "version";
77     public static final String JavaDoc PKAC_CHALLENGE = "challenge";
78
79     /**
80      * This method returns base64 encoded text of a given certificate.
81      * @param cert The certificate that needs to be encoded in base64
82      */

83     public static String JavaDoc base64Certificate(Certificate JavaDoc cert) throws CertificateEncodingException JavaDoc, Exception JavaDoc {
84         return base64Text(cert.getEncoded(), CaUtils.CERT_HEADER, CaUtils.CERT_FOOTER, CaUtils.B64_LINE_SIZE);
85     }
86     
87     /**
88      * This method encodes a given byte array into base64 along with specified header and footers.
89      * @param data The byte array to be encoded in base64
90      * @param header Header for base64 encoded text
91      * @param footer Footer for base64 encoded text
92      * @param lineSize Maximum line size to split base64 encoded text if required
93      */

94     public static String JavaDoc base64Text(byte[] data, String JavaDoc header, String JavaDoc footer, int lineSize) throws Exception JavaDoc {
95         ByteArrayOutputStream JavaDoc bout = new ByteArrayOutputStream JavaDoc();
96         storeInBase64(bout, data, header, footer, lineSize);
97         bout.close();
98         return bout.toString();
99     }
100     /**
101      * This method encodes a given byte array into base64 along with specified header and footers and writes
102      * the output to a specified OutputStream.
103      * @param fout Output stream to write the encoded text
104      * @param data The byte array to be encoded in base64
105      * @param header Header for base64 encoded text
106      * @param footer Footer for base64 encoded text
107      * @param lineSize Maximum line size to split base64 encoded text if required
108      */

109     public static void storeInBase64(OutputStream JavaDoc fout, byte[] data, String JavaDoc header, String JavaDoc footer, int lineSize) throws Exception JavaDoc {
110         PrintWriter JavaDoc out = new PrintWriter JavaDoc(fout);
111         if(header != null) out.println(header);
112
113         byte[] encodedData = Base64.encode(data);
114         int i = 0;
115         do {
116             out.println(new String JavaDoc(encodedData, i, Math.min(lineSize, encodedData.length-i)));
117             i += lineSize;
118         } while(i < encodedData.length);
119
120         if(footer != null) out.println(footer);
121         out.flush();
122     }
123
124     /**
125      * This method encodes a given byte array into base64 along with specified header and footers and writes
126      * the output to a specified file.
127      * @param outfile File name to write the output to
128      * @param data The byte array to be encoded in base64
129      * @param header Header for base64 encoded text
130      * @param footer Footer for base64 encoded text
131      * @param lineSize Maximum line size to split base64 encoded text if required
132      */

133     public static void storeInBase64(String JavaDoc outfile, byte[] data, String JavaDoc header, String JavaDoc footer, int lineSize) throws Exception JavaDoc {
134         FileOutputStream JavaDoc fout = new FileOutputStream JavaDoc(outfile);
135         storeInBase64(fout, data, header, footer, lineSize);
136         fout.close();
137     }
138
139     /**
140      * This method creates a java.security.PublicKey object based on the public key information given in SubjectPublicKeyInfo
141      * @param pubKeyInfo SubjectPublicKeyInfo instance containing the public key information.
142      */

143     public static PublicKey JavaDoc getPublicKeyObject(SubjectPublicKeyInfo pubKeyInfo) throws Exception JavaDoc{
144         RSAPublicKeyStructure pubkeyStruct = new RSAPublicKeyStructure((ASN1Sequence)pubKeyInfo.getPublicKey());
145         RSAPublicKeySpec JavaDoc pubkeySpec = new RSAPublicKeySpec JavaDoc(pubkeyStruct.getModulus(), pubkeyStruct.getPublicExponent());
146         KeyFactory JavaDoc keyFactory = KeyFactory.getInstance("RSA");
147         PublicKey JavaDoc pubKey = keyFactory.generatePublic(pubkeySpec);
148         return pubKey;
149     }
150     
151     /**
152      * This method returns a X509Name object corresponding to the subject in a given certificate
153      * @param cert Certificate from which subject needs to be retrieved
154      */

155     public static X509Name getSubjectX509Name(Certificate JavaDoc cert) throws CertificateEncodingException JavaDoc, IOException JavaDoc {
156         ASN1InputStream ais = new ASN1InputStream(cert.getEncoded());
157         X509CertificateStructure x509Struct = new X509CertificateStructure((ASN1Sequence)ais.readObject());
158         ais.close();
159         return x509Struct.getSubject();
160     }
161
162     /**
163      * This method returns a X509Name object corresponding to a given principal
164      */

165     public static X509Name getX509Name(X500Principal JavaDoc principal) throws CertificateEncodingException JavaDoc, IOException JavaDoc {
166         ASN1InputStream ais = new ASN1InputStream(principal.getEncoded());
167         X509Name name = new X509Name((ASN1Sequence)ais.readObject());
168         ais.close();
169         return name;
170     }
171
172     /**
173      * This method processes a certificate request and returns a map containing subject
174      * and public key in the request.
175      * @param certreq base64 encoded PKCS10 certificate request
176      */

177     public static Map JavaDoc processPKCS10Request(String JavaDoc certreq) throws InvalidKeyException JavaDoc, NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc, SignatureException JavaDoc, Exception JavaDoc {
178         if(certreq.indexOf("-----") != -1) {
179             // Strip any header and footer
180
BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(new ByteArrayInputStream JavaDoc(certreq.getBytes())));
181             String JavaDoc line = null;
182             String JavaDoc b64data = "";
183             while((line = br.readLine()) != null) {
184                 if(!line.startsWith("-----")) {
185                     b64data += line;
186                 }
187             }
188             br.close();
189             certreq = b64data;
190         }
191         byte[] data = Base64.decode(certreq);
192         
193         PKCS10CertificationRequest pkcs10certreq = new PKCS10CertificationRequest(data);
194         if(!pkcs10certreq.verify()) {
195             throw new Exception JavaDoc("CSR verification failed.");
196         }
197         CertificationRequestInfo certReqInfo = pkcs10certreq.getCertificationRequestInfo();
198         Map JavaDoc map = new HashMap JavaDoc();
199         map.put(CERT_REQ_SUBJECT, certReqInfo.getSubject());
200         map.put(CERT_REQ_PUBLICKEY, certReqInfo.getSubjectPublicKeyInfo());
201         map.put(CERT_REQ_PUBLICKEY_OBJ, getPublicKeyObject(certReqInfo.getSubjectPublicKeyInfo()));
202         map.put(CERT_REQ_VERSION, certReqInfo.getVersion());
203         return map;
204     }
205     
206     /**
207      * This method processes a DER encoded SignedPublicKeyAndChallenge in base64 format.
208      * @param spkac SignedPublicKeyAndChallenge in base64 text format
209      * @return a Map with Subject, public-key and challenge
210      */

211     public static Map JavaDoc processSPKAC(String JavaDoc spkac) throws IOException JavaDoc, NoSuchAlgorithmException JavaDoc, InvalidKeyException JavaDoc, SignatureException JavaDoc, Exception JavaDoc {
212         Map JavaDoc map = new HashMap JavaDoc();
213         byte[]data = Base64.decode(spkac);
214         ASN1InputStream ais = new ASN1InputStream(new ByteArrayInputStream JavaDoc(data));
215         DERSequence spkacSeq = (DERSequence)ais.readObject();
216
217         // SPKAC = SEQ {PKAC, SIGN-ALG, SIGN}
218
// Get PKAC and obtain PK and C
219
DERSequence pkacSeq = (DERSequence)spkacSeq.getObjectAt(0);
220         DERObject pk = (DERObject)pkacSeq.getObjectAt(0);
221         DERObject ch = (DERObject)pkacSeq.getObjectAt(1);
222         SubjectPublicKeyInfo pkInfo = new SubjectPublicKeyInfo((DERSequence)pk);
223         PublicKey JavaDoc pubKey = getPublicKeyObject(pkInfo);
224
225         // Get SIGN-ALG
226
DERSequence signAlg = (DERSequence) spkacSeq.getObjectAt(1);
227         DERObject alg0 = (DERObject)signAlg.getObjectAt(0);
228
229         // Get SIGN
230
DERBitString sign = (DERBitString) spkacSeq.getObjectAt(2);
231         byte[] signature = sign.getBytes();
232         
233         // Verify the signature on SPKAC
234
String JavaDoc signAlgString = PKCSObjectIdentifiers.md5WithRSAEncryption.equals(alg0) ? "MD5withRSA" :
235                                PKCSObjectIdentifiers.md2WithRSAEncryption.equals(alg0) ? "MD2withRSA" :
236                                PKCSObjectIdentifiers.sha1WithRSAEncryption.equals(alg0) ? "SHA1withRSA" : null;
237         Signature JavaDoc signObj = Signature.getInstance(signAlgString);
238         signObj.initVerify(pubKey);
239         signObj.update(pkacSeq.getEncoded());
240         boolean verified = signObj.verify(signature);
241         if(!verified) throw new Exception JavaDoc("SignedPublicKeyAndChallenge verification failed.");
242         map.put(CERT_REQ_PUBLICKEY, pkInfo);
243         map.put(CERT_REQ_PUBLICKEY_OBJ, pubKey);
244         if(((DERString)ch).getString() != null) map.put(PKAC_CHALLENGE, ((DERString)ch).getString());
245         return map;
246     }
247     
248     /**
249      * This method creates a X509Name object using the name attributes specified.
250      * @param cn Common Name
251      * @param ou Organization Unit
252      * @param o Organization
253      * @param l Locality
254      * @param st State
255      * @param c Country
256      */

257     public static X509Name getX509Name(String JavaDoc cn, String JavaDoc ou, String JavaDoc o, String JavaDoc l, String JavaDoc st, String JavaDoc c) {
258         Vector JavaDoc order = new Vector JavaDoc();
259         Hashtable JavaDoc attrmap = new Hashtable JavaDoc();
260         if (c != null) {
261             attrmap.put(X509Name.C, c);
262             order.add(X509Name.C);
263         }
264
265         if (st != null) {
266             attrmap.put(X509Name.ST, st);
267             order.add(X509Name.ST);
268         }
269
270         if (l != null) {
271             attrmap.put(X509Name.L, l);
272             order.add(X509Name.L);
273         }
274
275         if (o != null) {
276             attrmap.put(X509Name.O, o);
277             order.add(X509Name.O);
278         }
279
280         if (ou != null) {
281             attrmap.put(X509Name.OU, ou);
282             order.add(X509Name.OU);
283         }
284
285         if (cn != null) {
286             attrmap.put(X509Name.CN, cn);
287             order.add(X509Name.CN);
288         }
289
290         return new X509Name(order, attrmap);
291     }
292 }
293
Popular Tags