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 }