1
10package org.jstk.crypt;
11
12import java.util.*;
13import java.security.*;
14import java.io.*;
15import java.security.cert.Certificate;
16import javax.crypto.SecretKey;
17import javax.crypto.KeyGenerator;
18
19import org.jstk.JSTKCommand;
20import org.jstk.JSTKCommandAdapter;
21import org.jstk.JSTKException;
22import org.jstk.JSTKArgs;
23import org.jstk.JSTKOptions;
24import org.jstk.JSTKResult;
25
26import org.jstk.pem.PEMData;
27
28public class ExportCommand extends JSTKCommandAdapter{
29 private static HashMap defaults = new HashMap();
30 private boolean pkcs12Output = false;
31 static {
32 defaults.put("kstype", "JKS");
33 defaults.put("keystore", "my.keystore");
34 defaults.put("storepass", "changeit");
35 defaults.put("outform", "PEM");
36 }
37 public String briefDescription(){
38 return "exports key or cert entries from keystore to files";
39 }
40 public String optionsDescription(){
41 return
42 " -keystore <keystore>: the keystore.[" +
43 defaults.get("keystore") + "]\n" +
44 " -storepass <storepass>: Password for keystore.[" +
45 defaults.get("storepass") + "]\n" +
46 " -kstype <type> : the keystore type.[" +
47 defaults.get("type") + "]\n" +
48 " -alias <alias> : alias to access the key in the keystore.[" +
49 defaults.get("alias") + "]\n" +
50 " -keypass <keypass> : Password for key in the keystore.[" +
51 defaults.get("keypass") + "]\n" +
52 " -outform <outform> : Format of exported data(DER|PEM|PKCS12).[" +
53 defaults.get("keypass") + "]\n" +
54 " -provider <provider> : provider name for KeyStore.\n";
55
56 }
57
58 public String[] useForms(){
59 String[] forms = {
60 "[-keystore <keystore>] [-kstype (JCEKS|JKS|PKCS12)]\n" +
61 "\t[-storepass <storepass>] [-alias <alias>] [-keypass <keypass>]\n" +
62 "\t[-outform <outform>][-provider <provider>]"
63 };
64 return forms;
65 }
66
67 public String[] sampleUses(){
68 String[] uses = {
69 "",
70 "-keystore test.ks -storepass testpass",
71 "-alias test.key -outform PKCS12"
72 };
73 return uses;
74 }
75
76 private void exportKey(Key key, String alias, StringBuffer sb, String outform) throws Exception{
77 String keytype = (key instanceof SecretKey ? "SecretKey" :
78 (key instanceof PrivateKey ? "PrivateKey" : "PublicKey"));
79 String keyfile = alias + (outform.equalsIgnoreCase("PEM") ? ".pem" : ".key.der");
80 FileOutputStream fos = new FileOutputStream(keyfile);
81 byte[] derEncodedKey = key.getEncoded();
82 if (outform.equalsIgnoreCase("PEM")){
83 PEMData pemData = new PEMData(derEncodedKey);
84 String base64Data = pemData.encode();
85 String preEB = "-----BEGIN PRIVATE KEY-----\n";
86 String postEB = "\n-----END PRIVATE KEY-----\n";
87 fos.write(preEB.getBytes());
88 fos.write(base64Data.getBytes());
89 fos.write(postEB.getBytes());
90 } else {
91 fos.write(derEncodedKey);
92 }
93 fos.close();
94 sb.append("Exported " + keytype + " to file: " + keyfile + "\n");
95 }
96
97 private void exportCertChain(Certificate[] certs, String alias, StringBuffer sb, String outform) throws Exception{
98 if (certs == null)
99 return;
00
01 for (int i = 0; i < certs.length; i++){
02 String cerfile = alias + (outform.equalsIgnoreCase("PEM") ? ".pem" : ".crt." + i + ".der");
03 boolean append = (outform.equalsIgnoreCase("PEM") ? true : false);
04 FileOutputStream fos = new FileOutputStream(cerfile, append);
05 byte[] derEncodedCert = certs[i].getEncoded();
06 if (outform.equalsIgnoreCase("PEM")){
07 PEMData pemData = new PEMData(derEncodedCert);
08 String base64Data = pemData.encode();
09 String preEB = "-----BEGIN CERTIFICATE-----\n";
10 String postEB = "\n-----END CERTIFICATE-----\n";
11 fos.write(preEB.getBytes());
12 fos.write(base64Data.getBytes());
13 fos.write(postEB.getBytes());
14 } else {
15 fos.write(derEncodedCert);
16 }
17 fos.close();
18 sb.append("Appended Certificate#" + i + " to file: " + cerfile + "\n");
19 }
20 }
21
22 private String exportEntry(KeyStore ks, String alias, String keypass, String outform) throws Exception{
23 StringBuffer sb = new StringBuffer();
24 if (ks.isKeyEntry(alias)){
25 try {
26 Key key = ks.getKey(alias, keypass.toCharArray());
27 exportKey(key, alias, sb, outform);
28
29 Certificate[] certs = ks.getCertificateChain(alias);
30 exportCertChain(certs, alias, sb, outform);
31 if (pkcs12Output){ String pemfile = alias + ".pem";
33 String p12file = alias + ".p12";
34 pem2pkcs12(pemfile, p12file, keypass, sb);
35 }
36 } catch (UnrecoverableKeyException e){
37 sb.append("Cannot Receover Key from KeyStore.\n");
38 }
39 } else {
40 Certificate[] certs = ks.getCertificateChain(alias);
41 exportCertChain(certs, alias, sb, outform);
42 }
43 return sb.toString();
44 }
45
46 private void pem2pkcs12(String pemfile, String p12file, String keypass, StringBuffer sb){
48 if (!opensslPresent()){
50 sb.append("*** ERROR *** Couldn't find openssl. Cannot convert PEM to PKCS12.");
51 } else {
52 String cmd = "openssl pkcs12 -export -in " + pemfile +
53 " -out " + p12file + " -password pass:" + keypass;
54 int result = runOSCommand(cmd);
55 if (result == 0){
56 sb.append("Converted PEM file " + pemfile + " to PKCS12 file " + p12file);
57 } else {
58 sb.append("*** ERROR *** Conversion of PEM file " + pemfile +
59 "to PKCS12 file " + p12file + " FAILED");
60 }
61 }
62 }
63
64 private boolean opensslPresent(){
65 if (runOSCommand("openssl exit") == 0){
66 return true;
67 } else {
68 return false;
69 }
70 }
71
72 private int runOSCommand(String cmd){
73 try {
74 Process p = Runtime.getRuntime().exec(cmd);
75 return p.waitFor();
76 } catch (IOException ioe){
77 return 1;
78 } catch (InterruptedException ie){
79 return 1;
80 }
81 }
82
83 public Object execute(JSTKArgs args) throws JSTKException{
84 StringBuffer sb = new StringBuffer();
85 try {
86 args.setDefaults(defaults);
87 pkcs12Output = false;
88 String keystore = args.get("keystore");
89 String storepass = args.get("storepass");
90 String type = args.get("kstype");
91 String providerName = args.get("provider");
92 String keypass = args.get("keypass");
93 String outform = args.get("outform");
94 if (outform.equalsIgnoreCase("PKCS12")){
95 pkcs12Output = true;
96 outform = "PEM";
97 }
98 if (keypass == null)
99 keypass = storepass;
00 String alias = args.get("alias");
01
02 FileInputStream fis = new FileInputStream(keystore);
03
04 KeyStore ks;
05 if (providerName != null)
06 ks = KeyStore.getInstance(type, providerName);
07 else
08 ks = KeyStore.getInstance(type);
09
10 ks.load(fis, storepass.toCharArray());
11
12 if (alias != null){
13 if (ks.containsAlias(alias)){
14 sb.append(exportEntry(ks, alias, keypass, outform));
15 } else {
16 sb.append("No such Entry: " + alias + ".\n");
17 }
18 } else {
19 Enumeration enum = ks.aliases();
20
21 while (enum.hasMoreElements()){
22 String alias0 = (String)enum.nextElement();
23 sb.append(exportEntry(ks, alias0, keypass, outform));
24 }
25 }
26 } catch (Exception exc){
27 throw new JSTKException("ExportCommand.execute() failed", exc);
28 }
29 return new JSTKResult(null, true, sb.toString());
30 }
31}