/* * Copyright 2012 James Moger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.moxie.proxy; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.SecureRandom; import java.security.Security; import java.security.cert.X509Certificate; import java.util.Date; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; /** * Utility class to generate self-signed certificates. * * @author James Moger * */ public class MakeCertificate { private static final long MIN = 1000 * 60L; private static final long HALFHOUR = MIN * 30L; private static final long ONEHOUR = HALFHOUR * 2; private static final long ONEDAY = ONEHOUR * 24L; private static final long ONEYEAR = ONEDAY * 365L; private static final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; public static void main(String... args) { Params params = new Params(); JCommander jc = new JCommander(params); try { jc.parse(args); } catch (ParameterException t) { System.err.println(t.getMessage()); jc.usage(); } File keystore = new File("keystore"); generateSelfSignedCertificate(params.hostname, keystore, params.storePassword, params.subject); } public static void generateSelfSignedCertificate(String hostname, File keystore, String keystorePassword) { try { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC"); kpGen.initialize(1024, new SecureRandom()); KeyPair pair = kpGen.generateKeyPair(); // Generate self-signed certificate X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE); builder.addRDN(BCStyle.OU, Constants.getName()); builder.addRDN(BCStyle.O, Constants.getName()); builder.addRDN(BCStyle.CN, hostname); Date notBefore = new Date(System.currentTimeMillis() - ONEDAY); Date notAfter = new Date(System.currentTimeMillis() + 10 * ONEYEAR); BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(), serial, notBefore, notAfter, builder.build(), pair.getPublic()); ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption") .setProvider(BC).build(pair.getPrivate()); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) .getCertificate(certGen.build(sigGen)); cert.checkValidity(new Date()); cert.verify(cert.getPublicKey()); // Save to keystore KeyStore store = KeyStore.getInstance("JKS"); if (keystore.exists()) { FileInputStream fis = new FileInputStream(keystore); store.load(fis, keystorePassword.toCharArray()); fis.close(); } else { store.load(null); } store.setKeyEntry(hostname, pair.getPrivate(), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { cert }); FileOutputStream fos = new FileOutputStream(keystore); store.store(fos, keystorePassword.toCharArray()); fos.close(); } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException("Failed to generate self-signed certificate!", t); } } public static void generateSelfSignedCertificate(String hostname, File keystore, String keystorePassword, String info) { try { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC"); kpGen.initialize(1024, new SecureRandom()); KeyPair pair = kpGen.generateKeyPair(); // Generate self-signed certificate X500Principal principal = new X500Principal(info); Date notBefore = new Date(System.currentTimeMillis() - ONEDAY); Date notAfter = new Date(System.currentTimeMillis() + 10 * ONEYEAR); BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(principal, serial, notBefore, notAfter, principal, pair.getPublic()); ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption") .setProvider(BC).build(pair.getPrivate()); X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC) .getCertificate(certGen.build(sigGen)); cert.checkValidity(new Date()); cert.verify(cert.getPublicKey()); // Save to keystore KeyStore store = KeyStore.getInstance("JKS"); if (keystore.exists()) { FileInputStream fis = new FileInputStream(keystore); store.load(fis, keystorePassword.toCharArray()); fis.close(); } else { store.load(null); } store.setKeyEntry(hostname, pair.getPrivate(), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { cert }); FileOutputStream fos = new FileOutputStream(keystore); store.store(fos, keystorePassword.toCharArray()); fos.close(); } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException("Failed to generate self-signed certificate!", t); } } /** * JCommander Parameters class for MakeCertificate. */ @Parameters(separators = " ") private static class Params { @Parameter(names = { "--hostname" }, description = "Server Hostname", required = true) public String hostname; @Parameter(names = { "--subject" }, description = "Certificate subject", required = true) public String subject; @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.", required = true) public String storePassword; } }