dev.dsf.tools.generator.CertificateGenerator Maven / Gradle / Ivy
The newest version!
package dev.dsf.tools.generator;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCSException;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Streams;
import de.rwh.utils.crypto.CertificateAuthority;
import de.rwh.utils.crypto.CertificateAuthority.CertificateAuthorityBuilder;
import de.rwh.utils.crypto.CertificateHelper;
import de.rwh.utils.crypto.CertificationRequestBuilder;
import de.rwh.utils.crypto.io.CsrIo;
import de.rwh.utils.crypto.io.PemIo;
public class CertificateGenerator
{
private static final Logger logger = LoggerFactory.getLogger(CertificateGenerator.class);
private static final char[] CERT_PASSWORD = "password".toCharArray();
private static final String[] SERVER_COMMON_NAMES = { "localhost", "keycloak" };
private static final String[] CLIENT_COMMON_NAMES = { "ttp-client", "dic1-client", "dic2-client", "dic3-client",
"test-client", "Webbrowser Test User" };
private static final Map> DNS_NAMES = Map.of("localhost",
Arrays.asList("localhost", "host.docker.internal", "fhir", "bpe", "ttp", "dic1", "dic2", "dic3"));
private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();
private enum CertificateType
{
CLIENT, SERVER
}
public static final class CertificateFiles
{
private final String commonName;
private final KeyPair keyPair;
private final X509Certificate certificate;
private final byte[] certificateSha512Thumbprint;
CertificateFiles(String commonName, KeyPair keyPair, X509Certificate certificate,
byte[] certificateSha512Thumbprint)
{
this.commonName = commonName;
this.keyPair = keyPair;
this.certificate = certificate;
this.certificateSha512Thumbprint = certificateSha512Thumbprint;
}
public String getCommonName()
{
return commonName;
}
public X509Certificate getCertificate()
{
return certificate;
}
public String getCertificateSha512ThumbprintHex()
{
return Hex.encodeHexString(certificateSha512Thumbprint);
}
}
private CertificateAuthority ca;
private Map serverCertificateFilesByCommonName;
private Map clientCertificateFilesByCommonName;
public void generateCertificates()
{
ca = initCA();
serverCertificateFilesByCommonName = Arrays.stream(SERVER_COMMON_NAMES)
.map(commonName -> createCert(CertificateType.SERVER, commonName,
DNS_NAMES.getOrDefault(commonName, Collections.singletonList(commonName))))
.collect(Collectors.toMap(CertificateFiles::getCommonName, Function.identity()));
clientCertificateFilesByCommonName = Arrays.stream(CLIENT_COMMON_NAMES)
.map(commonName -> createCert(CertificateType.CLIENT, commonName, Collections.emptyList()))
.collect(Collectors.toMap(CertificateFiles::getCommonName, Function.identity()));
writeThumbprints();
}
public Map getServerCertificateFilesByCommonName()
{
return serverCertificateFilesByCommonName != null
? Collections.unmodifiableMap(serverCertificateFilesByCommonName)
: Collections.emptyMap();
}
public Map getClientCertificateFilesByCommonName()
{
return clientCertificateFilesByCommonName != null
? Collections.unmodifiableMap(clientCertificateFilesByCommonName)
: Collections.emptyMap();
}
public CertificateAuthority initCA()
{
Path caCertFile = createFolderIfNotExists(Paths.get("cert/ca/testca_certificate.pem"));
Path caPrivateKeyFile = createFolderIfNotExists(Paths.get("cert/ca/testca_private-key.pem"));
if (Files.isReadable(caCertFile) && Files.isReadable(caPrivateKeyFile))
{
logger.info("Initializing CA from cert file: {}, private key {}", caCertFile.toString(),
caPrivateKeyFile.toString());
X509Certificate caCertificate = readCertificate(caCertFile);
PrivateKey caPrivateKey = readPrivatekey(caPrivateKeyFile);
return CertificateAuthorityBuilder.create(caCertificate, caPrivateKey).initialize();
}
else
{
logger.info("Initializing CA with new cert file: {}, private key {}", caCertFile.toString(),
caPrivateKeyFile.toString());
CertificateAuthority ca = CertificateAuthorityBuilder.create("DE", null, null, null, null, "Test")
.initialize();
writeCertificate(caCertFile, ca.getCertificate());
writePrivateKeyEncrypted(caPrivateKeyFile, ca.getCaKeyPair().getPrivate());
return ca;
}
}
private void writePrivateKeyEncrypted(Path privateKeyFile, PrivateKey privateKey)
{
try
{
PemIo.writeAes128EncryptedPrivateKeyToPkcs8(PROVIDER, privateKeyFile, privateKey, CERT_PASSWORD);
}
catch (IOException | OperatorCreationException e)
{
logger.error("Error while writing encrypted private-key to {}", privateKeyFile.toString(), e);
throw new RuntimeException(e);
}
}
private void writePrivateKeyNotEncrypted(Path privateKeyFile, PrivateKey privateKey)
{
try
{
PemIo.writeNotEncryptedPrivateKeyToPkcs8(PROVIDER, privateKeyFile, privateKey);
}
catch (IOException | OperatorCreationException e)
{
logger.error("Error while writing not-encrypted private-key to {}", privateKeyFile.toString(), e);
throw new RuntimeException(e);
}
}
private void writeCertificate(Path certificateFile, X509Certificate certificate)
{
try
{
PemIo.writeX509CertificateToPem(certificate, certificateFile);
}
catch (CertificateEncodingException | IllegalStateException | IOException e)
{
logger.error("Error while writing certificate to {}", certificateFile.toString(), e);
throw new RuntimeException(e);
}
}
private PrivateKey readPrivatekey(Path privateKeyFile)
{
try
{
return PemIo.readPrivateKeyFromPem(PROVIDER, privateKeyFile, CERT_PASSWORD);
}
catch (IOException | PKCSException e)
{
logger.error("Error while reading private-key from {}", privateKeyFile.toString(), e);
throw new RuntimeException(e);
}
}
private X509Certificate readCertificate(Path certFile)
{
try
{
return PemIo.readX509CertificateFromPem(certFile);
}
catch (CertificateException | IOException e)
{
logger.error("Error while reading certificate from {}", certFile.toString(), e);
throw new RuntimeException(e);
}
}
public void writeThumbprints()
{
Path thumbprintsFile = Paths.get("cert", "thumbprints.txt");
Stream certificates = Streams
.concat(serverCertificateFilesByCommonName.values().stream(),
clientCertificateFilesByCommonName.values().stream())
.sorted(Comparator.comparing(CertificateFiles::getCommonName))
.map(c -> c.commonName + "\n\t" + c.getCertificateSha512ThumbprintHex() + " (SHA-512)\n");
try
{
logger.info("Writing certificate thumbprints file to {}", thumbprintsFile.toString());
Files.write(thumbprintsFile, (Iterable) () -> certificates.iterator(), StandardCharsets.UTF_8);
}
catch (IOException e)
{
logger.error("Error while writing certificate thumbprints file to {}", thumbprintsFile.toString(), e);
throw new RuntimeException(e);
}
}
public CertificateFiles createCert(CertificateType certificateType, String commonName, List dnsNames)
{
Path privateKeyFile = createFolderIfNotExists(getPrivateKeyPath(commonName));
KeyPair keyPair = createOrReadKeyPair(privateKeyFile, commonName);
Path certificateRequestFile = createFolderIfNotExists(getCertReqPath(commonName));
JcaPKCS10CertificationRequest certificateRequest = createOrReadCertificateRequest(certificateRequestFile,
certificateType, keyPair, commonName, dnsNames);
Path certificatePemFile = createFolderIfNotExists(getCertPemPath(commonName));
X509Certificate certificate = signOrReadCertificate(certificatePemFile, certificateRequest, commonName,
certificateType);
return new CertificateFiles(commonName, keyPair, certificate,
calculateSha512CertificateThumbprint(certificate));
}
private X509Certificate signOrReadCertificate(Path certificateFile,
JcaPKCS10CertificationRequest certificateRequest, String commonName, CertificateType certificateType)
{
if (Files.isReadable(certificateFile))
{
logger.info("Reading certificate (pem) from {} [{}]", certificateFile.toString(), commonName);
return readCertificate(certificateFile);
}
else
{
logger.info("Signing {} certificate [{}]", certificateType.toString().toLowerCase(), commonName);
X509Certificate certificate = signCertificateRequest(certificateRequest, certificateType);
logger.info("Saving certificate (pem) to {} [{}]", certificateFile.toString(), commonName);
writeCertificate(certificateFile, certificate);
return certificate;
}
}
private X509Certificate signCertificateRequest(JcaPKCS10CertificationRequest certificateRequest,
CertificateType certificateType)
{
try
{
return switch (certificateType)
{
case CLIENT -> ca.signWebClientCertificate(certificateRequest);
case SERVER -> ca.signWebServerCertificate(certificateRequest);
};
}
catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | OperatorCreationException
| CertificateException | IllegalStateException | IOException e)
{
logger.error("Error while signing {} certificate", certificateType.toString().toLowerCase(), e);
throw new RuntimeException(e);
}
}
private JcaPKCS10CertificationRequest createOrReadCertificateRequest(Path certificateRequestFile,
CertificateType certificateType, KeyPair keyPair, String commonName, List dnsNames)
{
if (!dnsNames.contains(commonName) && CertificateType.SERVER.equals(certificateType))
throw new IllegalArgumentException("dnsNames must contain commonName if certificateType is SERVER");
if (Files.isReadable(certificateRequestFile))
{
logger.info("Reading certificate request (csr) from {} [{}]", certificateRequestFile.toString(),
commonName);
return readCertificateRequest(certificateRequestFile);
}
else
{
X500Name subject = CertificationRequestBuilder.createSubject("DE", null, null, null, null, commonName);
JcaPKCS10CertificationRequest certificateRequest = createCertificateRequest(certificateType, subject,
keyPair, dnsNames);
logger.info("Saving certificate request (csr) to {} [{}]", certificateRequestFile.toString(), commonName);
writeCertificateRequest(certificateRequestFile, certificateRequest);
return certificateRequest;
}
}
private JcaPKCS10CertificationRequest createCertificateRequest(CertificateType certificateType, X500Name subject,
KeyPair keyPair, List dnsNames)
{
try
{
return switch (certificateType)
{
case CLIENT -> CertificationRequestBuilder.createClientCertificationRequest(subject, keyPair);
case SERVER ->
CertificationRequestBuilder.createServerCertificationRequest(subject, keyPair, null, dnsNames);
};
}
catch (NoSuchAlgorithmException | OperatorCreationException | IllegalStateException | IOException e)
{
logger.error("Error while creating certificate-request", e);
throw new RuntimeException(e);
}
}
private void writeCertificateRequest(Path certificateRequestFile, JcaPKCS10CertificationRequest certificateRequest)
{
try
{
CsrIo.writeJcaPKCS10CertificationRequestToCsr(certificateRequest, certificateRequestFile);
}
catch (IOException e)
{
logger.error("Error while reading certificate-request from {}", certificateRequestFile.toString(), e);
throw new RuntimeException(e);
}
}
private JcaPKCS10CertificationRequest readCertificateRequest(Path certificateRequestFile)
{
try
{
return CsrIo.readJcaPKCS10CertificationRequestFromCsr(certificateRequestFile);
}
catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e)
{
logger.error("Error while reading certificate-request from {}", certificateRequestFile.toString(), e);
throw new RuntimeException(e);
}
}
private KeyPair createOrReadKeyPair(Path privateKeyFile, String commonName)
{
if (Files.isReadable(privateKeyFile))
{
logger.info("Reading private-key from {} [{}]", privateKeyFile.toString(), commonName);
PrivateKey privateKey = readPrivatekey(privateKeyFile);
PublicKey publicKey = createPublicKey(privateKey, privateKeyFile, commonName);
return new KeyPair(publicKey, privateKey);
}
else
{
logger.info("Generating 4096 bit key pair [{}]", commonName);
KeyPair keyPair = createKeyPair();
logger.info("Saving private-key to {} [{}]", privateKeyFile.toString(), commonName);
writePrivateKeyEncrypted(privateKeyFile, keyPair.getPrivate());
return keyPair;
}
}
private PublicKey createPublicKey(PrivateKey privateKey, Path privateKeyFile, String commonName)
{
logger.debug("Generating public-key from private-key [{}]", commonName);
if ("RSA".equals(privateKey.getAlgorithm()) && privateKey instanceof RSAPrivateCrtKey rsaPrivateKey)
{
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(rsaPrivateKey.getModulus(),
rsaPrivateKey.getPublicExponent());
try
{
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(publicKeySpec);
}
catch (NoSuchAlgorithmException | InvalidKeySpecException e)
{
throw new RuntimeException(
"Error while generating public key from private key modules and public exponent", e);
}
}
else
throw new RuntimeException("Error while generating public key: private key for " + commonName + " at "
+ privateKeyFile + " not a RSA private crt key");
}
private KeyPair createKeyPair()
{
try
{
return CertificationRequestBuilder.createRsaKeyPair4096Bit();
}
catch (NoSuchAlgorithmException e)
{
logger.error("Error while creating RSA key pair", e);
throw new RuntimeException(e);
}
}
private Path createFolderIfNotExists(Path file)
{
try
{
Files.createDirectories(file.getParent());
}
catch (IOException e)
{
logger.error("Error while creating directories {}", file.getParent().toString(), e);
throw new RuntimeException(e);
}
return file;
}
private Path getCertReqPath(String commonName)
{
commonName = commonName.replaceAll("\\s+", "_");
return Paths.get("cert", commonName, commonName + "_" + "certificate.csr");
}
private Path getCertP12Path(String commonName)
{
commonName = commonName.replaceAll("\\s+", "_");
return Paths.get("cert", commonName, commonName + "_" + "certificate.p12");
}
private Path getCertPemPath(String commonName)
{
commonName = commonName.replaceAll("\\s+", "_");
return Paths.get("cert", commonName, commonName + "_" + "certificate.pem");
}
private Path getPrivateKeyPath(String commonName)
{
commonName = commonName.replaceAll("\\s+", "_");
return Paths.get("cert", commonName, commonName + "_" + "private-key.pem");
}
private byte[] calculateSha512CertificateThumbprint(X509Certificate certificate)
{
try
{
return MessageDigest.getInstance("SHA-512").digest(certificate.getEncoded());
}
catch (CertificateEncodingException | NoSuchAlgorithmException e)
{
logger.error("Error while calculating SHA-512 certificate thumbprint", e);
throw new RuntimeException(e);
}
}
public void copyJavaTestCertificates()
{
X509Certificate testCaCertificate = ca.getCertificate();
Path bpeCaCertFile = Paths.get("../../dsf-bpe/dsf-bpe-server-jetty/target/testca_certificate.pem");
logger.info("Copying Test CA certificate file to {}", bpeCaCertFile.toString());
writeCertificate(bpeCaCertFile, testCaCertificate);
Path fhirCacertFile = Paths.get("../../dsf-fhir/dsf-fhir-server-jetty/target/testca_certificate.pem");
logger.info("Copying Test CA certificate file to {}", fhirCacertFile.toString());
writeCertificate(fhirCacertFile, testCaCertificate);
CertificateFiles localhost = serverCertificateFilesByCommonName.get("localhost");
Path bpeCertificateFile = Paths.get("../../dsf-bpe/dsf-bpe-server-jetty/target/localhost_certificate.pem");
logger.info("Copying localhost certificate file to {}", bpeCertificateFile.toString());
writeCertificate(bpeCertificateFile, localhost.certificate);
Path bpeCertificatePrivateKeyFile = Paths
.get("../../dsf-bpe/dsf-bpe-server-jetty/target/localhost_private-key.pem");
logger.info("Copying localhost certificate private-key file to {}", bpeCertificateFile.toString());
writePrivateKeyEncrypted(bpeCertificatePrivateKeyFile, localhost.keyPair.getPrivate());
Path fhirCertificateFile = Paths.get("../../dsf-fhir/dsf-fhir-server-jetty/target/localhost_certificate.pem");
logger.info("Copying localhost certificate file to {}", fhirCertificateFile.toString());
writeCertificate(fhirCertificateFile, localhost.certificate);
Path fhirCertificatePrivateKeyFile = Paths
.get("../../dsf-fhir/dsf-fhir-server-jetty/target/localhost_private-key.pem");
logger.info("Copying localhost certificate private-key file to {}", fhirCertificateFile.toString());
writePrivateKeyEncrypted(fhirCertificatePrivateKeyFile, localhost.keyPair.getPrivate());
CertificateFiles testClient = clientCertificateFilesByCommonName.get("test-client");
Path bpeClientCertificateFile = Paths
.get("../../dsf-bpe/dsf-bpe-server-jetty/target/test-client_certificate.pem");
logger.info("Copying test-client certificate file to {}", bpeClientCertificateFile);
writeCertificate(bpeClientCertificateFile, testClient.certificate);
Path bpeClientPrivateKeyFile = Paths
.get("../../dsf-bpe/dsf-bpe-server-jetty/target/test-client_private-key.pem");
logger.info("Copying test-client certificate private-key file to {}", bpeClientPrivateKeyFile);
writePrivateKeyEncrypted(bpeClientPrivateKeyFile, testClient.keyPair.getPrivate());
Path fhirClientCertificateFile = Paths
.get("../../dsf-fhir/dsf-fhir-server-jetty/target/test-client_certificate.pem");
logger.info("Copying test-client certificate file to {}", fhirClientCertificateFile);
writeCertificate(fhirClientCertificateFile, testClient.certificate);
Path fhirClientPrivateKeyFile = Paths
.get("../../dsf-fhir/dsf-fhir-server-jetty/target/test-client_private-key.pem");
logger.info("Copying test-client certificate private-key file to {}", fhirClientPrivateKeyFile);
writePrivateKeyEncrypted(fhirClientPrivateKeyFile, testClient.keyPair.getPrivate());
}
public void copyDockerTestCertificates()
{
copyProxyFiles("dsf-docker-test-setup", "localhost");
copyClientCertFiles("../../dsf-docker-test-setup/bpe/secrets/", "../../dsf-docker-test-setup/fhir/secrets/",
"test-client");
}
private void copyProxyFiles(String dockerTestFolder, String commonName)
{
X509Certificate testCaCertificate = ca.getCertificate();
CertificateFiles serverCertFiles = serverCertificateFilesByCommonName.get(commonName);
Path baseFolder = Paths.get("../../", dockerTestFolder);
Path bpeCertificateFile = baseFolder.resolve("bpe/secrets/server_certificate.pem");
logger.info("Copying {} certificate pem file to {}", commonName, bpeCertificateFile);
writeCertificate(bpeCertificateFile, serverCertFiles.getCertificate());
Path bpeCertificatePrivateKeyFile = baseFolder.resolve("bpe/secrets/server_certificate_private_key.pem");
logger.info("Copying {} private-key file to {}", commonName, bpeCertificatePrivateKeyFile);
writePrivateKeyNotEncrypted(bpeCertificatePrivateKeyFile, serverCertFiles.keyPair.getPrivate());
Path bpeTestCaCertificate = baseFolder.resolve("bpe/secrets/testca_certificate.pem");
logger.info("Copying Test CA certificate file to {}", bpeTestCaCertificate.toString());
writeCertificate(bpeTestCaCertificate, testCaCertificate);
Path fhirCertificateFile = baseFolder.resolve("fhir/secrets/server_certificate.pem");
logger.info("Copying {} certificate pem file to {}", commonName, fhirCertificateFile);
writeCertificate(fhirCertificateFile, serverCertFiles.getCertificate());
Path fhirCertificatePrivateKeyFile = baseFolder.resolve("fhir/secrets/server_certificate_private_key.pem");
logger.info("Copying {} private-key file to {}", commonName, fhirCertificatePrivateKeyFile);
writePrivateKeyNotEncrypted(fhirCertificatePrivateKeyFile, serverCertFiles.keyPair.getPrivate());
Path fhirTestCaCertificate = baseFolder.resolve("fhir/secrets/testca_certificate.pem");
logger.info("Copying Test CA certificate file to {}", fhirTestCaCertificate.toString());
writeCertificate(fhirTestCaCertificate, testCaCertificate);
}
private void copyClientCertFiles(String bpeConfFolder, String fhirConfFolder, String commonName)
{
final CertificateFiles clientCertFiles = clientCertificateFilesByCommonName.get(commonName);
Path bpeClientCertificateFile = Paths.get(bpeConfFolder, "client_certificate.pem");
logger.info("Copying {} certificate certificate file to {}", commonName, bpeClientCertificateFile);
writeCertificate(bpeClientCertificateFile, clientCertFiles.certificate);
Path bpeClientPrivateKeyFile = Paths.get(bpeConfFolder, "client_certificate_private_key.pem");
logger.info("Copying {} certificate private-key file to {}", commonName, bpeClientPrivateKeyFile);
writePrivateKeyEncrypted(bpeClientPrivateKeyFile, clientCertFiles.keyPair.getPrivate());
Path fhirClientCertificateFile = Paths.get(fhirConfFolder, "client_certificate.pem");
logger.info("Copying {} certificate certificate file to {}", commonName, fhirClientCertificateFile);
writeCertificate(fhirClientCertificateFile, clientCertFiles.certificate);
Path fhirClientPrivateKeyFile = Paths.get(fhirConfFolder, "client_certificate_private_key.pem");
logger.info("Copying {} certificate private-key file to {}", commonName, fhirClientPrivateKeyFile);
writePrivateKeyEncrypted(fhirClientPrivateKeyFile, clientCertFiles.keyPair.getPrivate());
}
public void copyDockerTest3DicTtpCertificates()
{
Path baseFolder = Paths.get("../../dsf-docker-test-setup-3dic-ttp/secrets/");
final X509Certificate testCaCertificate = ca.getCertificate();
Path testCaCertificateFile = baseFolder.resolve("proxy_trusted_client_cas.pem");
logger.info("Copying Test CA certificate file to {}", testCaCertificateFile.toString());
writeCertificate(testCaCertificateFile, testCaCertificate);
CertificateFiles localhost = serverCertificateFilesByCommonName.get("localhost");
Path localhostCertificateAndCa = baseFolder.resolve("proxy_certificate_and_int_cas.pem");
logger.info("Writing localhost certificate and CA certificate to {}", testCaCertificateFile.toString());
writeCertificates(localhostCertificateAndCa, localhost.getCertificate()); // no intermediate CAs
Path localhostCertificatePrivateKey = baseFolder.resolve("proxy_certificate_private_key.pem");
logger.info("Copying localhost private-key file to {}", localhostCertificatePrivateKey);
writePrivateKeyNotEncrypted(localhostCertificatePrivateKey, localhost.keyPair.getPrivate());
List commonNames = Arrays.asList("dic1", "dic2", "dic3", "ttp");
commonNames.forEach(cn -> copyDockerTest3DicTtpClientCertFiles("../../dsf-docker-test-setup-3dic-ttp/secrets/",
cn + "-client"));
Path fhirCacertFile = baseFolder.resolve("app_testca_certificate.pem");
logger.info("Copying Test CA certificate file to {}", fhirCacertFile.toString());
writeCertificate(fhirCacertFile, testCaCertificate);
CertificateFiles keycloak = serverCertificateFilesByCommonName.get("keycloak");
Path keycloakCertificateAndCa = baseFolder.resolve("keycloak_certificate_and_int_cas.pem");
logger.info("Writing keycloak certificate and CA certificate to {}", testCaCertificateFile.toString());
writeCertificates(keycloakCertificateAndCa, keycloak.getCertificate()); // no intermediate CAs
Path keycloakCertificatePrivateKey = baseFolder.resolve("keycloak_certificate_private_key.pem");
logger.info("Copying keycloak private-key file to {}", keycloakCertificatePrivateKey);
writePrivateKeyNotEncrypted(keycloakCertificatePrivateKey, keycloak.keyPair.getPrivate());
Path keycloakTrustStoreFile = baseFolder.resolve("keycloak_trust_store.jks");
logger.info("Copying Test CA certificate as trust store file to {}", keycloakTrustStoreFile.toString());
KeyStore trustStore = createJksKeyStore(getCommonName(ca.getCertificate()), testCaCertificate);
writeKeyStore(keycloakTrustStoreFile, trustStore);
}
private String getCommonName(X509Certificate certificate)
{
try
{
return IETFUtils.valueToString(new JcaX509CertificateHolder(certificate).getSubject().getRDNs(BCStyle.CN)[0]
.getFirst().getValue());
}
catch (CertificateEncodingException e)
{
logger.error("Error unable to extract common-name from certificate", e);
throw new RuntimeException(e);
}
}
private void copyDockerTest3DicTtpClientCertFiles(String folder, String commonName)
{
final CertificateFiles clientCertFiles = clientCertificateFilesByCommonName.get(commonName);
Path bpeClientCertificateFile = Paths.get(folder, "app_" + commonName + "_certificate.pem");
logger.info("Copying {} certificate certificate file to {}", commonName, bpeClientCertificateFile);
writeCertificate(bpeClientCertificateFile, clientCertFiles.certificate);
Path bpeClientPrivateKeyFile = Paths.get(folder, "app_" + commonName + "_private-key.pem");
logger.info("Copying {} certificate private-key file to {}", commonName, bpeClientPrivateKeyFile);
writePrivateKeyEncrypted(bpeClientPrivateKeyFile, clientCertFiles.keyPair.getPrivate());
}
private void writeCertificates(Path certificateFile, X509Certificate... certificates)
{
try
{
StringBuilder b = new StringBuilder();
for (X509Certificate cert : certificates)
{
b.append("subject= ");
b.append(cert.getSubjectX500Principal().getName());
b.append("\n");
b.append(PemIo.writeX509Certificate(cert));
}
Files.writeString(certificateFile, b.toString());
}
catch (CertificateEncodingException | IllegalStateException | IOException e)
{
logger.error("Error while writing certificate to {}", certificateFile.toString(), e);
throw new RuntimeException(e);
}
}
private KeyStore createJksKeyStore(String commonName, X509Certificate certificate)
{
try
{
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(null, null);
keyStore.setCertificateEntry(commonName, certificate);
return keyStore;
}
catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e)
{
logger.error("Error while creating jks key-store", e);
throw new RuntimeException(e);
}
}
private KeyStore createP12KeyStore(PrivateKey privateKey, String commonName, X509Certificate certificate)
{
try
{
return CertificateHelper.toPkcs12KeyStore(privateKey,
new Certificate[] { certificate, ca.getCertificate() }, commonName, CERT_PASSWORD);
}
catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IllegalStateException
| IOException e)
{
logger.error("Error while creating P12 key-store", e);
throw new RuntimeException(e);
}
}
private void writeKeyStore(Path file, KeyStore keyStore)
{
try (OutputStream stream = Files.newOutputStream(file))
{
keyStore.store(stream, CERT_PASSWORD);
}
catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e)
{
logger.error("Error while writing keystore file to {}", file.toString(), e);
throw new RuntimeException(e);
}
}
public Path createP12(CertificateFiles files)
{
Path certP12Path = getCertP12Path(files.commonName);
logger.info("Saving certificate (p21) to {}, password '{}' [{}]", certP12Path.toString(),
String.valueOf(CERT_PASSWORD), files.commonName);
KeyStore p12KeyStore = createP12KeyStore(files.keyPair.getPrivate(), files.commonName, files.certificate);
writeKeyStore(certP12Path, p12KeyStore);
return certP12Path;
}
public static void main(String[] args)
{
CertificateAuthority.registerBouncyCastleProvider();
new CertificateGenerator().generateCertificates();
}
}