--- /dev/null
+package org.argeo.security.crypto;
+
+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.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.argeo.ArgeoException;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
+/**
+ * Utilities around private keys and certificate, mostly wrapping BouncyCastle
+ * implementations.
+ */
+public class PkiUtils {
+ private final static String SECURITY_PROVIDER;
+ static {
+ Security.addProvider(new BouncyCastleProvider());
+ SECURITY_PROVIDER = "BC";
+ }
+
+ public static X509Certificate generateSelfSignedCertificate(
+ KeyStore keyStore, X500Principal x500Principal, char[] keyPassword) {
+ try {
+ KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA",
+ SECURITY_PROVIDER);
+ kpGen.initialize(1024, new SecureRandom());
+ KeyPair pair = kpGen.generateKeyPair();
+ Date notBefore = new Date(System.currentTimeMillis() - 10000);
+ Date notAfter = new Date(
+ System.currentTimeMillis() + 24L * 3600 * 1000);
+ BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());
+ X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
+ x500Principal, serial, notBefore, notAfter, x500Principal,
+ pair.getPublic());
+ ContentSigner sigGen = new JcaContentSignerBuilder(
+ "SHA256WithRSAEncryption").setProvider(SECURITY_PROVIDER)
+ .build(pair.getPrivate());
+ X509Certificate cert = new JcaX509CertificateConverter()
+ .setProvider(SECURITY_PROVIDER).getCertificate(
+ certGen.build(sigGen));
+ cert.checkValidity(new Date());
+ cert.verify(cert.getPublicKey());
+
+ keyStore.setKeyEntry(x500Principal.getName(), pair.getPrivate(),
+ keyPassword, new Certificate[] { cert });
+ return cert;
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot generate self-signed certificate",
+ e);
+ }
+ }
+
+ public static KeyStore getKeyStore(File keyStoreFile,
+ char[] keyStorePassword) {
+ try {
+ KeyStore store = KeyStore.getInstance("PKCS12", SECURITY_PROVIDER);
+ if (keyStoreFile.exists()) {
+ try (FileInputStream fis = new FileInputStream(keyStoreFile)) {
+ store.load(fis, keyStorePassword);
+ }
+ } else {
+ store.load(null);
+ }
+ return store;
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot load keystore " + keyStoreFile, e);
+ }
+ }
+
+ public static void saveKeyStore(File keyStoreFile, char[] keyStorePassword,
+ KeyStore keyStore) {
+ try {
+ try (FileOutputStream fis = new FileOutputStream(keyStoreFile)) {
+ keyStore.store(fis, keyStorePassword);
+ }
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot save keystore " + keyStoreFile, e);
+ }
+ }
+
+}