001: /*************************************************************************
002: * *
003: * EJBCA: The OpenSource Certificate Authority *
004: * *
005: * This software is free software; you can redistribute it and/or *
006: * modify it under the terms of the GNU Lesser General Public *
007: * License as published by the Free Software Foundation; either *
008: * version 2.1 of the License, or any later version. *
009: * *
010: * See terms of license at gnu.org. *
011: * *
012: *************************************************************************/package org.ejbca.util;
013:
014: import java.io.*;
015: import java.security.KeyStore;
016: import java.security.KeyStoreException;
017: import java.security.NoSuchAlgorithmException;
018: import java.security.NoSuchProviderException;
019: import java.security.PrivateKey;
020: import java.security.UnrecoverableKeyException;
021: import java.security.cert.*;
022: import java.util.Enumeration;
023:
024: import org.apache.log4j.Logger;
025:
026: /**
027: * P12toPEM is used to export PEM files from a single p12 file. The class exports the user
028: * certificate, user private key in seperated files and the chain of sub ca and ca certifikate in
029: * a third file. The PEM files will have the names <i>common name</i>.pem, <i>common
030: * name</i>Key.pem and <i>common name</i>CA.pem derived from the DN in user certificate.
031: *
032: * @version $Id: P12toPEM.java,v 1.1 2006/01/17 20:32:19 anatom Exp $
033: */
034: public class P12toPEM {
035: private static Logger log = Logger.getLogger(P12toPEM.class);
036: String exportpath = "./p12/pem/";
037: String p12File;
038: String password;
039: KeyStore ks = null;
040:
041: boolean overwrite = false;
042: byte[] beginCertificate = "-----BEGIN CERTIFICATE-----".getBytes();
043: byte[] endCertificate = "-----END CERTIFICATE-----".getBytes();
044: byte[] beginPrivateKey = "-----BEGIN PRIVATE KEY-----".getBytes();
045: byte[] endPrivateKey = "-----END PRIVATE KEY-----".getBytes();
046: byte[] NL = "\n".getBytes();
047:
048: /**
049: * DOCUMENT ME!
050: *
051: * @param args DOCUMENT ME!
052: */
053: public static void main(String[] args) {
054: // Bouncy Castle security provider
055: CertTools.installBCProvider();
056:
057: P12toPEM p12 = null;
058:
059: try {
060: if (args.length > 2) {
061: boolean overwrite = false;
062:
063: if (args[2].equalsIgnoreCase("true")) {
064: overwrite = true;
065: }
066:
067: p12 = new P12toPEM(args[0], args[1], overwrite);
068: } else if (args.length > 1) {
069: p12 = new P12toPEM(args[0], args[1]);
070: } else {
071: System.out
072: .println("Usage: P12toPEM <p12file> <p12password> [overwrite (true/false)(default false)]");
073: System.exit(0);
074: }
075:
076: p12.createPEM();
077: } catch (Exception e) {
078: e.printStackTrace();
079: }
080: }
081:
082: /**
083: * Basic construtor for the P12toPEM class, set variables for the class.
084: *
085: * @param p12File p12File The (path +) name of the input p12 file.
086: * @param password password The password for the p12 file.
087: *
088: */
089: public P12toPEM(String p12File, String password) {
090: this .p12File = p12File;
091: this .password = password;
092: }
093:
094: /**
095: * Basic construtor using a inmemory keystore instead for a file.
096: *
097: * @param ks the keystore to use.
098: * @param password password The password for the p12 file.
099: * @param overwrite overwrite If existing files should be overwritten.
100: */
101: public P12toPEM(KeyStore keystore, String password,
102: boolean overwrite) {
103: this .password = password;
104: this .ks = keystore;
105: this .overwrite = overwrite;
106: }
107:
108: /**
109: * Sets the directory where PEM-files wil be stores
110: *
111: * @param path path where PEM-files will be stores
112: */
113: public void setExportPath(String path) {
114: exportpath = path;
115: }
116:
117: /**
118: * Constructor for the P12toPEM class.
119: *
120: * @param p12File p12File The (path +) name of the input p12 file.
121: * @param password password The password for the p12 file.
122: * @param overwrite overwrite If existing files should be overwritten.
123: */
124: public P12toPEM(String p12File, String password, boolean overwrite) {
125: this .p12File = p12File;
126: this .password = password;
127: this .overwrite = overwrite;
128: }
129:
130: /**
131: * DOCUMENT ME!
132: *
133: * @throws KeyStoreException DOCUMENT ME!
134: * @throws FileNotFoundException DOCUMENT ME!
135: * @throws IOException DOCUMENT ME!
136: * @throws NoSuchProviderException DOCUMENT ME!
137: * @throws NoSuchAlgorithmException DOCUMENT ME!
138: * @throws CertificateEncodingException DOCUMENT ME!
139: * @throws CertificateException DOCUMENT ME!
140: * @throws UnrecoverableKeyException DOCUMENT ME!
141: */
142: public void createPEM() throws KeyStoreException,
143: FileNotFoundException, IOException,
144: NoSuchProviderException, NoSuchAlgorithmException,
145: CertificateEncodingException, CertificateException,
146: UnrecoverableKeyException {
147:
148: if (this .ks == null) {
149: ks = KeyStore.getInstance("PKCS12", "BC");
150: InputStream in = new FileInputStream(p12File);
151: ks.load(in, password.toCharArray());
152: in.close();
153: }
154: // Fid the key private key entry in the keystore
155: Enumeration e = ks.aliases();
156: Object o = null;
157: PrivateKey serverPrivKey = null;
158:
159: while (e.hasMoreElements()) {
160: o = e.nextElement();
161:
162: if (o instanceof String) {
163: if ((ks.isKeyEntry((String) o))
164: && ((serverPrivKey = (PrivateKey) ks.getKey(
165: (String) o, password.toCharArray())) != null)) {
166: log.debug("Aliases " + o + " is KeyEntry.");
167:
168: break;
169: }
170: }
171: }
172:
173: log
174: .debug((("Private key encode: " + serverPrivKey) == null) ? null
175: : serverPrivKey.getFormat());
176:
177: byte[] privKeyEncoded = "".getBytes();
178:
179: if (serverPrivKey != null) {
180: privKeyEncoded = serverPrivKey.getEncoded();
181: }
182:
183: //Certificate chain[] = ks.getCertificateChain((String) o);
184: Certificate[] chain = KeyTools.getCertChain(ks, (String) o);
185: log.debug("Loaded certificate chain with length "
186: + chain.length + " from keystore.");
187:
188: X509Certificate userX509Certificate = (X509Certificate) chain[0];
189:
190: byte[] output = userX509Certificate.getEncoded();
191: String sn = CertTools.getSubjectDN(userX509Certificate);
192: String userFile = CertTools.getPartFromDN(sn, "CN");
193: String filetype = ".pem";
194:
195: File path = new File(exportpath);
196: path.mkdir();
197:
198: File tmpFile = new File(path, userFile + filetype);
199:
200: if (!overwrite) {
201: if (tmpFile.exists()) {
202: log.error("File '" + tmpFile
203: + "' already exists, don't overwrite.");
204:
205: return;
206: }
207: }
208:
209: OutputStream out = new FileOutputStream(tmpFile);
210: out.write(beginCertificate);
211: out.write(NL);
212:
213: byte[] userCertB64 = Base64.encode(output);
214: out.write(userCertB64);
215: out.write(NL);
216: out.write(endCertificate);
217: out.close();
218:
219: tmpFile = new File(path, userFile + "-Key" + filetype);
220:
221: if (!overwrite) {
222: if (tmpFile.exists()) {
223: log.error("File '" + tmpFile
224: + "' already exists, don't overwrite.");
225:
226: return;
227: }
228: }
229:
230: out = new FileOutputStream(tmpFile);
231: out.write(beginPrivateKey);
232: out.write(NL);
233:
234: byte[] privKey = Base64.encode(privKeyEncoded);
235: out.write(privKey);
236: out.write(NL);
237: out.write(endPrivateKey);
238: out.close();
239:
240: tmpFile = new File(path, userFile + "-CA" + filetype);
241:
242: if (!overwrite) {
243: if (tmpFile.exists()) {
244: log.error("File '" + tmpFile
245: + "' already exists, don't overwrite.");
246:
247: return;
248: }
249: }
250:
251: if (CertTools.isSelfSigned(userX509Certificate)) {
252: log
253: .info("User certificate is selfsigned, this is a RootCA, no CA certificates written.");
254: } else {
255: out = new FileOutputStream(tmpFile);
256:
257: for (int num = 1; num < chain.length; num++) {
258: X509Certificate tmpX509Cert = (X509Certificate) chain[num];
259: byte[] tmpOutput = tmpX509Cert.getEncoded();
260: out.write(beginCertificate);
261: out.write(NL);
262:
263: byte[] tmpCACertB64 = Base64.encode(tmpOutput);
264: out.write(tmpCACertB64);
265: out.write(NL);
266: out.write(endCertificate);
267: out.write(NL);
268: }
269:
270: out.close();
271: }
272: }
273:
274: // createPEM
275: }
276:
277: // P12toPEM
|