org/objectweb/proactive/ext/security/CertTools.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.ext.security;
00032 
00033 import java.io.BufferedReader;
00034 import java.io.ByteArrayInputStream;
00035 import java.io.ByteArrayOutputStream;
00036 import java.io.FileInputStream;
00037 import java.io.IOException;
00038 import java.io.InputStream;
00039 import java.io.InputStreamReader;
00040 import java.io.PrintStream;
00041 import java.net.URL;
00042 import java.security.InvalidKeyException;
00043 import java.security.KeyPair;
00044 import java.security.MessageDigest;
00045 import java.security.NoSuchAlgorithmException;
00046 import java.security.NoSuchProviderException;
00047 import java.security.PrivateKey;
00048 import java.security.PublicKey;
00049 import java.security.SecureRandom;
00050 import java.security.Security;
00051 import java.security.SignatureException;
00052 import java.security.cert.CRLException;
00053 import java.security.cert.CertificateEncodingException;
00054 import java.security.cert.CertificateException;
00055 import java.security.cert.CertificateFactory;
00056 import java.security.cert.CertificateParsingException;
00057 import java.security.cert.X509CRL;
00058 import java.security.cert.X509Certificate;
00059 import java.util.ArrayList;
00060 import java.util.Collection;
00061 import java.util.Date;
00062 import java.util.HashMap;
00063 import java.util.Iterator;
00064 import java.util.List;
00065 import java.util.Vector;
00066 
00067 import org.apache.log4j.Logger;
00068 import org.bouncycastle.asn1.ASN1InputStream;
00069 import org.bouncycastle.asn1.ASN1OctetString;
00070 import org.bouncycastle.asn1.ASN1Sequence;
00071 import org.bouncycastle.asn1.ASN1TaggedObject;
00072 import org.bouncycastle.asn1.DERObject;
00073 import org.bouncycastle.asn1.DERObjectIdentifier;
00074 import org.bouncycastle.asn1.DEROctetString;
00075 import org.bouncycastle.asn1.DERSequence;
00076 import org.bouncycastle.asn1.DERTaggedObject;
00077 import org.bouncycastle.asn1.DERUTF8String;
00078 import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
00079 import org.bouncycastle.asn1.x509.BasicConstraints;
00080 import org.bouncycastle.asn1.x509.PolicyInformation;
00081 import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
00082 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
00083 import org.bouncycastle.asn1.x509.X509Extensions;
00084 import org.bouncycastle.asn1.x509.X509Name;
00085 import org.bouncycastle.asn1.x509.X509NameTokenizer;
00086 import org.bouncycastle.jce.X509KeyUsage;
00087 import org.bouncycastle.jce.provider.BouncyCastleProvider;
00088 import org.bouncycastle.util.encoders.Base64;
00089 import org.bouncycastle.util.encoders.Hex;
00090 import org.bouncycastle.x509.X509V3CertificateGenerator;
00091 import org.objectweb.proactive.core.util.log.Loggers;
00092 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00093 
00094 
00099 public class CertTools {
00100     static Logger log = ProActiveLogger.getLogger(Loggers.SECURITY);
00101     public static final String EMAIL = "rfc822name";
00102     public static final String EMAIL1 = "email";
00103     public static final String EMAIL2 = "EmailAddress";
00104     public static final String EMAIL3 = "E";
00105     public static final String DNS = "dNSName";
00106     public static final String URI = "uniformResourceIdentifier";
00107     public static final String URI1 = "uri";
00108 
00110     public static final String UPN = "upn";
00111 
00113     public static final String UPN_OBJECTID = "1.3.6.1.4.1.311.20.2.3";
00114     private static final String[] EMAILIDS = { EMAIL, EMAIL1, EMAIL2, EMAIL3 };
00115 
00119     private CertTools() {
00120     }
00121 
00123     private static final HashMap<String,DERObjectIdentifier> oids = new HashMap<String,DERObjectIdentifier>();
00124   
00125     static {
00126         oids.put("c", X509Name.C);
00127         oids.put("dc", X509Name.DC);
00128         oids.put("st", X509Name.ST);
00129         oids.put("l", X509Name.L);
00130         oids.put("o", X509Name.O);
00131         oids.put("ou", X509Name.OU);
00132         oids.put("t", X509Name.T);
00133         oids.put("surname", X509Name.SURNAME);
00134         oids.put("initials", X509Name.INITIALS);
00135         oids.put("givenname", X509Name.GIVENNAME);
00136         oids.put("gn", X509Name.GIVENNAME);
00137         oids.put("sn", X509Name.SN);
00138         oids.put("serialnumber", X509Name.SN);
00139         oids.put("cn", X509Name.CN);
00140         oids.put("uid", X509Name.UID);
00141         oids.put("emailaddress", X509Name.EmailAddress);
00142         oids.put("e", X509Name.EmailAddress);
00143         oids.put("email", X509Name.EmailAddress);
00144     }
00145     ;
00146     private static final String[] dNObjectsForward = {
00147             "emailaddress", "e", "email", "uid", "cn", "sn", "serialnumber",
00148             "gn", "givenname", "initials", "surname", "t", "ou", "o", "l", "st",
00149             "dc", "c"
00150         };
00151     private static final String[] dNObjectsReverse = {
00152             "c", "dc", "st", "l", "o", "ou", "t", "surname", "initials",
00153             "givenname", "gn", "serialnumber", "sn", "cn", "uid", "email", "e",
00154             "emailaddress"
00155         };
00156 
00158     private static final String[] dNObjects = dNObjectsForward;
00159 
00160     private static DERObjectIdentifier getOid(String o) {
00161         return (DERObjectIdentifier) oids.get(o.toLowerCase());
00162     } // getOid
00163 
00176     public static X509Name stringToBcX509Name(String dn) {
00177         //log.debug(">stringToBcX509Name: " + dn);
00178         // first make two vectors, one with all the C, O, OU etc specifying
00179         // the order and one holding the actual values
00180         ArrayList<String> oldordering = new ArrayList<String>();
00181         ArrayList<String> oldvalues = new ArrayList<String>();
00182         X509NameTokenizer xt = new X509NameTokenizer(dn);
00183 
00184         while (xt.hasMoreTokens()) {
00185             // This is a pair (CN=xx)
00186             String pair = xt.nextToken();
00187             int ix = pair.indexOf("=");
00188 
00189             if (ix != -1) {
00190                 // make lower case so we can easily compare later
00191                 oldordering.add(pair.substring(0, ix).toLowerCase());
00192                 oldvalues.add(pair.substring(ix + 1));
00193             } else {
00194                 // Huh, what's this?
00195             }
00196         }
00197 
00198         // Now in the specified order, move from oldordering to newordering,
00199         // reshuffling as we go along
00200         Vector<DERObjectIdentifier> ordering = new Vector<DERObjectIdentifier>();
00201         Vector<String> values = new Vector<String>();
00202         int index = -1;
00203 
00204         for (int i = 0; i < dNObjects.length; i++) {
00205             //log.debug("Looking for "+objects[i]);
00206             String object = dNObjects[i];
00207 
00208             while ((index = oldordering.indexOf(object)) != -1) {
00209                 //log.debug("Found 1 "+object+" at index " + index);
00210                 DERObjectIdentifier oid = getOid(object);
00211 
00212                 if (oid != null) {
00213                     //log.debug("Added "+object+", "+oldvalues.elementAt(index));
00214                     ordering.add(oid);
00215 
00216                     // remove from the old vectors, so we start clean the next round
00217                     values.add(oldvalues.remove(index));
00218                     oldordering.remove(index);
00219                     index = -1;
00220                 }
00221             }
00222         }
00223 
00224         /*
00225            if (log.isDebugEnabled()) {
00226                Iterator i1 = ordering.iterator();
00227                Iterator i2 = values.iterator();
00228                log.debug("Order: ");
00229                while (i1.hasNext()) {
00230                    log.debug(((DERObjectIdentifier)i1.next()).getId());
00231                }
00232                log.debug("Values: ");
00233                while (i2.hasNext()) {
00234                    log.debug((String)i2.next());
00235                }
00236            } */
00237 
00238         //log.debug("<stringToBcX509Name");
00239         return new X509Name(ordering, values);
00240     } // stringToBcX509Name
00241 
00250     public static String stringToBCDNString(String dn) {
00251         //log.debug(">stringToBcDNString: "+dn);
00252         String ret = stringToBcX509Name(dn).toString();
00253 
00254         //log.debug("<stringToBcDNString: "+ret);
00255         return ret;
00256     }
00257 
00258     //    * Convenience method for getting an email address from a DN. Uses {@link
00259     //    * getPartFromDN(String,String)} internally, and searches for {@link EMAIL}, {@link EMAIL1},
00260     //    * {@link EMAIL2}, {@link EMAIL3} and returns the first one found.
00261 
00267     public static String getEmailFromDN(String dn) {
00268         log.debug(">getEmailFromDN(" + dn + ")");
00269 
00270         String email = null;
00271 
00272         for (int i = 0; (i < EMAILIDS.length) && (email == null); i++) {
00273             email = getPartFromDN(dn, EMAILIDS[i]);
00274         }
00275 
00276         log.debug("<getEmailFromDN(" + dn + "): " + email);
00277 
00278         return email;
00279     }
00280 
00290     public static String getPartFromDN(String dn, String dnpart) {
00291         log.debug(">getPartFromDN: dn:'" + dn + "', dnpart=" + dnpart);
00292 
00293         String part = null;
00294 
00295         if ((dn != null) && (dnpart != null)) {
00296             String o;
00297             dnpart += "="; // we search for 'CN=' etc.
00298 
00299             X509NameTokenizer xt = new X509NameTokenizer(dn);
00300 
00301             while (xt.hasMoreTokens()) {
00302                 o = xt.nextToken();
00303 
00304                 //log.debug("checking: "+o.substring(0,dnpart.length()));
00305                 if ((o.length() > dnpart.length()) &&
00306                         o.substring(0, dnpart.length()).equalsIgnoreCase(dnpart)) {
00307                     part = o.substring(dnpart.length());
00308 
00309                     break;
00310                 }
00311             }
00312         }
00313 
00314         log.debug("<getpartFromDN: resulting DN part=" + part);
00315 
00316         return part;
00317     } //getPartFromDN
00318 
00326     public static String getSubjectDN(X509Certificate cert) {
00327         return getDN(cert, 1);
00328     }
00329 
00337     public static String getIssuerDN(X509Certificate cert) {
00338         return getDN(cert, 2);
00339     }
00340 
00349     private static String getDN(X509Certificate cert, int which) {
00350         //log.debug(">getDN("+which+")");
00351         String dn = null;
00352         if (cert == null) {
00353             return dn;
00354         }
00355         try {
00356             CertificateFactory cf = CertTools.getCertificateFactory();
00357             X509Certificate x509cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00358                         cert.getEncoded()));
00359 
00360             //log.debug("Created certificate of class: " + x509cert.getClass().getName());
00361             if (which == 1) {
00362                 dn = x509cert.getSubjectDN().toString();
00363             } else {
00364                 dn = x509cert.getIssuerDN().toString();
00365             }
00366         } catch (CertificateException ce) {
00367             log.error("CertificateException: ", ce);
00368             return null;
00369         }
00370 
00371         //log.debug("<getDN("+which+"):"+dn);
00372         return stringToBCDNString(dn);
00373     } // getDN
00374 
00382     public static String getIssuerDN(X509CRL crl) {
00383         //log.debug(">getIssuerDN(crl)");
00384         String dn = null;
00385         try {
00386             CertificateFactory cf = CertTools.getCertificateFactory();
00387             X509CRL x509crl = (X509CRL) cf.generateCRL(new ByteArrayInputStream(
00388                         crl.getEncoded()));
00389 
00390             //log.debug("Created certificate of class: " + x509crl.getClass().getName());
00391             dn = x509crl.getIssuerDN().toString();
00392         } catch (CRLException ce) {
00393             log.error("CRLException: ", ce);
00394 
00395             return null;
00396         }
00397 
00398         //log.debug("<getIssuerDN(crl):"+dn);
00399         return stringToBCDNString(dn);
00400     } // getIssuerDN
00401 
00402     public static CertificateFactory getCertificateFactory() {
00403         try {
00404             return CertificateFactory.getInstance("X.509", "BC");
00405         } catch (NoSuchProviderException nspe) {
00406             log.error("NoSuchProvider: ", nspe);
00407         } catch (CertificateException ce) {
00408             log.error("CertificateException: ", ce);
00409         }
00410         return null;
00411     }
00412 
00413     public static void installBCProvider() {
00414         // we need to check if the BouncyCastle provider is already installed
00415         // before installing it
00416         if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
00417             Security.addProvider(new BouncyCastleProvider());
00418         }
00419         
00420      
00421     }
00422 
00432     public static Collection getCertsFromPEM(String certFile)
00433         throws IOException, CertificateException {
00434         log.debug(">getCertfromPEM: certFile=" + certFile);
00435         InputStream inStrm = new FileInputStream(certFile);
00436         Collection certs = getCertsFromPEM(inStrm);
00437         log.debug("<getCertfromPEM: certFile=" + certFile);
00438         return certs;
00439     }
00440 
00450     public static Collection getCertsFromPEM(InputStream certstream)
00451         throws IOException, CertificateException {
00452         log.debug(">getCertfromPEM:");
00453         ArrayList<X509Certificate> ret = new ArrayList<X509Certificate>();
00454         String beginKey = "-----BEGIN CERTIFICATE-----";
00455         String endKey = "-----END CERTIFICATE-----";
00456         BufferedReader bufRdr = new BufferedReader(new InputStreamReader(
00457                     certstream));
00458         while (bufRdr.ready()) {
00459             ByteArrayOutputStream ostr = new ByteArrayOutputStream();
00460             PrintStream opstr = new PrintStream(ostr);
00461             String temp;
00462             while (((temp = bufRdr.readLine()) != null) &&
00463                     !temp.equals(beginKey))
00464                 continue;
00465             if (temp == null) {
00466                 throw new IOException("Error in " + certstream.toString() +
00467                     ", missing " + beginKey + " boundary");
00468             }
00469             while (((temp = bufRdr.readLine()) != null) &&
00470                     !temp.equals(endKey))
00471                 opstr.print(temp);
00472             if (temp == null) {
00473                 throw new IOException("Error in " + certstream.toString() +
00474                     ", missing " + endKey + " boundary");
00475             }
00476             opstr.close();
00477 
00478             byte[] certbuf = Base64.decode(ostr.toByteArray());
00479             ostr.close();
00480             // Phweeew, were done, now decode the cert from file back to X509Certificate object
00481             CertificateFactory cf = CertTools.getCertificateFactory();
00482             X509Certificate x509cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00483                         certbuf));
00484             String dn = x509cert.getSubjectDN().toString();
00485             ret.add(x509cert);
00486         }
00487 
00488         log.debug("<getcertfromPEM:" + ret.size());
00489         return ret;
00490     } // getCertsFromPEM
00491 
00500     public static byte[] getPEMFromCerts(Collection certs)
00501         throws CertificateException {
00502         String beginKey = "-----BEGIN CERTIFICATE-----";
00503         String endKey = "-----END CERTIFICATE-----";
00504         ByteArrayOutputStream ostr = new ByteArrayOutputStream();
00505         PrintStream opstr = new PrintStream(ostr);
00506         Iterator iter = certs.iterator();
00507         while (iter.hasNext()) {
00508             X509Certificate cert = (X509Certificate) iter.next();
00509             byte[] certbuf = Base64.encode(cert.getEncoded());
00510             opstr.println("Subject: " + cert.getSubjectDN());
00511             opstr.println("Issuer: " + cert.getIssuerDN());
00512             opstr.println(beginKey);
00513             opstr.println(new String(certbuf));
00514             opstr.println(endKey);
00515         }
00516         opstr.close();
00517         byte[] ret = ostr.toByteArray();
00518         return ret;
00519     }
00520 
00531     public static X509Certificate getCertfromByteArray(byte[] cert)
00532         throws IOException, CertificateException {
00533         log.debug(">getCertfromByteArray:");
00534 
00535         CertificateFactory cf = CertTools.getCertificateFactory();
00536         X509Certificate x509cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00537                     cert));
00538         log.debug("<getCertfromByteArray:");
00539 
00540         return x509cert;
00541     } // getCertfromByteArray
00542 
00554     public static X509CRL getCRLfromByteArray(byte[] crl)
00555         throws IOException, CertificateException, CRLException {
00556         log.debug(">getCRLfromByteArray:");
00557 
00558         if (crl == null) {
00559             throw new IOException("Cannot read byte[] that is 'null'!");
00560         }
00561 
00562         CertificateFactory cf = CertTools.getCertificateFactory();
00563         X509CRL x509crl = (X509CRL) cf.generateCRL(new ByteArrayInputStream(crl));
00564         log.debug("<getCRLfromByteArray:");
00565 
00566         return x509crl;
00567     } // getCRLfromByteArray
00568 
00576     public static boolean isSelfSigned(X509Certificate cert) {
00577         log.debug(">isSelfSigned: cert: " + CertTools.getIssuerDN(cert) + "\n" +
00578             CertTools.getSubjectDN(cert));
00579 
00580         boolean ret = CertTools.getSubjectDN(cert).equals(CertTools.getIssuerDN(
00581                     cert));
00582         log.debug("<isSelfSigned:" + ret);
00583 
00584         return ret;
00585     } // isSelfSigned
00586 
00603     public static X509Certificate genSelfCert(String dn, long validity,
00604         String policyId, PrivateKey privKey, PublicKey pubKey, boolean isCA)
00605         throws NoSuchAlgorithmException, SignatureException, 
00606             InvalidKeyException {
00607         // Create self signed certificate
00608         String sigAlg = "SHA1WithRSA";
00609         Date firstDate = new Date();
00610 
00611         // Set back startdate ten minutes to avoid some problems with wrongly set clocks.
00612         firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
00613 
00614         Date lastDate = new Date();
00615 
00616         // validity in days = validity*24*60*60*1000 milliseconds
00617         lastDate.setTime(lastDate.getTime() +
00618             (validity * (24 * 60 * 60 * 1000)));
00619 
00620         X509V3CertificateGenerator certgen = new X509V3CertificateGenerator();
00621 
00622         // Serialnumber is random bits, where random generator is initialized with Date.getTime() when this
00623         // bean is created.
00624         byte[] serno = new byte[8];
00625         SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
00626         random.setSeed((long) (new Date().getTime()));
00627         random.nextBytes(serno);
00628         certgen.setSerialNumber((new java.math.BigInteger(serno)).abs());
00629         certgen.setNotBefore(firstDate);
00630         certgen.setNotAfter(lastDate);
00631         certgen.setSignatureAlgorithm(sigAlg);
00632         certgen.setSubjectDN(CertTools.stringToBcX509Name(dn));
00633         certgen.setIssuerDN(CertTools.stringToBcX509Name(dn));
00634         certgen.setPublicKey(pubKey);
00635 
00636         // Basic constranits is always critical and MUST be present at-least in CA-certificates.
00637         BasicConstraints bc = new BasicConstraints(isCA);
00638         certgen.addExtension(X509Extensions.BasicConstraints.getId(), true, bc);
00639 
00640         // Put critical KeyUsage in CA-certificates
00641         if (isCA == true) {
00642             int keyusage = X509KeyUsage.keyCertSign + X509KeyUsage.cRLSign;
00643             X509KeyUsage ku = new X509KeyUsage(keyusage);
00644             certgen.addExtension(X509Extensions.KeyUsage.getId(), true, ku);
00645         }
00646 
00647         // Subject and Authority key identifier is always non-critical and MUST be present for certificates to verify in Mozilla.
00648         try {
00649             if (isCA == true) {
00650                 SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(
00651                             new ByteArrayInputStream(pubKey.getEncoded())).readObject());
00652                 SubjectKeyIdentifier ski = new SubjectKeyIdentifier(spki);
00653 
00654                 SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(
00655                             new ByteArrayInputStream(pubKey.getEncoded())).readObject());
00656                 AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
00657 
00658                 certgen.addExtension(X509Extensions.SubjectKeyIdentifier.getId(),
00659                     false, ski);
00660                 certgen.addExtension(X509Extensions.AuthorityKeyIdentifier.getId(),
00661                     false, aki);
00662             }
00663         } catch (IOException e) { // do nothing
00664         }
00665 
00666         // CertificatePolicies extension if supplied policy ID, always non-critical
00667         if (policyId != null) {
00668             PolicyInformation pi = new PolicyInformation(new DERObjectIdentifier(
00669                         policyId));
00670             DERSequence seq = new DERSequence(pi);
00671             certgen.addExtension(X509Extensions.CertificatePolicies.getId(),
00672                 false, seq);
00673         }
00674 
00675         X509Certificate selfcert = certgen.generateX509Certificate(privKey);
00676 
00677         return selfcert;
00678     } //genselfCert
00679 
00680     public static X509Certificate genCert(String dn, long validity,
00681         String policyId, PrivateKey privKey, PublicKey pubKey, boolean isCA,
00682         String caDn, PrivateKey caPrivateKey, PublicKey acPubKey)
00683         throws NoSuchAlgorithmException, SignatureException, 
00684             InvalidKeyException {
00685         // Create self signed certificate
00686         String sigAlg = "SHA1WithRSA";
00687         Date firstDate = new Date();
00688 
00689         // Set back startdate ten minutes to avoid some problems with wrongly set clocks.
00690         firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
00691 
00692         Date lastDate = new Date();
00693 
00694         // validity in days = validity*24*60*60*1000 milliseconds
00695         lastDate.setTime(lastDate.getTime() +
00696             (validity * (24 * 60 * 60 * 1000)));
00697 
00698         X509V3CertificateGenerator certgen = new X509V3CertificateGenerator();
00699 
00700         // Serialnumber is random bits, where random generator is initialized with Date.getTime() when this
00701         // bean is created.
00702         byte[] serno = new byte[8];
00703         SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
00704         random.setSeed((long) (new Date().getTime()));
00705         random.nextBytes(serno);
00706         certgen.setSerialNumber((new java.math.BigInteger(serno)).abs());
00707         certgen.setNotBefore(firstDate);
00708         certgen.setNotAfter(lastDate);
00709         certgen.setSignatureAlgorithm(sigAlg);
00710         certgen.setSubjectDN(CertTools.stringToBcX509Name(dn));
00711         certgen.setIssuerDN(CertTools.stringToBcX509Name(caDn));
00712         certgen.setPublicKey(pubKey);
00713 
00714         // Basic constranits is always critical and MUST be present at-least in CA-certificates.
00715         BasicConstraints bc = new BasicConstraints(isCA);
00716         certgen.addExtension(X509Extensions.BasicConstraints.getId(), true, bc);
00717 
00718         // Put critical KeyUsage in CA-certificates
00719         if (false) {
00720             //if (isCA == true) {
00721             int keyusage = X509KeyUsage.keyCertSign + X509KeyUsage.cRLSign;
00722             X509KeyUsage ku = new X509KeyUsage(keyusage);
00723             certgen.addExtension(X509Extensions.KeyUsage.getId(), true, ku);
00724         }
00725 
00726         // Subject and Authority key identifier is always non-critical and MUST be present for certificates to verify in Mozilla.
00727         try {
00728             if (false) {
00729                 //if (isCA == true) {
00730                 SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(
00731                             new ByteArrayInputStream(pubKey.getEncoded())).readObject());
00732                 SubjectKeyIdentifier ski = new SubjectKeyIdentifier(spki);
00733 
00734                 SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(
00735                             new ByteArrayInputStream(acPubKey.getEncoded())).readObject());
00736                 AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
00737 
00738                 certgen.addExtension(X509Extensions.SubjectKeyIdentifier.getId(),
00739                     false, ski);
00740                 certgen.addExtension(X509Extensions.AuthorityKeyIdentifier.getId(),
00741                     false, aki);
00742             }
00743         } catch (IOException e) { // do nothing
00744         }
00745 
00746         // CertificatePolicies extension if supplied policy ID, always non-critical
00747         if (policyId != null) {
00748             PolicyInformation pi = new PolicyInformation(new DERObjectIdentifier(
00749                         policyId));
00750             DERSequence seq = new DERSequence(pi);
00751             certgen.addExtension(X509Extensions.CertificatePolicies.getId(),
00752                 false, seq);
00753         }
00754 
00755         X509Certificate selfcert = certgen.generateX509Certificate(caPrivateKey);
00756 
00757         return selfcert;
00758     } //genselfCert
00759 
00767     public static byte[] getAuthorityKeyId(X509Certificate cert)
00768         throws IOException {
00769         byte[] extvalue = cert.getExtensionValue("2.5.29.35");
00770         if (extvalue == null) {
00771             return null;
00772         }
00773         DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(
00774                     extvalue)).readObject());
00775         AuthorityKeyIdentifier keyId = new AuthorityKeyIdentifier((ASN1Sequence) new ASN1InputStream(
00776                     new ByteArrayInputStream(oct.getOctets())).readObject());
00777         return keyId.getKeyIdentifier();
00778     } // getAuthorityKeyId
00779 
00787     public static byte[] getSubjectKeyId(X509Certificate cert)
00788         throws IOException {
00789         byte[] extvalue = cert.getExtensionValue("2.5.29.14");
00790         if (extvalue == null) {
00791             return null;
00792         }
00793         ASN1OctetString str = ASN1OctetString.getInstance(new ASN1InputStream(
00794                     new ByteArrayInputStream(extvalue)).readObject());
00795         SubjectKeyIdentifier keyId = SubjectKeyIdentifier.getInstance(new ASN1InputStream(
00796                     new ByteArrayInputStream(str.getOctets())).readObject());
00797         return keyId.getKeyIdentifier();
00798     } // getSubjectKeyId
00799 
00808     public static String getCertificatePolicyId(X509Certificate cert, int pos)
00809         throws IOException {
00810         byte[] extvalue = cert.getExtensionValue(X509Extensions.CertificatePolicies.getId());
00811         if (extvalue == null) {
00812             return null;
00813         }
00814         DEROctetString oct = (DEROctetString) (new ASN1InputStream(new ByteArrayInputStream(
00815                     extvalue)).readObject());
00816         ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(
00817                     oct.getOctets())).readObject();
00818 
00819         // Check the size so we don't ArrayIndexOutOfBounds
00820         if (seq.size() < (pos + 1)) {
00821             return null;
00822         }
00823         PolicyInformation pol = new PolicyInformation((ASN1Sequence) seq.getObjectAt(
00824                     pos));
00825         String id = pol.getPolicyIdentifier().getId();
00826         return id;
00827     } // getCertificatePolicyId
00828 
00835     public static String getUPNAltName(X509Certificate cert)
00836         throws IOException, CertificateParsingException {
00837         Collection altNames = cert.getSubjectAlternativeNames();
00838         if (altNames != null) {
00839             Iterator i = altNames.iterator();
00840             while (i.hasNext()) {
00841                 List listitem = (List) i.next();
00842                 Integer no = (Integer) listitem.get(0);
00843                 if (no.intValue() == 0) {
00844                     byte[] altName = (byte[]) listitem.get(1);
00845                     DERObject oct = (DERObject) (new ASN1InputStream(new ByteArrayInputStream(
00846                                 altName)).readObject());
00847                     ASN1Sequence seq = ASN1Sequence.getInstance(oct);
00848                     ASN1TaggedObject obj = (ASN1TaggedObject) seq.getObjectAt(1);
00849                     DERUTF8String str = DERUTF8String.getInstance(obj.getObject());
00850                     return str.getString();
00851                 }
00852             }
00853         }
00854         return null;
00855     } // getUPNAltName
00856 
00860     public static URL getCrlDistributionPoint(X509Certificate certificate)
00861         throws CertificateParsingException {
00862         try {
00863             DERObject obj = getExtensionValue(certificate,
00864                     X509Extensions.CRLDistributionPoints.getId());
00865             if (obj == null) {
00866                 return null;
00867             }
00868             ASN1Sequence distributionPoints = (ASN1Sequence) obj;
00869             for (int i = 0; i < distributionPoints.size(); i++) {
00870                 ASN1Sequence distrPoint = (ASN1Sequence) distributionPoints.getObjectAt(i);
00871                 for (int j = 0; j < distrPoint.size(); j++) {
00872                     ASN1TaggedObject tagged = (ASN1TaggedObject) distrPoint.getObjectAt(j);
00873                     if (tagged.getTagNo() == 0) {
00874                         String url = getStringFromGeneralNames(tagged.getObject());
00875                         if (url != null) {
00876                             return new URL(url);
00877                         }
00878                     }
00879                 }
00880             }
00881         } catch (Exception e) {
00882             e.printStackTrace();
00883             throw new CertificateParsingException(e.toString());
00884         }
00885         return null;
00886     }
00887 
00891     private static DERObject getExtensionValue(X509Certificate cert, String oid)
00892         throws IOException {
00893         byte[] bytes = cert.getExtensionValue(oid);
00894         if (bytes == null) {
00895             return null;
00896         }
00897         ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(
00898                     bytes));
00899         ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
00900         aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));
00901         return aIn.readObject();
00902     } //getExtensionValue
00903 
00904     private static String getStringFromGeneralNames(DERObject names) {
00905         ASN1Sequence namesSequence = ASN1Sequence.getInstance((ASN1TaggedObject) names,
00906                 false);
00907         if (namesSequence.size() == 0) {
00908             return null;
00909         }
00910         DERTaggedObject taggedObject = (DERTaggedObject) namesSequence.getObjectAt(0);
00911         return new String(ASN1OctetString.getInstance(taggedObject, false)
00912                                          .getOctets());
00913     } //getStringFromGeneralNames
00914 
00922     public static String getCertFingerprintAsString(byte[] ba) {
00923         try {
00924             X509Certificate cert = getCertfromByteArray(ba);
00925             byte[] res = generateSHA1Fingerprint(cert.getEncoded());
00926 
00927             return Hex.encode(res).toString();
00928         } catch (CertificateEncodingException cee) {
00929             log.error("Error encoding X509 certificate.", cee);
00930         } catch (CertificateException cee) {
00931             log.error("Error decoding X509 certificate.", cee);
00932         } catch (IOException ioe) {
00933             log.error("Error reading byte array for X509 certificate.", ioe);
00934         }
00935 
00936         return null;
00937     }
00938 
00946     public static String getFingerprintAsString(X509Certificate cert) {
00947         try {
00948             byte[] res = generateSHA1Fingerprint(cert.getEncoded());
00949 
00950             return Hex.encode(res).toString();
00951         } catch (CertificateEncodingException cee) {
00952             log.error("Error encoding X509 certificate.", cee);
00953         }
00954 
00955         return null;
00956     }
00957 
00965     public static String getFingerprintAsString(X509CRL crl) {
00966         try {
00967             byte[] res = generateSHA1Fingerprint(crl.getEncoded());
00968 
00969             return Hex.encode(res).toString();
00970         } catch (CRLException ce) {
00971             log.error("Error encoding X509 CRL.", ce);
00972         }
00973 
00974         return null;
00975     }
00976 
00984     public static byte[] generateSHA1Fingerprint(byte[] ba) {
00985         try {
00986             MessageDigest md = MessageDigest.getInstance("SHA1");
00987 
00988             return md.digest(ba);
00989         } catch (NoSuchAlgorithmException nsae) {
00990             log.error("SHA1 algorithm not supported", nsae);
00991         }
00992 
00993         return null;
00994     } // generateSHA1Fingerprint
00995 
01003     public static byte[] generateMD5Fingerprint(byte[] ba) {
01004         try {
01005             MessageDigest md = MessageDigest.getInstance("MD5");
01006 
01007             return md.digest(ba);
01008         } catch (NoSuchAlgorithmException nsae) {
01009             log.error("MD5 algorithm not supported", nsae);
01010         }
01011 
01012         return null;
01013     } // generateMD5Fingerprint
01014 
01015     public static KeyPair keyPair(int size) {
01016         KeyPair kp = null;
01017 
01018         // o = ProActiveSecurity.generateGenericCertificate();
01019         try {
01020             //acCert = (X509Certificate) o[0];
01021             //acPrivateKey = (PrivateKey) o[1];
01022             kp = KeyTools.genKeys(size);
01023         } catch (NoSuchAlgorithmException e4) {
01024             e4.printStackTrace();
01025         } catch (NoSuchProviderException e4) {
01026             e4.printStackTrace();
01027         }
01028         return kp;
01029     }
01030 } // CertTools

Generated on Mon Jan 22 15:16:10 2007 for ProActive by  doxygen 1.5.1