/* * keys - a primitive program to export and import (DSA) private and public keys and certificates from/into keystore * * Author: Andrey Tretyakov */ import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.FileNotFoundException; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.InvalidKeyException; import sun.security.provider.DSAPrivateKey; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import sun.misc.BASE64Encoder; import sun.misc.BASE64Decoder; public class keys { private File keystoreFile; private String storetype; private char[] storepass; private String alias; private char[] keypass; private File certfile; private File publicfile; private File privatefile; private Certificate certificate; private PublicKey publickey; private PrivateKey privatekey; private boolean certificatespecified; private boolean privatekeyspecified; public String getPassword() { Runtime runtime = Runtime.getRuntime(); Process process = null; String pass = null; try { //echo off String[] cmd = { "/bin/sh", "-c", "/bin/stty -echo < /dev/tty" }; process = runtime.exec(cmd); process.waitFor(); //read pass = (new BufferedReader(new InputStreamReader(System.in))).readLine(); //echo on cmd[2] = "/bin/stty echo < /dev/tty"; process = runtime.exec(cmd); process.waitFor(); } catch (InterruptedException e) { System.out.println(e); } catch (IOException e) { System.out.println(e); } return pass; } public PublicKey getPublicKey(KeyStore keystore, String alias) { try { certificate = keystore.getCertificate(alias); if (certificate == null) return null; return certificate.getPublicKey(); } catch (KeyStoreException e) { certificate = null; System.out.println(e); } return null; } public PrivateKey getPrivateKey(KeyStore keystore, String alias, char[] password) { try { Key key = keystore.getKey(alias, password); if (key instanceof PrivateKey) { return (PrivateKey)key; } } catch (UnrecoverableKeyException e) { //System.out.println(e); } catch (NoSuchAlgorithmException e) { //System.out.println(e); } catch (KeyStoreException e) { //System.out.println(e); } return null; } public void importKeys() { //checks and initialization if (certfile == null) { System.out.println("Certificate file name was not specified!"); System.out.println("Use parameters: -certfile "); return; } if (!certfile.exists()) { System.out.println("Certificate file " + certfile.getPath() + " doesn't exist!"); if (!certificatespecified) System.out.println("Use parameters: -certfile "); return; } if (privatefile == null) { System.out.println("Private key file name was not specified!"); System.out.println("Use parameters: -privatefile "); return; } if (!privatefile.exists()) { System.out.println("Private key file " + privatefile.getPath() + " doesn't exist!"); if (!privatekeyspecified) System.out.println("Use parameters: -privatefile "); return; } FileInputStream inKeystore = null; KeyStore keystore = null; BASE64Decoder decoder = new BASE64Decoder(); //get keystore password if (storepass == null) { System.out.println("Enter keystore password:"); storepass = getPassword().toCharArray(); } //loading of keystore database try { keystore = KeyStore.getInstance(storetype); } catch (KeyStoreException e) { System.out.println(e); return; } try { if (keystoreFile.exists()) inKeystore = new FileInputStream(keystoreFile); } catch (FileNotFoundException e) { System.out.println("Keystore file " + keystoreFile.getPath() + " not found.\n" + e); inKeystore = null; } try { keystore.load(inKeystore, storepass); } catch (NoSuchAlgorithmException e) { System.out.println(e); return; } catch (CertificateException e) { System.out.println(e); return; } catch (IOException e) { System.out.println("Wrong password for " + keystoreFile.getPath() + "!\n" + e); return; } //load private key (DSA only!) DSAPrivateKey DSAprKey = new DSAPrivateKey(); try { DSAprKey.decode(decoder.decodeBuffer(new FileInputStream(privatefile))); } catch (FileNotFoundException e) { System.out.println("Private key file " + privatefile.getPath() + " not found.\n" + e); return; } catch (InvalidKeyException e) { System.out.println(e); return; } catch (IOException e) { System.out.println(e); return; } privatekey = DSAprKey; char[] password; if (keypass != null) password = keypass; else { System.out.println("Enter key password for <" + alias + "> (or press ENTER if same as keystore password):"); keypass = getPassword().toCharArray(); if (keypass.length > 0) password = keypass; else password = storepass; } //load certificate try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate X509certificate = (X509Certificate)cf.generateCertificate(new FileInputStream(certfile)); certificate = X509certificate; } catch (FileNotFoundException e) { System.out.println("Certificate file " + certfile.getPath() + " not found.\n" + e); return; } catch (CertificateException e) { System.out.println(e); return; } Certificate[] chain = new Certificate[1]; chain[0] = certificate; //save keys into keystore try { keystore.setKeyEntry(alias, privatekey, password, chain); keystore.store(new FileOutputStream(keystoreFile), storepass); } catch (FileNotFoundException e) { System.out.println("Keystore file " + keystoreFile.getPath() + " not found.\n" + e); } catch (KeyStoreException e) { System.out.println(e); } catch (NoSuchAlgorithmException e) { System.out.println(e); } catch (CertificateException e) { System.out.println(e); } catch (IOException e) { System.out.println(e); } } public void exportKeys() { //checks and initialization if (!keystoreFile.exists()) { System.out.println("Keystore file " + keystoreFile.getPath() + " doesn't exist!"); return; } KeyStore keystore = null; BASE64Encoder encoder = new BASE64Encoder(); //get keystore password if (storepass == null) { System.out.println("Enter keystore password:"); storepass = getPassword().toCharArray(); } //loading of keystore database try { keystore = KeyStore.getInstance(storetype); } catch (KeyStoreException e) { System.out.println(e); return; } try { keystore.load(new FileInputStream(keystoreFile), storepass); } catch (FileNotFoundException e) { System.out.println("Keystore file " + keystoreFile.getPath() + " not found.\n" + e); return; } catch (NoSuchAlgorithmException e) { System.out.println(e); return; } catch (CertificateException e) { System.out.println(e); return; } catch (IOException e) { System.out.println("Wrong password for " + keystoreFile.getPath() + "!\n" + e); return; } //get certificate and public key if (certfile != null || publicfile != null) { publickey = getPublicKey(keystore, alias); if (certificate == null) System.out.println("Couldn't get certificate for <" + alias + ">!"); if (publickey == null) System.out.println("Couldn't get public key for <" + alias + ">!"); } //save certificate and public key to files FileWriter fw = null; if (certfile != null && certificate != null) try { fw = new FileWriter(certfile); fw.write("-----BEGIN CERTIFICATE-----\n"); fw.write(encoder.encode(certificate.getEncoded())); fw.write("\n-----END CERTIFICATE-----\n"); fw.close(); } catch (CertificateEncodingException e) { System.out.println(e); } catch (IOException e) { System.out.println(e); } if (publicfile != null && publickey != null) try { fw = new FileWriter(publicfile); fw.write(encoder.encode(publickey.getEncoded())); fw.close(); } catch (IOException e) { System.out.println(e); } //get private key if (privatefile != null) { privatekey = getPrivateKey(keystore, alias, storepass); if (privatekey == null) { if (keypass == null) { System.out.println("Enter key password for <" + alias + ">:"); keypass = getPassword().toCharArray(); } privatekey = getPrivateKey(keystore, alias, keypass); if (privatekey == null) System.out.println("Wrong password for <" + alias + ">!"); } } //save private key to file if (privatefile != null && privatekey != null) try { fw = new FileWriter(privatefile); // fw.write("—–BEGIN PRIVATE KEY—–\n"); fw.write(encoder.encode(privatekey.getEncoded())); // fw.write("\n—–END PRIVATE KEY—–\n"); fw.close(); } catch (IOException e) { System.out.println(e); } } public static void printUsage() { System.out.println("\nUsage:\n"); System.out.println("java keys {-import | -export} -keystore [-storepass ]" + " -alias [-keypass ]" + " [-storetype ] [-certfile ]" + " [-publicfile ] [-privatefile ]"); System.out.println("\nNote: You can import only DSA Private keys in PKCS #8 PEM format and certificates (not certificate chains!) in X.509 format.\n"); System.out.println("\nAuthor: Andrey Tretyakov"); System.out.println("\nThanks to:\nhttp://www.anandsekar.com/2006/01/19/exporting-the-private-key-from-a-jks-keystore/\nhttp://groups.google.com/group/comp.lang.java.programmer/msg/a132c7feda18187a\n"); } public static void main(String[] args) { if (args.length < 1 || args[0] == null || !args[0].equals("-import") && !args[0].equals("-export")) { printUsage(); return; } keys keys = new keys(); int i = 1; while (i < args.length - 1 && args[i] != null && !args[i].equals("") && args[i+1] != null && !args[i+1].equals("")) { if (args[i].equals("-keystore")) keys.keystoreFile = new File(args[i+1]); else if (args[i].equals("-storepass")) keys.storepass = args[i+1].toCharArray(); else if (args[i].equals("-alias")) keys.alias = args[i+1]; else if (args[i].equals("-keypass")) keys.keypass = args[i+1].toCharArray(); else if (args[i].equals("-storetype")) keys.storetype = args[i+1]; else if (args[i].equals("-certfile")) keys.certfile = new File(args[i+1]); else if (args[i].equals("-publicfile")) keys.publicfile = new File(args[i+1]); else if (args[i].equals("-privatefile")) keys.privatefile = new File(args[i+1]); else i--; i += 2; } if (keys.keystoreFile == null || keys.alias == null) { printUsage(); return; } if (keys.storetype == null) keys.storetype = "JKS"; if (keys.certfile != null) keys.certificatespecified = true; else keys.certificatespecified = false; if (keys.privatefile != null) keys.privatekeyspecified = true; else keys.privatekeyspecified = false; if (keys.certfile == null && keys.publicfile == null && keys.privatefile == null) { String s = keys.keystoreFile.getPath(); if (s.indexOf('/') == -1) s = ""; else s = s.substring(0, s.lastIndexOf('/') + 1); s = s + keys.alias; keys.certfile = new File(s + ".cer"); keys.publicfile = new File(s + ".public"); keys.privatefile = new File(s + ".private"); } if (args[0].equals("-import")) keys.importKeys(); if (args[0].equals("-export")) keys.exportKeys(); } }