From a9299738a991014788b72db7c9afc946633590e2 Mon Sep 17 00:00:00 2001 From: James Moger Date: Sun, 22 May 2011 13:45:20 -0400 Subject: [PATCH] Make keystore script independent of JDK using BouncyCastle. --- distrib/makekeystore.cmd | 2 +- src/com/gitblit/GitBlitServer.java | 61 +----------- src/com/gitblit/MakeCertificate.java | 140 +++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 61 deletions(-) create mode 100644 src/com/gitblit/MakeCertificate.java diff --git a/distrib/makekeystore.cmd b/distrib/makekeystore.cmd index 34a11b21..b2206efb 100644 --- a/distrib/makekeystore.cmd +++ b/distrib/makekeystore.cmd @@ -1,2 +1,2 @@ @del keystore -@keytool -keystore keystore -alias localhost -genkey -keyalg RSA -dname "CN=localhost, OU=Git:Blit, O=Git:Blit, L=Some Town, ST=Some State, C=US" \ No newline at end of file +@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.MakeCertificate --alias localhost --subject "CN=localhost, OU=Git:Blit, O=Git:Blit, L=Some Town, ST=Some State, C=US" diff --git a/src/com/gitblit/GitBlitServer.java b/src/com/gitblit/GitBlitServer.java index 17b9e7a0..08c9b297 100644 --- a/src/com/gitblit/GitBlitServer.java +++ b/src/com/gitblit/GitBlitServer.java @@ -2,40 +2,23 @@ package com.gitblit; import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; -import java.math.BigInteger; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; import java.net.UnknownHostException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; import java.security.ProtectionDomain; -import java.security.SecureRandom; -import java.security.Security; -import java.security.cert.X509Certificate; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Date; import java.util.List; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.PatternLayout; import org.apache.wicket.protocol.http.ContextParamWebApplicationFactory; import org.apache.wicket.protocol.http.WicketFilter; -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 org.eclipse.jetty.http.security.Constraint; import org.eclipse.jetty.security.ConstraintMapping; import org.eclipse.jetty.security.ConstraintSecurityHandler; @@ -170,7 +153,7 @@ public class GitBlitServer { File keystore = new File("keystore"); if (!keystore.exists()) { logger.info("Generating self-signed SSL certificate"); - generateSelfSignedCertificate("localhost", keystore, params.storePassword); + MakeCertificate.generateSelfSignedCertificate("localhost", keystore, params.storePassword); } if (keystore.exists()) { Connector secureConnector = createSSLConnector(keystore, params.storePassword, params.useNIO, params.securePort); @@ -336,48 +319,6 @@ public class GitBlitServer { return connector; } - private static void generateSelfSignedCertificate(String hostname, File keystore, String keystorePassword) { - try { - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - - final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; - - 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.NAME); - builder.addRDN(BCStyle.O, Constants.NAME); - builder.addRDN(BCStyle.CN, hostname); - - Date notBefore = new Date(System.currentTimeMillis() - 1*24*60*60*1000l); - Date notAfter = new Date(System.currentTimeMillis() + 10*365*24*60*60*1000l); - 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()); - } else { - store.load(null); - } - store.setKeyEntry(hostname, pair.getPrivate(), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { cert }); - store.store(new FileOutputStream(keystore), keystorePassword.toCharArray()); - } catch (Throwable t) { - t.printStackTrace(); - throw new RuntimeException("Failed to generate self-signed certificate!", t); - } - } - /** * Recursively delete a folder and its contents. * diff --git a/src/com/gitblit/MakeCertificate.java b/src/com/gitblit/MakeCertificate.java new file mode 100644 index 00000000..e8ac6d60 --- /dev/null +++ b/src/com/gitblit/MakeCertificate.java @@ -0,0 +1,140 @@ +package com.gitblit; + +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; + +public class MakeCertificate { + + private final static FileSettings fileSettings = new FileSettings(); + + public static void main(String... args) { + Params params = new Params(); + JCommander jc = new JCommander(params); + try { + jc.parse(args); + } catch (ParameterException t) { + jc.usage(); + } + File keystore = new File("keystore"); + generateSelfSignedCertificate(params.alias, keystore, params.storePassword, params.subject); + } + + public static void generateSelfSignedCertificate(String hostname, File keystore, String keystorePassword) { + try { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + + final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; + + 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.NAME); + builder.addRDN(BCStyle.O, Constants.NAME); + builder.addRDN(BCStyle.CN, hostname); + + Date notBefore = new Date(System.currentTimeMillis() - 1*24*60*60*1000l); + Date notAfter = new Date(System.currentTimeMillis() + 10*365*24*60*60*1000l); + 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()); + } else { + store.load(null); + } + store.setKeyEntry(hostname, pair.getPrivate(), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { cert }); + store.store(new FileOutputStream(keystore), keystorePassword.toCharArray()); + } 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()); + + final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME; + + 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() - 1*24*60*60*1000l); + Date notAfter = new Date(System.currentTimeMillis() + 10*365*24*60*60*1000l); + 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()); + } else { + store.load(null); + } + store.setKeyEntry(hostname, pair.getPrivate(), keystorePassword.toCharArray(), new java.security.cert.Certificate[] { cert }); + store.store(new FileOutputStream(keystore), keystorePassword.toCharArray()); + } catch (Throwable t) { + t.printStackTrace(); + throw new RuntimeException("Failed to generate self-signed certificate!", t); + } + } + + @Parameters(separators = " ") + private static class Params { + + @Parameter(names = { "--alias" }, description = "Server alias", required = true) + public String alias = null; + + @Parameter(names = { "--subject" }, description = "Certificate subject", required = true) + public String subject = null; + + + @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.") + public String storePassword = fileSettings.getString(Keys.server.storePassword, ""); + } +} -- 2.39.5