00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030  
00031 package org.objectweb.proactive.ext.security;
00032 
00033 import java.io.*;
00034 import java.security.KeyFactory;
00035 import java.security.KeyPair;
00036 import java.security.KeyPairGenerator;
00037 import java.security.KeyStore;
00038 import java.security.KeyStoreException;
00039 import java.security.NoSuchAlgorithmException;
00040 import java.security.NoSuchProviderException;
00041 import java.security.PrivateKey;
00042 import java.security.PublicKey;
00043 import java.security.cert.*;
00044 import java.security.interfaces.*;
00045 import java.security.spec.*;
00046 import java.util.*;
00047 
00048 import org.apache.log4j.Logger;
00049 import org.bouncycastle.asn1.*;
00050 import org.bouncycastle.asn1.pkcs.*;
00051 import org.bouncycastle.asn1.x509.*;
00052 import org.bouncycastle.jce.interfaces.*;
00053 import org.objectweb.proactive.core.util.log.Loggers;
00054 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00055 
00056 
00061 public class KeyTools {
00062     static Logger log = ProActiveLogger.getLogger(Loggers.SECURITY);
00063 
00067     private KeyTools() {
00068     }
00069 
00077     public static KeyPair genKeys(int keysize)
00078         throws NoSuchAlgorithmException, NoSuchProviderException {
00079         log.debug(">genKeys()");
00080 
00081         KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA", "BC");
00082         keygen.initialize(keysize);
00083 
00084         KeyPair rsaKeys = keygen.generateKeyPair();
00085 
00086         log.debug("Generated " + rsaKeys.getPublic().getAlgorithm() +
00087             " keys with length " +
00088             ((RSAPrivateKey) rsaKeys.getPrivate()).getPrivateExponent()
00089              .bitLength());
00090 
00091         log.debug("<genKeys()");
00092 
00093         return rsaKeys;
00094     } 
00095 
00109     public static KeyStore createP12(String alias, PrivateKey privKey,
00110         X509Certificate cert, X509Certificate cacert) throws Exception {
00111         Certificate[] chain;
00112 
00113         if (cacert == null) {
00114             chain = null;
00115         } else {
00116             chain = new Certificate[1];
00117             chain[0] = cacert;
00118         }
00119 
00120         return createP12(alias, privKey, cert, chain);
00121     } 
00122 
00133     static public KeyStore createP12(String alias, PrivateKey privKey,
00134         X509Certificate cert, Collection<Certificate> cacerts) throws Exception {
00135         Certificate[] chain;
00136         if (cacerts == null) {
00137             chain = null;
00138         } else {
00139             chain = new Certificate[cacerts.size()];
00140             chain = (Certificate[]) cacerts.toArray(chain);
00141         }
00142         return createP12(alias, privKey, cert, chain);
00143     } 
00144 
00156     public static KeyStore createP12(String alias, PrivateKey privKey,
00157         X509Certificate cert, Certificate[] cachain) throws Exception {
00158         log.debug(">createP12: alias=" + alias + ", privKey, cert=" +
00159             CertTools.getSubjectDN(cert) + ", cachain.length=" +
00160             ((cachain == null) ? 0 : cachain.length));
00161 
00162         
00163         if (cert == null) {
00164             throw new IllegalArgumentException("Parameter cert cannot be null.");
00165         }
00166         int len = 1;
00167         if (cachain != null) {
00168             len += cachain.length;
00169         }
00170         Certificate[] chain = new Certificate[len];
00171 
00172         
00173         CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
00174         chain[0] = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00175                     cert.getEncoded()));
00176 
00177         if (cachain != null) {
00178             for (int i = 0; i < cachain.length; i++) {
00179                 X509Certificate tmpcert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00180                             cachain[i].getEncoded()));
00181                 chain[i + 1] = tmpcert;
00182             }
00183         }
00184         if (chain.length > 1) {
00185             for (int i = 1; i < chain.length; i++) {
00186                 X509Certificate cacert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
00187                             chain[i].getEncoded()));
00188 
00189                 
00190                 PKCS12BagAttributeCarrier caBagAttr = (PKCS12BagAttributeCarrier) chain[i];
00191 
00192                 
00193                 String cafriendly = CertTools.getPartFromDN(CertTools.getSubjectDN(
00194                             cacert), "CN");
00195 
00196                 
00197                 if (cafriendly == null) {
00198                     cafriendly = CertTools.getPartFromDN(CertTools.getSubjectDN(
00199                                 cacert), "O") + i;
00200                 }
00201                 if (cafriendly == null) {
00202                     cafriendly = CertTools.getPartFromDN(CertTools.getSubjectDN(
00203                                 cacert), "OU" + i);
00204                 }
00205                 if (cafriendly == null) {
00206                     cafriendly = "CA_unknown" + i;
00207                 }
00208                 caBagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
00209                     new DERBMPString(cafriendly));
00210             }
00211         }
00212 
00213         
00214         PKCS12BagAttributeCarrier certBagAttr = (PKCS12BagAttributeCarrier) chain[0];
00215         certBagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
00216             new DERBMPString(alias));
00217         
00218         certBagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
00219             createSubjectKeyId(chain[0].getPublicKey()));
00220         
00221         KeyFactory keyfact = KeyFactory.getInstance(privKey.getAlgorithm(), "BC");
00222         PrivateKey pk = keyfact.generatePrivate(new PKCS8EncodedKeySpec(
00223                     privKey.getEncoded()));
00224 
00225         
00226         PKCS12BagAttributeCarrier keyBagAttr = (PKCS12BagAttributeCarrier) pk;
00227 
00228         
00229         keyBagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
00230             new DERBMPString(alias));
00231         keyBagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
00232             createSubjectKeyId(chain[0].getPublicKey()));
00233         
00234         KeyStore store = KeyStore.getInstance("PKCS12", "BC");
00235         store.load(null, null);
00236         store.setKeyEntry(alias, pk, null, chain);
00237         log.debug("<createP12: alias=" + alias + ", privKey, cert=" +
00238             CertTools.getSubjectDN(cert) + ", cachain.length=" +
00239             ((cachain == null) ? 0 : cachain.length));
00240 
00241         return store;
00242     } 
00243 
00259     public static KeyStore createJKS(String alias, PrivateKey privKey,
00260         String password, X509Certificate cert, Certificate[] cachain)
00261         throws Exception {
00262         log.debug(">createJKS: alias=" + alias + ", privKey, cert=" +
00263             CertTools.getSubjectDN(cert) + ", cachain.length=" +
00264             ((cachain == null) ? 0 : cachain.length));
00265 
00266         String caAlias = "cacert";
00267 
00268         
00269         if (cert == null) {
00270             throw new IllegalArgumentException("Parameter cert cannot be null.");
00271         }
00272         int len = 1;
00273         if (cachain != null) {
00274             len += cachain.length;
00275         }
00276         Certificate[] chain = new Certificate[len];
00277         chain[0] = cert;
00278         if (cachain != null) {
00279             for (int i = 0; i < cachain.length; i++) {
00280                 chain[i + 1] = cachain[i];
00281             }
00282         }
00283 
00284         
00285         KeyStore store = KeyStore.getInstance("JKS");
00286         store.load(null, null);
00287 
00288         
00289         X509Certificate[] usercert = new X509Certificate[1];
00290         usercert[0] = cert;
00291         store.setKeyEntry(alias, privKey, password.toCharArray(), usercert);
00292 
00293         
00294         if (cachain != null) {
00295             if (!CertTools.isSelfSigned(
00296                         (X509Certificate) cachain[cachain.length - 1])) {
00297                 throw new IllegalArgumentException(
00298                     "Root cert is not self-signed.");
00299             }
00300             store.setCertificateEntry(caAlias, cachain[cachain.length - 1]);
00301         }
00302 
00303         
00304         log.debug("Storing cert chain of length " + chain.length);
00305         store.setKeyEntry(alias, privKey, password.toCharArray(), chain);
00306         log.debug("<createJKS: alias=" + alias + ", privKey, cert=" +
00307             CertTools.getSubjectDN(cert) + ", cachain.length=" +
00308             ((cachain == null) ? 0 : cachain.length));
00309 
00310         return store;
00311     } 
00312 
00321     public static Certificate[] getCertChain(KeyStore keyStore,
00322         String privateKeyAlias) throws KeyStoreException {
00323         System.out.println(">getCertChain: alias='" + privateKeyAlias + "'");
00324 
00325         Certificate[] certchain = keyStore.getCertificateChain(privateKeyAlias);
00326         System.out.println("Certchain retrieved from alias '" +
00327             privateKeyAlias + "' has length " + certchain.length);
00328 
00329         if (certchain.length < 1) {
00330             log.error("Cannot load certificate chain with alias '" +
00331                 privateKeyAlias + "' from keystore.");
00332             System.out.println("<getCertChain: alias='" + privateKeyAlias +
00333                 "', retlength=" + certchain.length);
00334 
00335             return certchain;
00336         } else if (certchain.length > 0) {
00337             if (CertTools.isSelfSigned(
00338                         (X509Certificate) certchain[certchain.length - 1])) {
00339                 System.out.println("Issuer='" +
00340                     CertTools.getIssuerDN(
00341                         (X509Certificate) certchain[certchain.length - 1]) +
00342                     "'.");
00343                 System.out.println("Subject='" +
00344                     CertTools.getSubjectDN(
00345                         (X509Certificate) certchain[certchain.length - 1]) +
00346                     "'.");
00347                 System.out.println("<getCertChain: alias='" + privateKeyAlias +
00348                     "', retlength=" + certchain.length);
00349 
00350                 return certchain;
00351             }
00352         }
00353 
00354         
00355         ArrayList<Certificate> array = new ArrayList<Certificate>();
00356 
00357         for (int i = 0; i < certchain.length; i++) {
00358             array.add(certchain[i]);
00359         }
00360 
00361         boolean stop = false;
00362 
00363         while (!stop) {
00364             X509Certificate cert = (X509Certificate) array.get(array.size() -
00365                     1);
00366             String ialias = CertTools.getPartFromDN(CertTools.getIssuerDN(cert),
00367                     "CN");
00368             Certificate[] chain1 = keyStore.getCertificateChain(ialias);
00369 
00370             if (chain1 == null) {
00371                 stop = true;
00372             } else {
00373                 System.out.println("Loaded certificate chain with length " +
00374                     chain1.length + " with alias '" + ialias + "'.");
00375 
00376                 if (chain1.length == 0) {
00377                     log.error("No RootCA certificate found!");
00378                     stop = true;
00379                 }
00380 
00381                 for (int j = 0; j < chain1.length; j++) {
00382                     array.add(chain1[j]);
00383 
00384                     
00385                     if (CertTools.isSelfSigned((X509Certificate) chain1[j])) {
00386                         stop = true;
00387                     }
00388                 }
00389             }
00390         }
00391 
00392         Certificate[] ret = new Certificate[array.size()];
00393 
00394         for (int i = 0; i < ret.length; i++) {
00395             ret[i] = (X509Certificate) array.get(i);
00396             System.out.println("Issuer='" +
00397                 CertTools.getIssuerDN((X509Certificate) ret[i]) + "'.");
00398             System.out.println("Subject='" +
00399                 CertTools.getSubjectDN((X509Certificate) ret[i]) + "'.");
00400         }
00401 
00402         System.out.println("<getCertChain: alias='" + privateKeyAlias +
00403             "', retlength=" + ret.length);
00404 
00405         return ret;
00406     } 
00407 
00415     public static SubjectKeyIdentifier createSubjectKeyId(PublicKey pubKey) {
00416         try {
00417             ByteArrayInputStream bIn = new ByteArrayInputStream(pubKey.getEncoded());
00418             SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(
00419                         bIn).readObject());
00420 
00421             return new SubjectKeyIdentifier(info);
00422         } catch (Exception e) {
00423             throw new RuntimeException("error creating key");
00424         }
00425     } 
00426 }