1
10package org.jstk.cert;
11
12import java.util.*;
13import java.security.Signature;
14import java.security.KeyPair;
15import java.security.PrivateKey;
16import java.security.PublicKey;
17import java.security.cert.Certificate;
18import java.security.cert.CertificateFactory;
19import java.security.cert.X509Certificate;
20import java.io.ByteArrayInputStream;
21import java.io.InputStream;
22
23import org.jstk.JSTKException;
24import org.jstk.pki.CSR;
25import org.jstk.pki.TBSCertificate;
26import org.jstk.pki.AlgorithmIdentifier;
27import org.jstk.pki.Name;
28import org.jstk.pki.Validity;
29import org.jstk.pki.SubjectPublicKeyInfo;
30import org.jstk.asn1.*;
31import java.math.BigInteger;
32import javax.security.auth.x500.X500Principal;
33
34public class CertificateGenerator {
35 public final static int DEFAULT_VALIDITY_PERIOD = 365; public final static String DEFAULT_SIGNATURE_ALGORITHM = "dsaWithSHA1";
37
38 private X509Certificate issuerCert = null;
39 private PrivateKey issuerKey = null;
40 private boolean caFlag = false;
41 private int pathLen = 0;
42 private String sigAlg = DEFAULT_SIGNATURE_ALGORITHM;
43 private KeyUsage keyUsage = null;
44 private List extendedKeyUsage = null;
45
46 public CertificateGenerator(){
47 }
48
49 public CertificateGenerator(X509Certificate issuerCert, PrivateKey issuerKey){
50 this.issuerCert = issuerCert;
51 this.issuerKey = issuerKey;
52 }
53
54 public X509Certificate generateCertificate(String csrFile, BigInteger serialNo) throws JSTKException {
55 return generateCertificate(csrFile, serialNo, DEFAULT_VALIDITY_PERIOD);
56 }
57
58 public void setBasicConstraints(boolean caFlag, int pathLen){
59 this.caFlag = caFlag;
60 this.pathLen = pathLen;
61 }
62
63 public void setSigAlg(String sigAlg){
64 this.sigAlg = sigAlg;
65 }
66
67 public void setKeyUsage(KeyUsage keyUsage){
68 this.keyUsage = keyUsage;
69 }
70
71 public void setExtendedKeyUsage(List extendedKeyUsage){
72 this.extendedKeyUsage = extendedKeyUsage;
73 }
74
75 public X509Certificate generateCertificate(String csrFile, BigInteger serialNo,
76 int noDays) throws JSTKException {
77 Calendar cal = Calendar.getInstance();
78 Date notBefore = cal.getTime();
79 cal.add(Calendar.DATE, noDays);
80 Date notAfter = cal.getTime();
81 return generateCertificate(csrFile, serialNo, notBefore,
82 notAfter, sigAlg);
83 }
84
85 public X509Certificate generateCertificate(String csrFile, BigInteger serialNo,
86 Date notBefore, Date notAfter, String sigAlgorithm) throws JSTKException{
87 if (issuerCert == null || issuerKey == null){
88 throw new JSTKException("CertificateGenerator not initialized.");
89 }
90 try {
91 InputStream csris = org.jstk.pem.PEMData.getDERInputStream(csrFile);
93 CSR csr = new CSR();
94 DefASN1PullParser parser = new DefASN1PullParser();
95 parser.setInput(csris);
96 csr.decode(parser);
97
98 org.jstk.pki.Certificate cert = new org.jstk.pki.Certificate();
00 TBSCertificate tbsCertificate = cert.getTBSCertificate();
01
02 ASN1Integer version = tbsCertificate.getVersion().getVersion();
03 version.setValue((new BigInteger("2")).toByteArray());
04
05 tbsCertificate.getSerialNumber().setValue(serialNo.toByteArray());
06
07 AlgorithmIdentifier algorithmId = tbsCertificate.getAlgorithm();
08 algorithmId.setOid(OidMap.getId(sigAlgorithm));
09 algorithmId.setParams(new ASN1Null());
10
11 javax.security.auth.x500.X500Principal p = issuerCert.getSubjectX500Principal();
13 Name issuer = tbsCertificate.getIssuer();
14 issuer.setValue(p.getEncoded());
15 issuer.setIgnoreMembers(true);
16
17 Validity validity = tbsCertificate.getValidity();
19 validity.getNotBefore().setDate(notBefore);
20 validity.getNotAfter().setDate(notAfter);
21
22 Name subject = tbsCertificate.getSubject();
24 subject.reinitialize(csr.getCSRInfo().getSubject());
25 SubjectPublicKeyInfo publicKeyInfo = tbsCertificate.getSubjectPublicKeyInfo();
26 publicKeyInfo.reinitialize(csr.getCSRInfo().getPublicKeyInfo());
27
28 ASN1Explicit extensions = tbsCertificate.getExtensions();
30 ASN1Seq extnsSeq = new ASN1Seq();
31
32 ASN1Seq basicConsExtn = new ASN1Seq();
33 basicConsExtn.setValue(encodeBasicConstraints());
34 basicConsExtn.setIgnoreMembers(true);
35 extnsSeq.add(basicConsExtn);
36
37 if (keyUsage != null){ extnsSeq.add(createKeyUsage());
39 }
40
41 if (extendedKeyUsage != null){ extnsSeq.add(createExtendedKeyUsage());
43 }
44
45 extensions.setInstance(extnsSeq);
46
47 AlgorithmIdentifier algorithmId1 = cert.getAlgorithm();
50 algorithmId1.setOid(OidMap.getId(sigAlgorithm));
51 algorithmId1.setParams(new ASN1Null());
52
53 X509Certificate c = signCertificate(cert, sigAlgorithm, issuerKey);
54 return c;
55 } catch (Exception exc){
56 throw new JSTKException("generateCertificate failed", exc);
57 }
58 }
59
60 public X509Certificate generateSelfSignedCertificate(String dn, KeyPair kp, BigInteger serialNo,
61 int noDays) throws JSTKException {
62 Calendar cal = Calendar.getInstance();
63 Date notBefore = cal.getTime();
64 cal.add(Calendar.DATE, noDays);
65 Date notAfter = cal.getTime();
66 return generateSelfSignedCertificate(dn, kp, serialNo, notBefore,
67 notAfter, sigAlg);
68 }
69
70 public X509Certificate generateSelfSignedCertificate(String dn, KeyPair kp, BigInteger serialNo,
71 Date notBefore, Date notAfter, String sigAlgorithm) throws JSTKException{
72 try {
73 org.jstk.pki.Certificate cert = new org.jstk.pki.Certificate();
75 TBSCertificate tbsCertificate = cert.getTBSCertificate();
76
77 ASN1Integer version = tbsCertificate.getVersion().getVersion();
78 version.setValue((new BigInteger("2")).toByteArray());
79
80 tbsCertificate.getSerialNumber().setValue(serialNo.toByteArray());
81
82 AlgorithmIdentifier algorithmId = tbsCertificate.getAlgorithm();
83 algorithmId.setOid(OidMap.getId(sigAlgorithm));
84 algorithmId.setParams(new ASN1Null());
85
86 X500Principal p = new X500Principal(dn);
88 Name issuer = tbsCertificate.getIssuer();
89 issuer.setValue(p.getEncoded());
90 issuer.setIgnoreMembers(true);
91
92 Validity validity = tbsCertificate.getValidity();
94 validity.getNotBefore().setDate(notBefore);
95 validity.getNotAfter().setDate(notAfter);
96
97 Name subject = tbsCertificate.getSubject();
99 subject.setValue(p.getEncoded());
00 subject.setIgnoreMembers(true);
01 SubjectPublicKeyInfo publicKeyInfo = tbsCertificate.getSubjectPublicKeyInfo();
02 byte[] encoded = kp.getPublic().getEncoded();
03 publicKeyInfo.setValue(encoded);
04 publicKeyInfo.setIgnoreMembers(true);
05
06 ASN1Explicit extensions = tbsCertificate.getExtensions();
08 ASN1Seq extnsSeq = new ASN1Seq();
09
10 ASN1Seq basicConsExtn = new ASN1Seq();
11 basicConsExtn.setValue(encodeBasicConstraints());
12 basicConsExtn.setIgnoreMembers(true);
13 extnsSeq.add(basicConsExtn);
14
15 extensions.setInstance(extnsSeq);
16
17 AlgorithmIdentifier algorithmId1 = cert.getAlgorithm();
20 algorithmId1.setOid(OidMap.getId(sigAlgorithm));
21 algorithmId1.setParams(new ASN1Null());
22
23 X509Certificate c = signCertificate(cert, sigAlgorithm, kp.getPrivate());
24 return c;
25 } catch (Exception exc){
26 throw new JSTKException("generateCertificate failed", exc);
27 }
28 }
29
30 byte[] encodeBasicConstraints(){
31 ASN1Seq basicConsExtn = new ASN1Seq();
32 ASN1Oid oid = new ASN1Oid();
33 oid.setOid("2.5.29.19");
34
35 ASN1Seq basicConstraints = new ASN1Seq();
36 ASN1Boolean ab = new ASN1Boolean();
37 ab.setValue(caFlag);
38 ASN1Integer ai = new ASN1Integer();
39 ai.setValue(new BigInteger(Integer.toString(pathLen)));
40 basicConstraints.add(ab);
41 basicConstraints.add(ai);
42
43 ASN1OctetString aos = new ASN1OctetString();
44 aos.setValue(basicConstraints.encode());
45
46 basicConsExtn.add(oid);
47 basicConsExtn.add(aos);
48 return basicConsExtn.encode();
49 }
50
51 ASN1Seq createKeyUsage(){
52 ASN1Seq keyUsageExtn = new ASN1Seq();
53 ASN1Oid oid = new ASN1Oid();
54 oid.setOid("2.5.29.15");
55 ASN1BitString abs = new ASN1BitString();
56 abs.setValue(keyUsage.getBitString(), keyUsage.getNumUnusedBits());
57
58 ASN1OctetString aos = new ASN1OctetString();
59 aos.setValue(abs.encode());
60
61 keyUsageExtn.add(oid);
62 keyUsageExtn.add(aos);
63 return keyUsageExtn;
64 }
65
66 ASN1Seq createExtendedKeyUsage(){
67 ASN1Seq ekuExtn = new ASN1Seq();
68 ASN1Oid oid = new ASN1Oid();
69 oid.setOid("2.5.29.37");
70 ASN1Seq ids = new ASN1Seq();
71 for (int i = 0; i < extendedKeyUsage.size(); i++){
72 ASN1Oid id = new ASN1Oid();
73 id.setOid((String)extendedKeyUsage.get(i));
74 ids.add(id);
75 }
76
77 ASN1OctetString aos = new ASN1OctetString();
78 aos.setValue(ids.encode());
79
80 ekuExtn.add(oid);
81 ekuExtn.add(aos);
82 return ekuExtn;
83 }
84
85 X509Certificate signCertificate(org.jstk.pki.Certificate cert, String sigAlgorithm,
86 PrivateKey prvKey) throws Exception {
87 TBSCertificate tbsCertificate = cert.getTBSCertificate();
88
89 byte[] encodedTBSCertificate = tbsCertificate.encode();
91 Signature sig = Signature.getInstance(sigAlgorithm);
92 sig.initSign(prvKey);
93 sig.update(encodedTBSCertificate);
94 byte[] sigbytes = sig.sign();
95
96 ASN1BitString signatureBytes = cert.getSignatureBytes();
97 signatureBytes.setValue(sigbytes);
98
99 byte[] certBytes = cert.encode();
00
01 ByteArrayInputStream bais = new ByteArrayInputStream(certBytes);
02 CertificateFactory cf = CertificateFactory.getInstance("X.509");
03 X509Certificate c = (X509Certificate)cf.generateCertificate(bais);
04 return c;
05 }
06}