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.X509Certificate;
18import java.security.cert.CertPath;
19import java.io.*;
20
21import org.jstk.*;
22import org.jstk.asn1.DefASN1PullParser;
23import org.jstk.asn1.ASN1Seq;
24import org.jstk.asn1.ASN1Set;
25import org.jstk.asn1.ASN1Oid;
26import org.jstk.asn1.ASN1Explicit;
27import org.jstk.pki.SignedData;
28import org.jstk.pki.ContentInfo;
29import org.jstk.cert.ca.CADatabase;
30import org.jstk.cert.ca.FileBasedCADatabaseParams;
31import java.math.BigInteger;
32
33public class IssueCertCommand extends JSTKCommandAdapter {
34 private static HashMap defaults = new HashMap();
35 static {
36 defaults.put("csrfile", "my.csr");
37 defaults.put("cerfile", "my.cer");
38 defaults.put("capath", "0");
39 defaults.put("cadir", "cadir");
40 defaults.put("cpfmt", "pkcs7");
41 defaults.put("keyalg", "RSA");
42 defaults.put("keysize", "1024");
43 defaults.put("sigalg", "SHA1WithRSA");
44 }
45
46 public String briefDescription(){
47 String briefDesc = "issues certificate based on Certificate Signing Request (CSR)";
48 return briefDesc;
49 }
50
51 public String optionsDescription(){
52 String optionsDesc =
53 " -cadir <cadir> : CA directory.[" +
54 defaults.get("cadir") + "]\n" +
55 " -csrfile <csrfile> : CSR file.[" +
56 defaults.get("csrfile") + "]\n" +
57 " -cerfile <cerfile> : File to write issued Certificate.[" +
58 defaults.get("cerfile") + "]\n" +
59 " -ca : Allow generated cert. to be used as a CA cert.\n" +
60 " -capath <length> : Certificate signing path length.[" +
61 defaults.get("capath") + "]\n" +
62 " -keyalg <keyalg> : Algorithm for Key Pair generation (RSA|DSA).[" +
63 defaults.get("keyalg") + "]\n" +
64 " -keysize <keysize> : Size of key (no. of bits).[" +
65 defaults.get("keysize") + "]\n" +
66 " -sigalg <sigalg> : Signature Algorithm. Should match Key Algorithm.[" +
67 defaults.get("sigalg") + "]\n" +
68 " -password <passwd> : Password for CA keystore.\n" +
69 " -extnconf <conffile>: Configuration file to indicate extensions.\n" +
70 " -cpfmt <cpfmt> : Certificate Path format (pkcs7, pkipath or x509).[" +
71 defaults.get("cpfmt") + "]\n";
72 return optionsDesc;
73 }
74 public String[] useForms(){
75 String[] useForms = {
76 "[-csrfile <csrfile>] [-cerfile <cerfile>]"
77 };
78 return useForms;
79 }
80 public String[] sampleUses(){
81 String[] sampleUses = {
82 "",
83 "-csrfile test.csr -cerfile test.cer"
84 };
85 return sampleUses;
86 }
87
88
89 public Object execute(JSTKArgs args) throws JSTKException{
90 try {
91 args.setDefaults(defaults);
92 String csrfile = args.get("csrfile");
93 String cerfile = args.get("cerfile");
94 String cadir = args.get("cadir");
95 String cpfmt = args.get("cpfmt");
96 boolean caFlag = Boolean.valueOf(args.get("ca")).booleanValue();
97 int pathLen = Integer.parseInt(args.get("capath"));
98 String keyAlg = args.get("keyalg");
99 String sigAlg = args.get("sigalg");
00 String password = args.get("password");
01 String conffile = args.get("extnconf");
02 int keySize = Integer.parseInt(args.get("keysize"));
03
04 boolean pkcs7Format = false;
05 boolean pkipathFormat = false;
06 boolean x509Format = false;
07 if (cpfmt.equalsIgnoreCase("pkcs7"))
08 pkcs7Format = true;
09 else if (cpfmt.equalsIgnoreCase("pkipath"))
10 pkipathFormat = true;
11 else if (cpfmt.equalsIgnoreCase("x509"))
12 x509Format = true;
13 else
14 return new JSTKResult(null, false, "Invalid CertPath format: " + cpfmt);
15
16 if (password == null)
17 return new JSTKResult(null, false, "CA keystore password not specified. Use -password option.");
18
19 KeyUsage ku = null;
20 List eku = null;
21
22 if (conffile != null){ Properties props = new Properties();
24 try {
25 FileInputStream fis = new FileInputStream(conffile);
26 props.load(fis);
27 } catch (IOException ioe){
28 return new JSTKResult(null, false, "Cannot read extnconf file: " + ioe);
29 }
30
31 String kuFlag = props.getProperty("KeyUsage");
33 if (kuFlag != null && kuFlag.equalsIgnoreCase("true")){
34 ku = new KeyUsage();
35 String kuString = null;
36 int index = 0;
37 while ((kuString = KeyUsage.getKeyUsageString(index)) != null){
38 String kuStringFlag = props.getProperty("KeyUsage." + kuString);
39 if (kuStringFlag != null && kuStringFlag.equalsIgnoreCase("true")){
40 ku.setKeyUsage(index, true);
41 }
42 ++index;
43 }
44 }
45
46 String ekuFlag = props.getProperty("ExtendedKeyUsage");
48 if (ekuFlag != null && ekuFlag.equalsIgnoreCase("true")){
49 eku = new LinkedList();
50 String ekuOId = null;
51 int index = 0;
52 while ((ekuOId = props.getProperty("ExtendedKeyUsage.ObjectId." + index)) != null){
53 eku.add(ekuOId);
54 ++index;
55 }
56 }
57 }
58
59 FileBasedCADatabaseParams fbParams = new FileBasedCADatabaseParams(cadir);
60 fbParams.setPassword(password);
61
62 CADatabase cadb = CADatabase.getInstance("file", fbParams);
63 CertificateGenerator cg =
64 new CertificateGenerator((X509Certificate)cadb.getCACert(), cadb.getCAPrivateKey());
65
66 cg.setBasicConstraints(caFlag, pathLen);
67 cg.setSigAlg(sigAlg);
68 cg.setKeyUsage(ku);
69 cg.setExtendedKeyUsage(eku);
70
71
72 X509Certificate cert = cg.generateCertificate(csrfile, cadb.nextSerialNumber());
73 cadb.getIssuedCerts().add(cert);
74
75 byte[] outBytes;
76 if (pkipathFormat){
77 try {
78 CertPath caCertPath = cadb.getCACertPath();
79 byte[] caCertPathBytes = caCertPath.getEncoded();
80 ASN1Seq cpSeq = new ASN1Seq();
81 cpSeq.decode(DefASN1PullParser.getInstance(caCertPathBytes));
82 byte[] certBytes = cert.getEncoded();
83 ASN1Seq certSeq = new ASN1Seq();
84 certSeq.decode(DefASN1PullParser.getInstance(certBytes));
85 cpSeq.add(certSeq);
86 outBytes = cpSeq.encode();
87 } catch (Exception e){
88 throw new JSTKException("cannot form PkiPath certpath", e);
89 }
90 } else if (pkcs7Format){
91 try {
92 CertPath caCertPath = cadb.getCACertPath();
93 byte[] caCertPathBytes = caCertPath.getEncoded();
94 ASN1Seq cpSeq = new ASN1Seq();
95 cpSeq.decode(DefASN1PullParser.getInstance(caCertPathBytes));
96 byte[] certBytes = cert.getEncoded();
97 ASN1Seq certSeq = new ASN1Seq();
98 certSeq.decode(DefASN1PullParser.getInstance(certBytes));
99 ContentInfo ci = new ContentInfo();
00 ASN1Oid contentType = ci.getContentType();
01 contentType.setOid("1.2.840.113549.1.7.2");
02 ASN1Explicit content = ci.getContent();
03 SignedData sd = new SignedData();
04 sd.getVersion().setValue(new java.math.BigInteger("1"));
05 sd.getContentInfo().getContentType().setOid("1.2.840.113549.1.7.1");
06 content.setInstance(sd);
07 ASN1Set certs = sd.getCertificates();
08
09 certs.add(certSeq);
10 for (int i = cpSeq.size() - 1; i >= 0; i--)
11 certs.add(cpSeq.elementAt(i));
12 outBytes = ci.encode();
13 } catch (Exception e){
14 throw new JSTKException("cannot form PKCS#7 certpath", e);
15 }
16 } else {
17 outBytes = cert.getEncoded();
18 }
19 FileOutputStream fos = new FileOutputStream(cerfile);
20 fos.write(outBytes);
21 fos.close();
22
23 return new JSTKResult(null, true, "Issued Certificate written to file: " + cerfile);
24 } catch (Exception exc){
25 throw new JSTKException("IssueCertCommand execution failed", exc);
26 }
27 }
28
29 public static void main(String[] args) throws Exception {
30 JSTKOptions opts = new JSTKOptions();
31 opts.parse(args, 0);
32 IssueCertCommand issueCertCmd = new IssueCertCommand();
33 JSTKResult result = (JSTKResult)issueCertCmd.execute(opts);
34 System.out.println(result.getText());
35 System.exit(result.isSuccess()? 0 : 1);
36 }
37}