| /* | |
| * Copyright 2011 gitblit.com. | |
| * | |
| * 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 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; | |
| import com.gitblit.utils.TimeUtils; | |
| /** | |
| * Utility class to generate self-signed certificates. | |
| * | |
| * @author James Moger | |
| * | |
| */ | |
| public class MakeCertificate { | |
| 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.NAME); | |
| builder.addRDN(BCStyle.O, Constants.NAME); | |
| builder.addRDN(BCStyle.CN, hostname); | |
| Date notBefore = new Date(System.currentTimeMillis() - TimeUtils.ONEDAY); | |
| Date notAfter = new Date(System.currentTimeMillis() + 10 * TimeUtils.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() - TimeUtils.ONEDAY); | |
| Date notAfter = new Date(System.currentTimeMillis() + 10 * TimeUtils.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 { | |
| private static final FileSettings FILESETTINGS = new FileSettings(Constants.PROPERTIES_FILE); | |
| @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.") | |
| public String storePassword = FILESETTINGS.getString(Keys.server.storePassword, ""); | |
| } | |
| } |