KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > security > util > CertificatesManager


1 /*
2  * JacORB - a free Java ORB
3  *
4  * Copyright (C) 1997-2004 Gerald Brose.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */

20
21 package org.jacorb.security.util;
22
23 import java.io.*;
24 import java.security.*;
25 import java.util.*;
26 import java.net.*;
27 import java.math.BigInteger JavaDoc;
28 import java.security.cert.CertificateException JavaDoc;
29
30 import iaik.security.rsa.*;
31 import iaik.x509.*;
32 import iaik.asn1.structures.*;
33 import iaik.asn1.*;
34 import iaik.x509.extensions.*;
35 import iaik.security.provider.IAIK;
36 import iaik.pkcs.pkcs8.*;
37 import iaik.utils.KeyAndCertificate;
38
39 /**
40  * @author André Benvenuti ( bnv ), UGFU, Generalstab, Bern
41  */

42
43 public class CertificatesManager {
44
45   /* -----------------05.12.98 19:16------------------------------*
46    * Genarates rsa key pair and a certificate for rsa public key. *
47    * *
48    * It also has utility methods called by the trust deciders. *
49    * *
50    * Author: André Benvenuti *
51    * -------------------------------------------------------------*/

52
53   public static int saveFormat = ASN1.PEM;
54   private static final String JavaDoc pass_phrase = "bnv_8.12.99_passpass_find_out_ORB_JacORB1_0/beta14_SSL";
55   private static Hashtable signers = new Hashtable (); // the trusted signers
56

57   /**
58    * Add a trusted signer to our signers hash table.
59    *
60    * @param certificate the certificate to be added as trusted
61    */

62   public static Principal addTrustedSigner(
63                  java.security.cert.X509Certificate JavaDoc certificate
64                                       )
65   {
66
67     if ( certificate == null ) {
68       System.out.println( "certificate is empty." );
69       System.exit ( 0 );
70     }
71     Principal dn = certificate.getSubjectDN ();
72     if ( dn == null ) {
73       System.out.println( "Unable to get dn from certificate." );
74       System.exit ( 0 );
75     }
76     Vector certs = ( Vector ) signers.get ( dn );
77     if( certs == null ) {
78       certs = new Vector( 4 );
79       signers.put( dn, certs );
80     }
81     certs.addElement( certificate );
82     if ( dn == null ) {
83       System.out.println( "Unable to add dn." );
84       System.exit ( 0 );
85     }
86     return dn;
87   }
88
89   /*
90    * Set the list with the certificates of the trusted signers.
91    * Previous trusted signers are deleted.
92    *
93    * @param certificateList the list of certificates
94    */

95   public static void setTrustedSigners ( X509Certificate[] certificateList ) {
96     signers = new Hashtable ();
97     for ( int i = 0; i < certificateList.length; i++ ) {
98       addTrustedSigner ( certificateList[ i ] );
99     }
100   }
101
102   /*
103    * This method checks every certificate in the chain if it was signed
104    * from an signer in our trusted signers list. This method also verifies that
105    * the certificate chain from the client has a certificate signed by a
106    * trusted signer.
107    */

108   public static boolean hasTrustedRoot (
109                java.security.cert.X509Certificate JavaDoc [] certificateChain
110                                        )
111   {
112     try {
113     // check all certificates for a trusted root
114
for ( int i = 0; i < certificateChain.length; i++ )
115       {
116         if ( i > 0 ) {
117         // we are looking for a trusted root for a certificate in the chain
118
certificateChain[ i - 1 ].verify (
119                            certificateChain[ i ].getPublicKey ()
120                                            );
121         }
122         Vector certs = ( Vector )signers.get(
123                             certificateChain[ i ].getSubjectDN ()
124                                             );
125         if ( certs == null ) {
126           continue;
127         } else
128             for( int j = 0; j < certs.size (); j++ ) {
129               X509Certificate currentCert = ( X509Certificate )certs.elementAt ( j );
130               if ( currentCert.equals ( certificateChain[ i ] )) return true;
131           
132             }
133       }
134     } catch ( Exception JavaDoc ex ) { return false; }
135     return false;
136   }
137
138   /*
139    * Encrypt the private key with a password according to PKCS#5 and PKCS#8.
140    * We encode a value of type PrivateKeyInfo keyPair.getPrivate()
141    * according to PKCS#8 to represent the private key in an
142    * algorithm-independent manner, which subsequently will be encrypted
143    * using the PbeWithMD5AndDES_CBC ( PKCS#5 ) algorithm and encoded
144    * as PKCS#8 and save the key and the certificate chain to a file.
145    */

146   public static void saveKeyAndCert ( KeyPair keyPair,
147                                       X509Certificate[] chain,
148                                       String JavaDoc fileName
149                                     ) throws IOException
150   {
151
152     EncryptedPrivateKeyInfo epki = new
153       EncryptedPrivateKeyInfo(( PrivateKeyInfo )keyPair.getPrivate ());
154     try {
155       epki.encrypt ( pass_phrase,
156                      AlgorithmID.pbeWithMD5AndDES_CBC, // PKCS#5 standard
157
null
158                    );
159     } catch ( NoSuchAlgorithmException ex ) {
160       throw new RuntimeException JavaDoc( "No implementation for pbeWithMD5AndDES_CBC!" );
161     }
162     // append the correct extension
163
fileName = fileName + ( saveFormat == ASN1.DER ? ".der" : ".pem" );
164     System.out.println( "save private key and certificate chain to file "
165                       + fileName
166                       + "..."
167                       );
168     new KeyAndCertificate( epki, chain ).saveTo( fileName, saveFormat );
169   }
170
171
172   /**
173    * Generate a KeyPair.
174    *
175    * @param bits the length of the key ( modulus ) in bits
176    * @return the KeyPair
177    */

178   public static KeyPair generateKeyPair( String JavaDoc algorithm,
179                                          int bits
180                                        )
181   {
182         try {
183       KeyPairGenerator generator =
184          KeyPairGenerator.getInstance( algorithm, "IAIK" );
185       generator.initialize( bits );
186       KeyPair kp = generator.generateKeyPair ();
187       return kp;
188     } catch ( NoSuchProviderException ex ) {
189       System.out.println ( "Provider IAIK not found!" );
190       return null;
191     } catch ( NoSuchAlgorithmException ex ) {
192       System.out.println ( "Algorithm " + algorithm + " not found!" );
193       return null;
194     }
195     }
196
197   /*
198    * Verifies a certificate chain.
199    *
200    * The certificate of the user is the first one in the list
201    * ( chain[0] ), and the top level certificate is the last one.
202    * chain[0] = user certificate.
203    * chain[x] = self signed CA certificate
204    *
205    * @chain the certificate chain to verify
206    * @return true if the certificate chain is o.k., false otherwise
207    */

208   public static boolean verifyCertificateChain ( java.security.cert.X509Certificate JavaDoc[] chain )
209   {
210     int len = chain.length;
211     try {
212       chain[ len - 1 ].verify( chain [ len - 1 ].getPublicKey ());
213       for ( int i = len - 1; i > 0; i-- )
214         chain[ i - 1 ].verify( chain[ i ].getPublicKey ());
215     } catch ( Exception JavaDoc ex ) { return false; }
216     return hasTrustedRoot ( chain );
217   }
218
219   /**
220    * Create a certificate.
221    */

222   public static X509Certificate createCertificate( Name subject,
223                                                    PublicKey pk,
224                                                    Name issuer,
225                                                    PrivateKey sk,
226                                                    AlgorithmID algorithm
227                                                   )
228   {
229
230     X509Certificate cert = new X509Certificate ();
231
232     try {
233       cert.setSerialNumber( new BigInteger JavaDoc( 20, new Random ()));
234       cert.setSubjectDN( subject );
235       cert.setPublicKey( pk );
236       cert.setIssuerDN( issuer );
237
238       // not before yesterday
239
GregorianCalendar date = new GregorianCalendar ();
240       date.add( Calendar.DATE, -1 );
241       cert.setValidNotBefore( date.getTime ());
242
243       // valid six monthe
244
date.add( Calendar.MONTH, 6 );
245       cert.setValidNotAfter( date.getTime ());
246
247       cert.sign( algorithm, sk );
248     } catch ( CertificateException JavaDoc ex ) {
249       System.out.println( "CertificateException: " + ex.getMessage ());
250       return null;
251     } catch ( InvalidKeyException ex ) {
252       System.out.println( "InvalidKeyException: " + ex.getMessage ());
253       return null;
254     } catch ( NoSuchAlgorithmException ex ) {
255       System.out.println( "NoSuchAlgorithmException: " + ex.getMessage ());
256       return null;
257     }
258
259     return cert;
260   }
261
262   /**
263    * Creates the server and client certificates.
264    */

265   public static void main( String JavaDoc arg[] ) throws IOException
266   {
267     boolean caFound = false;
268     boolean selfSigned = false;
269     String JavaDoc userName = null;
270     String JavaDoc caName = null;
271     KeyAndCertificate caKAC;
272     PrivateKey caRSA = null;
273     X509Certificate caCert = null;
274     X509Certificate cert;
275     KeyPair clientRSA;
276     KeyPair serverRSA;
277     iaik.pkcs.pkcs8.EncryptedPrivateKeyInfo epki;
278
279     if ( arg.length == 3 ) {
280       caFound = true;
281       if ( arg[ 0 ].equals ( "-ca" )) {
282         caName = arg[ 1 ]; userName = arg[ 2 ];
283       } else if ( arg[ 1 ].equals ( "-ca" )) {
284         System.out.println ( "caFound at 1" );
285         caName = arg[ 2 ]; userName = arg[ 0 ];
286       } else {
287         System.out.println ( "caNotFound" );
288         System.out.println ( "Usage: CerttificatesManager [-ca caName] userName" );
289         return;
290       }
291     } else if ( arg.length != 1 ) {
292       System.out.println ( "bad # params" );
293       System.out.println ( "Usage: CertificatesManager [-ca caName] userName" );
294       return;
295     } else {
296       userName = arg[ 0 ];
297       selfSigned = true;
298     }
299
300     try {
301       IAIK.addAsProvider();
302
303       File certsDir = new File( "certs" );
304       String JavaDoc caKeyAndCertFileName = null;
305       if ( certsDir.exists ()) {
306         if ( caFound ) {
307           caKeyAndCertFileName = "certs/"
308                                 + caName
309                                 + "KeyAndCert"
310                                 + ".pem";
311           caKAC = new KeyAndCertificate ( caKeyAndCertFileName );
312           epki = ( EncryptedPrivateKeyInfo ) caKAC.getPrivateKey ();
313           epki.decrypt ( pass_phrase );
314           caRSA = epki.getPrivateKeyInfo ();
315           caCert = caKAC.getCertificateChain ()[ 0 ];
316         }
317       } else if ( caName != null ) {
318         System.out.println ( "No certificate file "
319                            + caKeyAndCertFileName
320                            );
321             return;
322       } else certsDir.mkdir();
323
324       // enquire local host name for user
325
BufferedReader reader = new
326          BufferedReader ( new InputStreamReader ( System.in ));
327       String JavaDoc line;
328       String JavaDoc localhost = InetAddress.getLocalHost().getHostName ();
329       System.out.print( "Give server host name [" + localhost + "]:");
330       line = reader.readLine();
331       if ( line.length () != 0 ) {
332         localhost = line;
333       }
334
335       X509Certificate[] chain;
336
337       if ( !selfSigned && caFound ) {
338         System.out.println ( "Creating server certificates for "
339                            + userName + " at " + localhost + "\n"
340                            );
341         // First create the private keys
342
clientRSA = generateKeyPair ( "RSA", 1024 );
343         serverRSA = generateKeyPair ( "RSA", 1024 );
344
345         Name issuer = new Name();
346         issuer.addRDN ( ObjectID.country, "CH" );
347         issuer.addRDN ( ObjectID.organization , "EPFL" );
348         issuer.addRDN ( ObjectID.organizationalUnit , "SSLCertificateManager" );
349         issuer.addRDN ( ObjectID.commonName , caName );
350
351         Name serverSubject = new Name();
352         serverSubject.addRDN ( ObjectID.country, "CH");
353         serverSubject.addRDN ( ObjectID.organization , "EPFL");
354         serverSubject.addRDN ( ObjectID.commonName , userName
355                                                    + localhost
356                              );
357         // create server certificates
358
chain = new X509Certificate[ 2 ];
359         serverSubject.addRDN ( ObjectID.organizationalUnit,
360                                "RSA Server Certificate"
361                              );
362         chain[ 0 ] = createCertificate ( serverSubject,
363                                          serverRSA.getPublic(),
364                                          issuer,
365                                          caRSA,
366                                          AlgorithmID.md5WithRSAEncryption
367                                        );
368         chain[ 1 ] = caCert;
369         verifyCertificateChain( chain );
370         saveKeyAndCert ( serverRSA, chain,
371                          "certs/server" + userName + "KeyAndCert"
372                        );
373
374         System.out.println ( "Creating client test certificates for "
375                            + userName + " at " + localhost + "\n"
376                            );
377         Name clientSubject = new Name();
378         clientSubject.addRDN ( ObjectID.country, "CH");
379         clientSubject.addRDN ( ObjectID.organization , "EPFL");
380         clientSubject.addRDN ( ObjectID.commonName , "Client"
381                                                      + userName
382                                                      + localhost
383                              );
384       // create client certificates
385
chain = new X509Certificate[ 2 ];
386         clientSubject.addRDN ( ObjectID.organizationalUnit,
387                                "RSA Client Certificate"
388                              );
389         chain[ 0 ] = createCertificate ( clientSubject,
390                                          clientRSA.getPublic(),
391                                          issuer,
392                                          caRSA,
393                                          AlgorithmID.md5WithRSAEncryption
394                                        );
395         chain[ 1 ] = caCert;
396         verifyCertificateChain( chain );
397         saveKeyAndCert ( clientRSA, chain,
398                          "certs/client" + userName + "KeyAndCert"
399                        );
400
401       } else {
402         //
403
// create self signed CA certs
404
//
405

406         X509Certificate userCert = null;
407         chain = new X509Certificate[ 1 ];
408
409         System.out.println ( "create self signed RSA CA certificate..."
410                            + " for " + userName
411                            );
412         Name user = new Name();
413         user.addRDN ( ObjectID.country, "CH" );
414         user.addRDN ( ObjectID.organization , "EPFL" );
415         user.addRDN ( ObjectID.organizationalUnit , "SSLCertificateManager" );
416         user.addRDN ( ObjectID.commonName , userName );
417
418         KeyPair userRSA = generateKeyPair ( "RSA", 1024 );
419         userCert = createCertificate( user,
420                                       userRSA.getPublic(),
421                                       user,
422                                       userRSA.getPrivate(),
423                                       AlgorithmID.md5WithRSAEncryption
424                                     );
425         chain[ 0 ] = userCert;
426         OutputStream certFile = new FileOutputStream( "certs/"
427                                                     + userName
428                                                     + "Cert.pem"
429                                                     );
430         userCert.writeTo ( certFile ); certFile.close ();
431         saveKeyAndCert( userRSA,
432                         chain, "certs/"
433                       + userName
434                       + "KeyAndCert"
435                       );
436       }
437
438       System.out.println("\nServer and Client certificates created.");
439
440     } catch ( NoSuchAlgorithmException ex ) {
441       System.out.println( "NoSuchAlgorithmException: "+ex.toString());
442     } catch ( UnknownHostException ex ) {
443       System.out.print( "UnknownHostException: " + ex.getMessage ());
444     } catch ( CertificateException JavaDoc ex ) {
445       System.out.print( "CertificateException: " + ex.getMessage ());
446     } catch (Exception JavaDoc ex) {
447       System.out.println( "Other Exception: " + ex);
448     }
449
450     }
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464
Popular Tags