Java tutorial
/* * Copyright (c) 2010-2011, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.common.tools; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.Certificate; import java.util.Enumeration; import java.util.UUID; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.MissingArgumentException; import org.apache.commons.cli.MissingOptionException; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.UnrecognizedOptionException; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.text.StrBuilder; /** * Tool which can be used to manage PFX files * * @author Martijn Brinkers * */ public class PfxTool { private static final String COMMAND_NAME = PfxTool.class.getName(); private String inPassword; private String destPassword; private String inFile; private String destFile; private boolean retainAliases; private Option inPasswordOption; private Option destPasswordOption; private Option inOption; private Option destOption; private Option mergeOption; private Option listOption; private Option retainAliasesOption; private Option helpOption; @SuppressWarnings("static-access") private Options createCommandLineOptions() { Options options = new Options(); inPasswordOption = OptionBuilder.withArgName("inpass").hasArg() .withDescription("Password for the input pfx.").create("inpass"); inPasswordOption.setRequired(true); options.addOption(inPasswordOption); destPasswordOption = OptionBuilder.withArgName("destpass").hasArg() .withDescription("Password for the destination pfx.").create("destpass"); destPasswordOption.setRequired(false); options.addOption(destPasswordOption); inOption = OptionBuilder.withArgName("file").hasArg().withDescription("The filename of the input pfx.") .create("in"); inOption.setRequired(true); options.addOption(inOption); destOption = OptionBuilder.withArgName("file").hasArg() .withDescription("The filename of the destination pfx.").create("dest"); destOption.setRequired(false); options.addOption(destOption); mergeOption = OptionBuilder.withDescription("Adds the input pfx to the output pfx.").create("merge"); mergeOption.setRequired(false); options.addOption(mergeOption); listOption = OptionBuilder.withDescription("Shows all items from the input pfx.").create("list"); listOption.setRequired(false); options.addOption(listOption); helpOption = OptionBuilder.withDescription("Show help").create("help"); helpOption.setRequired(false); options.addOption(helpOption); retainAliasesOption = OptionBuilder.withDescription("If enabled, the aliases from the input will be kept.") .create("retainaliases"); retainAliasesOption.setRequired(false); options.addOption(retainAliasesOption); return options; } private static KeyStore loadKeyStore(String keyFile, boolean shouldExist, String password) throws Exception { File file = new File(keyFile); file = file.getAbsoluteFile(); KeyStore keyStore = KeyStore.getInstance("PKCS12"); if (shouldExist && !file.exists()) { throw new FileNotFoundException(keyFile + " pfx file not found."); } /* initialize key store */ char[] pw = password != null ? password.toCharArray() : null; if (file.exists()) { InputStream input = new FileInputStream(file); keyStore.load(input, pw); input.close(); } else { // creates an empty keystore keyStore.load(null, pw); } return keyStore; } private void mergePfx() throws Exception { if (StringUtils.isEmpty(destFile)) { throw new MissingOptionException(destOption.getOpt() + " is missing."); } if (StringUtils.isEmpty(destPassword)) { throw new MissingOptionException(destPasswordOption.getOpt() + " is missing."); } KeyStore inStore = loadKeyStore(inFile, true, inPassword); KeyStore destStore = loadKeyStore(destFile, false, destPassword); Enumeration<String> aliases = inStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); String destAlias = retainAliases ? alias : UUID.randomUUID().toString() + "_" + alias; if (inStore.isKeyEntry(alias)) { KeyStore.Entry entry = inStore.getEntry(alias, new KeyStore.PasswordProtection(inPassword.toCharArray())); destStore.setEntry(destAlias, entry, new KeyStore.PasswordProtection(destPassword.toCharArray())); } else { Certificate certificate = inStore.getCertificate(alias); destStore.setCertificateEntry(destAlias, certificate); } } destStore.store(new FileOutputStream(destFile), destPassword.toCharArray()); } private static void printKeystoreDetails(KeyStore keyStore) throws KeyStoreException { Enumeration<String> aliases = keyStore.aliases(); int count = 0; System.out.println("**** BEGIN ENTRIES ***"); while (aliases.hasMoreElements()) { count++; String alias = aliases.nextElement(); StrBuilder sb = new StrBuilder(); sb.append("Alias: ").append(alias).append(", key entry: ").append(keyStore.isKeyEntry(alias)); System.out.println(sb.toString()); } System.out.println("**** END ENTRIES ***"); System.out.println("Nr of entries: " + count); } private void listPfx() throws Exception { KeyStore keyStore = loadKeyStore(inFile, true, inPassword); printKeystoreDetails(keyStore); } private void handleCommandline(String[] args) throws Exception { CommandLineParser parser = new BasicParser(); Options options = createCommandLineOptions(); HelpFormatter formatter = new HelpFormatter(); CommandLine commandLine; try { commandLine = parser.parse(options, args); } catch (ParseException e) { formatter.printHelp(COMMAND_NAME, options, true); throw e; } if (commandLine.getOptions().length == 0) { formatter.printHelp(COMMAND_NAME, options, true); System.exit(1); return; } if (commandLine.getOptions().length == 0 || commandLine.hasOption(helpOption.getOpt())) { formatter.printHelp(COMMAND_NAME, options, true); return; } inPassword = inPasswordOption.getValue(); destPassword = destPasswordOption.getValue(); inFile = inOption.getValue(); destFile = destOption.getValue(); retainAliases = commandLine.hasOption(retainAliasesOption.getOpt()); if (commandLine.hasOption(mergeOption.getOpt())) { mergePfx(); } if (commandLine.hasOption(listOption.getOpt())) { listPfx(); } } public static void main(String[] args) throws Exception { PfxTool tool = new PfxTool(); try { tool.handleCommandline(args); } catch (MissingArgumentException e) { System.err.println("Not all required parameters are specified. " + e.getMessage()); System.exit(3); } catch (MissingOptionException e) { System.err.println("Not all required options are specified. " + e.getMessage()); System.exit(4); } catch (UnrecognizedOptionException e) { System.err.println("Unknown option specified. " + e.getMessage()); System.exit(4); } } }