1 package org.eparapher.core.crypto.cert;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.File;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.io.UnsupportedEncodingException;
9 import java.math.BigInteger;
10 import java.security.GeneralSecurityException;
11 import java.security.InvalidAlgorithmParameterException;
12 import java.security.InvalidKeyException;
13 import java.security.KeyPair;
14 import java.security.KeyPairGenerator;
15 import java.security.KeyStore;
16 import java.security.KeyStoreException;
17 import java.security.NoSuchAlgorithmException;
18 import java.security.NoSuchProviderException;
19 import java.security.Principal;
20 import java.security.PrivateKey;
21 import java.security.PublicKey;
22 import java.security.SecureRandom;
23 import java.security.Signature;
24 import java.security.SignatureException;
25 import java.security.cert.CertPath;
26 import java.security.cert.CertPathBuilder;
27 import java.security.cert.CertPathBuilderException;
28 import java.security.cert.CertPathValidator;
29 import java.security.cert.CertPathValidatorException;
30 import java.security.cert.CertPathValidatorResult;
31 import java.security.cert.CertSelector;
32 import java.security.cert.CertStore;
33 import java.security.cert.Certificate;
34 import java.security.cert.CertificateEncodingException;
35 import java.security.cert.CertificateException;
36 import java.security.cert.CertificateFactory;
37 import java.security.cert.CertificateParsingException;
38 import java.security.cert.CollectionCertStoreParameters;
39 import java.security.cert.PKIXBuilderParameters;
40 import java.security.cert.PKIXCertPathValidatorResult;
41 import java.security.cert.PKIXParameters;
42 import java.security.cert.X509CRL;
43 import java.security.cert.X509CertSelector;
44 import java.security.cert.X509Certificate;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Date;
50 import java.util.Enumeration;
51 import java.util.HashMap;
52 import java.util.Hashtable;
53 import java.util.LinkedList;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Vector;
57 import java.util.regex.Matcher;
58 import java.util.regex.Pattern;
59
60 import org.apache.log4j.Level;
61 import org.apache.log4j.Logger;
62 import org.bouncycastle.asn1.ASN1Encodable;
63 import org.bouncycastle.asn1.ASN1InputStream;
64 import org.bouncycastle.asn1.ASN1Sequence;
65 import org.bouncycastle.asn1.DEREncodable;
66 import org.bouncycastle.asn1.DERObjectIdentifier;
67 import org.bouncycastle.asn1.DEROutputStream;
68 import org.bouncycastle.asn1.DERSequence;
69 import org.bouncycastle.asn1.DERTaggedObject;
70 import org.bouncycastle.asn1.DERUTF8String;
71 import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
72 import org.bouncycastle.asn1.x509.DistributionPoint;
73 import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
74 import org.bouncycastle.asn1.x509.GeneralName;
75 import org.bouncycastle.asn1.x509.GeneralNames;
76 import org.bouncycastle.asn1.x509.KeyPurposeId;
77 import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
78 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
79 import org.bouncycastle.asn1.x509.X509Extensions;
80 import org.bouncycastle.asn1.x509.X509Name;
81 import org.bouncycastle.cms.CMSSignedGenerator;
82 import org.bouncycastle.jce.ECNamedCurveTable;
83 import org.bouncycastle.jce.PKCS10CertificationRequest;
84 import org.bouncycastle.jce.X509KeyUsage;
85 import org.bouncycastle.jce.spec.ECParameterSpec;
86 import org.bouncycastle.openssl.PEMWriter;
87 import org.bouncycastle.x509.X509V3CertificateGenerator;
88 import org.eparapher.core.EParapherManager;
89 import org.eparapher.core.crypto.EPCryptoProviderManager;
90 import org.eparapher.core.crypto.EPKeystoreManager;
91 import org.eparapher.core.tools.JVMSettings;
92
93 public class CertificateManager {
94
95 private static Logger log = Logger.getLogger(CertificateManager.class);
96
97 private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)");
98
99
100
101
102
103
104
105
106
107
108
109 public static List<String> getPeerIdentities(X509Certificate x509Certificate) {
110
111 List<String> names = getSubjectAlternativeNames(x509Certificate);
112 if (names.isEmpty()) {
113 String name = x509Certificate.getSubjectDN().getName();
114 Matcher matcher = cnPattern.matcher(name);
115 if (matcher.find()) {
116 name = matcher.group(2);
117 }
118
119 names = new ArrayList<String>();
120 names.add(name);
121 }
122 return names;
123 }
124
125
126
127
128
129
130
131
132
133 private static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
134 List<String> identities = new ArrayList<String>();
135 try {
136 Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
137
138 if (altNames == null) {
139 return Collections.emptyList();
140 }
141
142 for (List<?> item : altNames) {
143 Integer type = (Integer) item.get(0);
144 if (type == 0) {
145
146 try {
147
148 ASN1InputStream decoder = new ASN1InputStream((byte[]) item.toArray()[1]);
149 DEREncodable encoded = decoder.readObject();
150 encoded = ((DERSequence) encoded).getObjectAt(1);
151 encoded = ((DERTaggedObject) encoded).getObject();
152 encoded = ((DERTaggedObject) encoded).getObject();
153 String identity = ((DERUTF8String) encoded).getString();
154
155 identities.add(identity);
156 }
157 catch (UnsupportedEncodingException e) {
158 log.error("Error decoding subjectAltName",e);
159 }
160 catch (IOException e) {
161 log.error("Error decoding subjectAltName",e);
162 }
163 catch (Exception e) {
164 log.error("Error decoding subjectAltName",e);
165 }
166 }
167
168 log.info("SubjectAltName of invalid type found: " + certificate);
169 }
170 }
171 catch (CertificateParsingException e) {
172 log.error("Error parsing SubjectAltName in certificate: ",e);
173 }
174 return identities;
175 }
176 public static boolean isValidKeyUsageForEncryption(X509Certificate cert) {
177 boolean[] keyUsage = cert.getKeyUsage();
178 return keyUsage[CertificateInfo.KEYENCIPHERMENT];
179 }
180
181 public static boolean isValidKeyUsageForNonRepudiation(X509Certificate cert) {
182 boolean[] keyUsage = cert.getKeyUsage();
183 return keyUsage[CertificateInfo.NONREPUDIATION];
184 }
185
186 public static boolean isValidKeyUsageForSignature(X509Certificate cert) {
187 boolean[] keyUsage = cert.getKeyUsage();
188 return keyUsage[CertificateInfo.DIGITALSIGNATURE];
189 }
190
191
192
193
194
195
196
197
198 public static boolean isRSACertificate(KeyStore ksKeys, String domain) throws KeyStoreException {
199 return isCertificate(ksKeys, domain, "RSA");
200 }
201
202
203
204
205
206
207
208
209
210 public static boolean isDSACertificate(KeyStore ksKeys, String domain) throws KeyStoreException {
211 return isCertificate(ksKeys, domain, "DSA");
212 }
213
214
215
216
217
218
219
220
221
222
223 public static boolean isDSACertificate(X509Certificate certificate) throws KeyStoreException {
224 return certificate.getPublicKey().getAlgorithm().equals("DSA");
225 }
226
227
228
229
230
231
232
233
234
235 public static boolean isECCertificate(X509Certificate certificate) throws KeyStoreException {
236 return (certificate.getPublicKey().getAlgorithm().equals("EC") ||
237 certificate.getPublicKey().getAlgorithm().equals("GOST")) ;
238 }
239
240
241
242
243
244
245
246
247
248
249 private static boolean isCertificate(KeyStore ksKeys, String domain, String algorithm) throws KeyStoreException {
250 for (Enumeration<String> aliases = ksKeys.aliases(); aliases.hasMoreElements();) {
251 X509Certificate certificate = (X509Certificate) ksKeys.getCertificate(aliases.nextElement());
252 for (String identity : getPeerIdentities(certificate)) {
253 if (identity.endsWith(domain) && certificate.getPublicKey().getAlgorithm().equals(algorithm)) {
254 return true;
255 }
256 }
257 }
258 return false;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 public static String createSigningRequest(X509Certificate cert, PrivateKey privKey) throws Exception {
275 StringBuilder sb = new StringBuilder();
276
277 String subject = cert.getSubjectDN().getName();
278 X509Name xname = new X509Name(subject);
279
280 PublicKey pubKey = cert.getPublicKey();
281
282 String signatureAlgorithm = cert.getSigAlgName();
283
284 PKCS10CertificationRequest csr =
285 new PKCS10CertificationRequest(signatureAlgorithm, xname, pubKey, null, privKey);
286
287 ByteArrayOutputStream baos = new ByteArrayOutputStream();
288 DEROutputStream deros = new DEROutputStream(baos);
289 deros.writeObject(csr.getDERObject());
290 String sTmp = new String(org.bouncycastle.util.encoders.Base64.encode(baos.toByteArray()));
291
292
293 sb.append(X509Util.BEGIN_CERT_REQ + "\n");
294
295
296 for (int iCnt = 0; iCnt < sTmp.length(); iCnt += X509Util.CERT_REQ_LINE_LENGTH) {
297 int iLineLength;
298
299 if ((iCnt + X509Util.CERT_REQ_LINE_LENGTH) > sTmp.length()) {
300 iLineLength = sTmp.length() - iCnt;
301 } else {
302 iLineLength = X509Util.CERT_REQ_LINE_LENGTH;
303 }
304
305 sb.append(sTmp.substring(iCnt, iCnt + iLineLength)).append("\n");
306 }
307
308
309 sb.append(X509Util.END_CERT_REQ + "\n");
310 return sb.toString();
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325 public static String createSigningRequest( NewCertParams params, KeyPair keypair ) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, IOException {
326
327
328 PrivateKey privateKey = keypair.getPrivate();
329 PublicKey publicKey = keypair.getPublic();
330 X509Name subject = new X509Name(params.getSubjectDN());
331
332
333
334
335 PKCS10CertificationRequest certificateRequest = new PKCS10CertificationRequest( params.getCertSigAlg(), subject, publicKey, null, privateKey);
336
337
338 String csrFile = JVMSettings.getEParapherCSRDirectory() + File.separator + params.getAlias() + ".pem";
339
340 PEMWriter pem = new PEMWriter(new FileWriter( csrFile ));
341 pem.writeObject(certificateRequest);
342 pem.close();
343
344 return csrFile;
345 }
346
347 public static X509Certificate[] generateNewCertificate( NewCertParams params, KeyPair keypair ) throws CertificateEncodingException, InvalidKeyException, IllegalStateException, NoSuchAlgorithmException, SignatureException, IOException, NoSuchProviderException {
348
349 PrivateKey privateKey = keypair.getPrivate();
350 PublicKey publicKey = keypair.getPublic();
351
352 X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
353
354 X509Name subject = new X509Name(params.getSubjectDN());
355
356
357 if (params.isSelfCertSigned() || params.isCSR())
358 certGen.setIssuerDN(subject);
359
360
361 certGen.setSubjectDN(subject);
362 certGen.setPublicKey(publicKey);
363 certGen.setSignatureAlgorithm(params.getCertSigAlg());
364 certGen.setNotBefore(params.getValidFrom());
365 certGen.setNotAfter(params.getValidUntil());
366
367
368 certGen.setSerialNumber(generateRandomSerial());
369
370
371 int keyusage = X509KeyUsage.digitalSignature + X509KeyUsage.nonRepudiation;
372 X509KeyUsage ku = new X509KeyUsage(keyusage);
373 certGen.addExtension(X509Extensions.KeyUsage.getId(), false, ku);
374
375
376 Vector<KeyPurposeId> extkeyusage = new Vector<KeyPurposeId>();
377 extkeyusage.add(KeyPurposeId.anyExtendedKeyUsage);
378
379
380
381 ExtendedKeyUsage extendedKeyUsage = new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth);
382 certGen.addExtension(X509Extensions.ExtendedKeyUsage, false, extendedKeyUsage);
383
384
385 if (!params.getSubaltnameEMail().equals("")
386 || !params.getSubaltnameDNSName().equals("")
387 || !params.getSubaltnameOtherName().equals("")) {
388 GeneralNames subjectAltName = null;
389 ASN1Encodable[] asn1san;
390 GeneralName email=null,othername=null,dnsname=null;
391 int nbsubaltname = 0;
392
393 if (!params.getSubaltnameEMail().equals("")) {
394 email = new GeneralName(GeneralName.rfc822Name, params.getSubaltnameEMail());
395 nbsubaltname++;
396 }
397 if (!params.getSubaltnameDNSName().equals("")) {
398 dnsname = new GeneralName(GeneralName.dNSName, params.getSubaltnameDNSName());
399 nbsubaltname++;
400 }
401 if (!params.getSubaltnameOtherName().equals("")) {
402 ASN1Encodable[] othernameasn1 = new ASN1Encodable[]{ new DERObjectIdentifier("1.3.6.1.5.5.7.8.5"),
403 new DERTaggedObject(true, 0, new DERUTF8String(params.getSubaltnameOtherName())) };
404 DERSequence othernameSequence = new DERSequence( othernameasn1 );
405 othername = new GeneralName(GeneralName.otherName, othernameSequence);
406 nbsubaltname++;
407 }
408
409 asn1san= new ASN1Encodable[nbsubaltname];
410 nbsubaltname = 0;
411 if (email!=null)
412 asn1san[nbsubaltname++] = email;
413 if (dnsname!=null)
414 asn1san[nbsubaltname++] = dnsname;
415 if (othername!=null)
416 asn1san[nbsubaltname++] = othername;
417
418 subjectAltName = new GeneralNames( new DERSequence(asn1san));
419 certGen.addExtension(X509Extensions.SubjectAlternativeName, false, subjectAltName);
420 }
421
422
423
424 SubjectKeyIdentifier ski;
425 AuthorityKeyIdentifier aki;
426
427 ASN1Sequence spki_asn1 = (ASN1Sequence) new ASN1InputStream( new ByteArrayInputStream(publicKey.getEncoded())).readObject();
428 SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo( spki_asn1);
429 ski = new SubjectKeyIdentifier(spki);
430 ASN1Sequence ac_spki_asn1 = (ASN1Sequence) new ASN1InputStream(new ByteArrayInputStream(publicKey.getEncoded())).readObject();
431 SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo(ac_spki_asn1);
432 aki = new AuthorityKeyIdentifier(apki);
433
434 certGen.addExtension(X509Extensions.SubjectKeyIdentifier.getId(), false, ski);
435 certGen.addExtension(X509Extensions.AuthorityKeyIdentifier.getId(), false, aki);
436
437
438 X509Certificate[] userCertChain = new X509Certificate[1];
439 PrivateKey certsigningpk = privateKey;
440 String currentalias = EPKeystoreManager.getInstance().getUserkeystore().getDefaultAlias();
441
442
443 if (!params.isSelfCertSigned() && !params.isCSR()) {
444 EPKeystoreManager.getInstance().getUserkeystore().setDefaultAlias(params.getIssueralias());
445 if (!EPKeystoreManager.getInstance().getUserkeystore().loadPrivateKey()) {
446 log.error("Need private key access to generate new certificate from " + params.getIssueralias());
447 return null;
448 }
449 certsigningpk = EPKeystoreManager.getInstance().getUserkeystore().getPrivateKey();
450
451 X509Certificate[] issuerCertChain = EPKeystoreManager.getInstance().getUserkeystore().getX509CertificateChain();
452 userCertChain = new X509Certificate[issuerCertChain.length+1];
453 }
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 userCertChain[userCertChain.length-1] = certGen.generate(certsigningpk, "BC");
473
474 if (!params.isSelfCertSigned()) {
475 EPKeystoreManager.getInstance().getUserkeystore().setDefaultAlias(currentalias);
476 }
477
478 return userCertChain;
479 }
480
481 public static boolean validateCertChain( X509Certificate[] certificate, boolean trustCACerts) throws Exception {
482 try {
483
484 List certList = Arrays.asList(certificate);
485 CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
486 CertPath path = factory.generateCertPath(certList);
487
488
489
490 PKIXParameters param = new PKIXParameters(EPKeystoreManager.getInstance().getTrustStore().getKeystore());
491
492
493
494 param.setRevocationEnabled(false);
495
496
497 CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX", "BC");
498 CertPathValidatorResult cpvResult = certPathValidator.validate(path, param);
499
500 return true;
501 } catch (NoSuchAlgorithmException ex) {
502 log.error("error while validating a Certificate Chain",ex);
503
504 } catch (CertificateException ex) {
505 log.error("error while validating a Certificate Chain",ex);
506
507 } catch (InvalidAlgorithmParameterException ex) {
508 log.error("error while validating a Certificate Chain",ex);
509
510 } catch (KeyStoreException ex) {
511 log.error("error while validating a Certificate Chain",ex);
512
513 } catch (CertPathValidatorException ex) {
514 log.error("error while validating a Certificate Chain",ex);
515
516 }
517 return false;
518 }
519 public static List<X509Certificate> establishCertChain( X509Certificate certificate, boolean trustCACerts)
520 throws Exception {
521
522 KeyStore keyStore = EPKeystoreManager.getInstance().getUserkeystore().getKeystore();
523 KeyStore trustStore = EPKeystoreManager.getInstance().getTrustStore().getKeystore();
524
525 Map<Principal, List<X509Certificate>> knownCerts = new Hashtable<Principal, List<X509Certificate>>();
526 if ( keyStore!=null && keyStore.size() > 0) {
527 knownCerts.putAll(getCertsByIssuer(keyStore));
528 }
529
530 if (trustCACerts && trustStore.size() > 0) {
531 knownCerts.putAll(getCertsByIssuer(trustStore));
532 }
533
534 LinkedList<X509Certificate> answer = new LinkedList<X509Certificate>();
535 if (buildChain(certificate, answer, knownCerts)) {
536 return answer;
537 } else {
538 throw new Exception("Failed to establish chain from reply");
539 }
540 }
541
542
543
544
545
546
547
548
549
550
551
552
553 private static boolean buildChain(X509Certificate certificate, LinkedList<X509Certificate> answer,
554 Map<Principal, List<X509Certificate>> knownCerts) {
555 Principal subject = certificate.getSubjectDN();
556 Principal issuer = certificate.getIssuerDN();
557
558
559 if (subject.equals(issuer)) {
560 answer.addFirst(certificate);
561 return true;
562 }
563
564 List<X509Certificate> issuerCerts = knownCerts.get(issuer);
565 if (issuerCerts == null || issuerCerts.isEmpty()) {
566
567 return false;
568 }
569 for (X509Certificate issuerCert : issuerCerts) {
570 PublicKey publickey = issuerCert.getPublicKey();
571 try {
572
573 certificate.verify(publickey);
574
575 if (!buildChain(issuerCert, answer, knownCerts)) {
576 return false;
577 }
578 }
579 catch (Exception exception) {
580
581 return false;
582 }
583 }
584 answer.addFirst(certificate);
585 return true;
586 }
587
588
589
590
591
592
593
594
595 private static Map<Principal, List<X509Certificate>> getCertsByIssuer(KeyStore ks)
596 throws Exception {
597 Map<Principal, List<X509Certificate>> answer = new HashMap<Principal, List<X509Certificate>>();
598 Enumeration<String> aliases = ks.aliases();
599 while (aliases.hasMoreElements()) {
600 String alias = aliases.nextElement();
601 X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
602 cert = X509Util.getBCCertificate(cert);
603 if (cert != null) {
604 Principal subjectDN = cert.getSubjectDN();
605 List<X509Certificate> vec = answer.get(subjectDN);
606 if (vec == null) {
607 vec = new ArrayList<X509Certificate>();
608 vec.add(cert);
609 }
610 else {
611 if (!vec.contains(cert)) {
612 vec.add(cert);
613 }
614 }
615 answer.put(subjectDN, vec);
616 }
617 }
618 return answer;
619 }
620
621
622
623
624
625
626
627
628
629
630 private static List<X509Certificate> validateReply(KeyStore keyStore, KeyStore trustStore, String alias,
631 X509Certificate userCert, List<X509Certificate> replyCerts,
632 boolean trustCACerts, boolean verifyRoot)
633 throws Exception {
634
635 int i;
636 PublicKey userPubKey = userCert.getPublicKey();
637 for (i = 0; i < replyCerts.size(); i++) {
638 if (userPubKey.equals(replyCerts.get(i).getPublicKey())) {
639 break;
640 }
641 }
642 if (i == replyCerts.size()) {
643 throw new Exception(
644 "Certificate reply does not contain public key for <alias>: " + alias);
645 }
646
647 X509Certificate tmpCert = replyCerts.get(0);
648 replyCerts.set(0, replyCerts.get(i));
649 replyCerts.set(i, tmpCert);
650 Principal issuer = replyCerts.get(0).getIssuerDN();
651
652 for (i = 1; i < replyCerts.size() - 1; i++) {
653
654
655 int j;
656 for (j = i; j < replyCerts.size(); j++) {
657 Principal subject = replyCerts.get(j).getSubjectDN();
658 if (subject.equals(issuer)) {
659 tmpCert = replyCerts.get(i);
660 replyCerts.set(i, replyCerts.get(j));
661 replyCerts.set(j, tmpCert);
662 issuer = replyCerts.get(i).getIssuerDN();
663 break;
664 }
665 }
666 if (j == replyCerts.size()) {
667 throw new Exception("Incomplete certificate chain in reply");
668 }
669 }
670
671
672 for (i = 0; i < replyCerts.size() - 1; i++) {
673 PublicKey pubKey = replyCerts.get(i + 1).getPublicKey();
674 try {
675 replyCerts.get(i).verify(pubKey);
676 }
677 catch (Exception e) {
678 throw new Exception(
679 "Certificate chain in reply does not verify: " + e.getMessage());
680 }
681 }
682
683 if (!verifyRoot) {
684 return replyCerts;
685 }
686
687
688 X509Certificate topCert = replyCerts.get(replyCerts.size() - 1);
689 boolean foundInKeyStore = keyStore.getCertificateAlias(topCert) != null;
690 boolean foundInCAStore = trustCACerts && (trustStore.getCertificateAlias(topCert) != null);
691 if (!foundInKeyStore && !foundInCAStore) {
692 boolean verified = false;
693 X509Certificate rootCert = null;
694 if (trustCACerts) {
695 for (Enumeration<String> aliases = trustStore.aliases(); aliases.hasMoreElements();) {
696 String name = aliases.nextElement();
697 rootCert = (X509Certificate) trustStore.getCertificate(name);
698 if (rootCert != null) {
699 try {
700 topCert.verify(rootCert.getPublicKey());
701 verified = true;
702 break;
703 }
704 catch (Exception e) {
705
706 }
707 }
708 }
709 }
710 if (!verified) {
711 return null;
712 }
713 else {
714
715 if (!topCert.getSubjectDN().equals(topCert.getIssuerDN())) {
716
717 replyCerts.add(rootCert);
718 }
719 }
720 }
721
722 return replyCerts;
723 }
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738 public static synchronized X509Certificate createX509V3Certificate(KeyPair kp, int months, String issuerDN,
739 String subjectDN, String domain,
740 String signAlgoritm)
741 throws GeneralSecurityException, IOException {
742 PublicKey pubKey = kp.getPublic();
743 PrivateKey privKey = kp.getPrivate();
744
745 byte[] serno = new byte[8];
746 SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
747 random.setSeed((new Date().getTime()));
748 random.nextBytes(serno);
749 BigInteger serial = (new java.math.BigInteger(serno)).abs();
750
751 X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
752 certGenerator.reset();
753
754 certGenerator.setSerialNumber(serial);
755 certGenerator.setIssuerDN(new X509Name(issuerDN));
756 certGenerator.setNotBefore(new Date(System.currentTimeMillis()));
757 certGenerator.setNotAfter(
758 new Date(System.currentTimeMillis() + months * (1000L * 60 * 60 * 24 * 30)));
759 certGenerator.setSubjectDN(new X509Name(subjectDN));
760 certGenerator.setPublicKey(pubKey);
761 certGenerator.setSignatureAlgorithm(signAlgoritm);
762
763
764 boolean critical = subjectDN == null || "".equals(subjectDN.trim());
765 DERSequence othernameSequence = new DERSequence(new ASN1Encodable[]{
766 new DERObjectIdentifier("1.3.6.1.5.5.7.8.5"), new DERTaggedObject(true, 0, new DERUTF8String(domain))});
767 GeneralName othernameGN = new GeneralName(GeneralName.otherName, othernameSequence);
768 GeneralNames subjectAltNames = new GeneralNames(new DERSequence(new ASN1Encodable[]{othernameGN}));
769
770 certGenerator.addExtension(X509Extensions.SubjectAlternativeName, critical, subjectAltNames);
771
772 X509Certificate cert =
773 certGenerator.generateX509Certificate(privKey, "BC", new SecureRandom());
774 cert.checkValidity(new Date());
775 cert.verify(pubKey);
776
777 return cert;
778 }
779
780 public static X509CRL getCRLFromCertCDP(X509Certificate certificate)
781 throws CertificateParsingException {
782 DistributionPoint[] dps = X509Util.getCrlDistributionPoint(certificate);
783 X509CRL latestCRL = null;
784 for (int i = 0; i < dps.length; i++) {
785 DistributionPoint dp = dps[i];
786 X509CRL crl = null;
787 crl = X509Util.loadCRLFromDP(dp);
788 if (latestCRL==null) {
789 latestCRL = crl;
790 } else if (crl !=null) {
791 if (latestCRL.getNextUpdate().before(crl.getNextUpdate()))
792 latestCRL = crl;
793 }
794 }
795 return latestCRL;
796 }
797
798 public static KeyPair generateKeyPair(NewCertParams params) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
799 if (params.getKeypairAlg().equals("ECDSA"))
800 return CertificateManager.generateECKeyPair( params.getEcDSASpecName() );
801 else
802 return CertificateManager.generateKeyPair( params.getKeypairAlg(), params.getKeypairSize() );
803 }
804
805
806
807
808
809
810
811
812
813
814
815 public static KeyPair generateKeyPair(String algorithm, int keysize, String provider) throws NoSuchAlgorithmException, NoSuchProviderException {
816 KeyPairGenerator generator;
817 if (provider == null) {
818 generator = KeyPairGenerator.getInstance(algorithm);
819 } else {
820 generator = KeyPairGenerator.getInstance(algorithm, provider);
821 }
822 generator.initialize(keysize, new SecureRandom());
823 return generator.generateKeyPair();
824 }
825
826 public static KeyPair generateKeyPair(String algorithm, int keysize) throws NoSuchAlgorithmException, NoSuchProviderException {
827
828
829 String prov=null;
830 if ( EPKeystoreManager.isPKCS11Used() )
831 prov = EPCryptoProviderManager.getDefaultProviderName();
832 else prov = EPCryptoProviderManager.getDefaultProviderName();
833
834 return generateKeyPair( algorithm, keysize, prov );
835 }
836 public static KeyPair generateECKeyPair(String ecspecs) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
837
838 ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(ecspecs);
839
840 KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "BC");
841
842 generator.initialize(ecSpec, new SecureRandom());
843
844 return generator.generateKeyPair();
845 }
846
847
848
849
850
851
852 private static BigInteger generateRandomSerial() throws NoSuchAlgorithmException {
853 byte[] serno = new byte[8];
854 SecureRandom random;
855 try {
856 if (JVMSettings.isJava16Min() && JVMSettings.isWindowsOS())
857 random = SecureRandom.getInstance("Windows-PRNG");
858 else
859 random = SecureRandom.getInstance("SHA1PRNG");
860 } catch (NoSuchAlgorithmException e) {
861 String msg = "Error while generating a random serial number : " + e.getMessage();
862 EParapherManager.getInstance().getUI().errorMessage(msg,e);
863 log.error(msg, e);
864 return null;
865 }
866 random.setSeed( System.currentTimeMillis() );
867 random.nextBytes(serno);
868 return new BigInteger(serno).abs();
869 }
870
871
872
873
874
875
876
877 public static boolean verify(X509Certificate certificate, Collection<X509Certificate[]> caCertPath)
878 throws Exception {
879 try {
880
881 ArrayList<X509Certificate> certlist = new ArrayList<X509Certificate>();
882 certlist.add(certificate);
883
884
885 CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
886 java.security.cert.CertPath cp = cf.generateCertPath(certlist);
887
888
889
890 X509Certificate[] cac = (X509Certificate[]) caCertPath.toArray(new X509Certificate[] {});
891 java.security.cert.TrustAnchor anchor = new java.security.cert.TrustAnchor(cac[0], null);
892
893 java.security.cert.PKIXParameters params = new java.security.cert.PKIXParameters(java.util.Collections.singleton(anchor));
894 params.setRevocationEnabled(true);
895 params.setDate( new Date() );
896
897 CertPathValidator cpv = CertPathValidator.getInstance("PKIX", "BC");
898 PKIXCertPathValidatorResult result = (PKIXCertPathValidatorResult) cpv.validate(cp, params);
899 log.info("Certificate verify result: " + result.toString());
900 } catch (java.security.cert.CertPathValidatorException cpve) {
901 throw new Exception("Invalid certificate or certificate not issued by specified CA: " + cpve.getMessage());
902 } catch (Exception e) {
903 throw new Exception("Error checking certificate chain: " + e.getMessage());
904 }
905 return true;
906 }
907
908 public static X509Certificate[] buildChain(X509Certificate[] certs) {
909 try {
910 if (Logger.getRootLogger().getLevel().toInt()<=Level.DEBUG_INT)
911 System.setProperty("java.security.debug","certpath");
912 CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX","BC");
913 X509CertSelector targetConstraints = new X509CertSelector();
914
915 KeyStore trustedKS = EPKeystoreManager.getInstance().getTrustStore().getKeystore();
916 if (trustedKS == null) {
917 log.warn("trusted KeyStore is null");
918 return null;
919 }
920
921 PKIXBuilderParameters params = new PKIXBuilderParameters( trustedKS, targetConstraints);
922
923
924 ArrayList<X509Certificate> certsList = new ArrayList<X509Certificate>();
925 for (int i=0; i < certs.length; i++) {
926 certsList.add(certs[i]);
927 }
928 CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(certsList);
929 CertStore store = CertStore.getInstance("Collection", ccsp);
930 params.addCertStore(store);
931 params.setRevocationEnabled(false);
932
933 CertPath certPath = certPathBuilder.build(params).getCertPath();
934 log.info("Cert Path building OK : " + certPath);
935 List<Certificate> trustedChain = (List<Certificate>) certPath.getCertificates();
936
937 Certificate[] cerchain = (Certificate[]) trustedChain.toArray(new Certificate[] {} );
938
939 System.setProperty("java.security.debug","false");
940 return X509Util.convertCertChaintoX509( cerchain );
941 } catch (NoSuchAlgorithmException e) {
942 log.error(e.getLocalizedMessage(),e);
943 } catch (KeyStoreException e) {
944 log.error(e.getLocalizedMessage(),e);
945 } catch (CertPathBuilderException e) {
946
947 log.debug(e.getLocalizedMessage(),e);
948
949 log.warn(e.getLocalizedMessage());
950 } catch (InvalidAlgorithmParameterException e) {
951 log.error(e.getLocalizedMessage(),e);
952 } catch (NoSuchProviderException e) {
953 log.error(e.getLocalizedMessage(),e);
954 }
955 System.setProperty("java.security.debug","false");
956 return null;
957 }
958 }