Java tutorial
// Copyright 2009 Jean-Francois Houzard, Olivier Roger // // This file is part of epassportviewer. // // epassportviewer is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // epassportviewer 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 General Public License for more details. // // You should have received a copy of the GNU General Public // License along with epassportviewer. // If not, see <http://www.gnu.org/licenses/>. import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.cert.CertStore; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Vector; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessable; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class createSod { private static final String NAME = "createSod"; private static final String VERSION = "v0.1"; /** * @param args * @throws CMSException */ public static void main(String[] args) throws Exception { try { CommandLine options = verifyArgs(args); String privateKeyLocation = options.getOptionValue("privatekey"); String keyPassword = options.getOptionValue("keypass"); String certificate = options.getOptionValue("certificate"); String sodContent = options.getOptionValue("content"); String sod = ""; if (options.hasOption("out")) { sod = options.getOptionValue("out"); } // CHARGEMENT DU FICHIER PKCS#12 KeyStore ks = null; char[] password = null; Security.addProvider(new BouncyCastleProvider()); try { ks = KeyStore.getInstance("PKCS12"); // Password pour le fichier personnal_nyal.p12 password = keyPassword.toCharArray(); ks.load(new FileInputStream(privateKeyLocation), password); } catch (Exception e) { System.out.println("Erreur: fichier " + privateKeyLocation + " n'est pas un fichier pkcs#12 valide ou passphrase incorrect"); return; } // RECUPERATION DU COUPLE CLE PRIVEE/PUBLIQUE ET DU CERTIFICAT PUBLIQUE X509Certificate cert = null; PrivateKey privatekey = null; PublicKey publickey = null; try { Enumeration en = ks.aliases(); String ALIAS = ""; Vector vectaliases = new Vector(); while (en.hasMoreElements()) vectaliases.add(en.nextElement()); String[] aliases = (String[]) (vectaliases.toArray(new String[0])); for (int i = 0; i < aliases.length; i++) if (ks.isKeyEntry(aliases[i])) { ALIAS = aliases[i]; break; } privatekey = (PrivateKey) ks.getKey(ALIAS, password); cert = (X509Certificate) ks.getCertificate(ALIAS); publickey = ks.getCertificate(ALIAS).getPublicKey(); } catch (Exception e) { e.printStackTrace(); return; } // Chargement du certificat partir du fichier InputStream inStream = new FileInputStream(certificate); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) cf.generateCertificate(inStream); inStream.close(); // Chargement du fichier qui va tre sign File file_to_sign = new File(sodContent); byte[] buffer = new byte[(int) file_to_sign.length()]; DataInputStream in = new DataInputStream(new FileInputStream(file_to_sign)); in.readFully(buffer); in.close(); // Chargement des certificats qui seront stocks dans le fichier .p7 // Ici, seulement le certificat personnal_nyal.cer sera associ. // Par contre, la chane des certificats non. ArrayList certList = new ArrayList(); certList.add(cert); CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC"); CMSSignedDataGenerator signGen = new CMSSignedDataGenerator(); // privatekey correspond notre cl prive rcupre du fichier PKCS#12 // cert correspond au certificat publique personnal_nyal.cer // Le dernier argument est l'algorithme de hachage qui sera utilis signGen.addSigner(privatekey, cert, CMSSignedDataGenerator.DIGEST_SHA1); signGen.addCertificatesAndCRLs(certs); CMSProcessable content = new CMSProcessableByteArray(buffer); // Generation du fichier CMS/PKCS#7 // L'argument deux permet de signifier si le document doit tre attach avec la signature // Valeur true: le fichier est attach (c'est le cas ici) // Valeur false: le fichier est dtach CMSSignedData signedData = signGen.generate(content, true, "BC"); byte[] signeddata = signedData.getEncoded(); // Ecriture du buffer dans un fichier. if (sod.equals("")) { System.out.print(signeddata.toString()); } else { FileOutputStream envfos = new FileOutputStream(sod); envfos.write(signeddata); envfos.close(); } } catch (OptionException oe) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(NAME, getOptions()); System.exit(-1); } catch (Exception e) { e.printStackTrace(); return; } } private static CommandLine verifyArgs(String[] args) throws OptionException { // create the command line parser CommandLineParser parser = new PosixParser(); try { CommandLine line = parser.parse(getOptions(), args); // parse the command line arguments if (line.hasOption("v") || line.hasOption("version")) { System.out.println(NAME + " " + VERSION); System.out.println(""); System.out.println(NAME + " packages two unaltered open-source tools:"); System.out.println(" Apache Common CLI -- commons.apache.org"); System.out.println(" Bouncy Castle -- www.bouncycastle.org"); System.out.println("Please see LICENSE files for more informations"); System.exit(0); } List<String> mandatory = new ArrayList<String>(); mandatory.add("privatekey"); mandatory.add("keypass"); mandatory.add("certificate"); mandatory.add("content"); for (String option : mandatory) { if (!line.hasOption(option)) { throw new OptionException("Option " + option + " missing"); } } return line; } catch (ParseException exp) { System.out.println("Unexpected exception:" + exp.getMessage()); System.exit(-1); } return null; } // create the Options private static Options getOptions() { Options options = new Options(); options.addOption("v", "version", false, "Version"); options.addOption(OptionBuilder.withLongOpt("privatekey").withDescription("Private Key Location").hasArg() .withArgName("path").create()); options.addOption(OptionBuilder.withLongOpt("keypass").withDescription("Key Password").hasArg() .withArgName("string").create()); options.addOption(OptionBuilder.withLongOpt("certificate").withDescription("Certificate").hasArg() .withArgName("path").create()); options.addOption(OptionBuilder.withLongOpt("content").withDescription("SOD Content").hasArg() .withArgName("path").create()); options.addOption(OptionBuilder.withLongOpt("out").withDescription("Destination file").hasArg() .withArgName("path").create()); return options; } }