package org.digidoc4j.main; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.UUID; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.IOUtils; import eu.europa.esig.dss.DSSUtils; import eu.europa.esig.dss.DigestAlgorithm; import eu.europa.esig.dss.x509.CertificateToken; /** * Utility to generate keystore. */ public class KeystoreGenerator { private static final String DEFAULT_KEYSTORE_CERTIFICATES_FILEPATH = "keystore/keystore_certs"; private static final String DEFAULT_KEYSTORE_FILEPATH = "keystore/keystore.jks"; private static final String DEFAULT_KEYSTORE_PASSWORD = "digidoc4j-password"; private static final String DEFAULT_KEYSTORE_TYPE = "JKS"; private static final String TEST_KEYSTORE_CERTIFICATES_FILEPATH = "keystore/test_keystore_certs/"; private static final String TEST_KEYSTORE_FILEPATH = "keystore/test-keystore.jks"; private String keyStoreCertificateFilepath; private String keyStoreFilepath; private String keyStorePassword; public static void main(String[] args) { try { KeystoreGenerator.aGenerator() .withCertificateDirectory(TEST_KEYSTORE_CERTIFICATES_FILEPATH) .withKeyStoreFilepath(TEST_KEYSTORE_FILEPATH) .generateKeystore(); } catch (CertificateException | NoSuchAlgorithmException | IOException | KeyStoreException e) { e.printStackTrace(); } } private KeystoreGenerator() {}; public static KeystoreGenerator aGenerator() { return new KeystoreGenerator(); } public KeystoreGenerator withCertificateDirectory(String keyStoreCertificateFilepath) { this.keyStoreCertificateFilepath = keyStoreCertificateFilepath; return this; } public KeystoreGenerator withKeyStoreFilepath(String keyStoreFilepath) { this.keyStoreFilepath = keyStoreFilepath; return this; } public KeystoreGenerator withKeyStorePassword(String keyStorePassword) { this.keyStorePassword = keyStorePassword; return this; } /** * Generate a keystore with default options. * @throws CertificateException * @throws NoSuchAlgorithmException * @throws KeyStoreException * @throws IOException */ public void generateKeystore() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { keyStoreFilepath = keyStoreFilepath == null ? DEFAULT_KEYSTORE_FILEPATH : keyStoreFilepath; keyStoreCertificateFilepath = keyStoreCertificateFilepath == null ? DEFAULT_KEYSTORE_CERTIFICATES_FILEPATH : keyStoreCertificateFilepath; keyStorePassword = keyStorePassword == null ? DEFAULT_KEYSTORE_PASSWORD : keyStorePassword; generateKeystore(keyStoreCertificateFilepath, keyStoreFilepath, keyStorePassword); } /** * Generates a java.security.KeyStore on the specified path, filled with certificates from the specified path and * protected with the specified password. * @param keyStoreCertsFilepath Path to directory that holds necessary certificates. * @param keyStoreFilepath Path where to create the Keystore. * @param keyStorePassword Keystore Password. * @throws CertificateException * @throws NoSuchAlgorithmException * @throws KeyStoreException * @throws IOException */ private void generateKeystore(String keyStoreCertsFilepath, String keyStoreFilepath, String keyStorePassword) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { createKeystore(keyStoreFilepath, keyStorePassword); KeyStore store = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); store.load(new FileInputStream(keyStoreFilepath), keyStorePassword.toCharArray()); OutputStream fos = new FileOutputStream(keyStoreFilepath); File dir = new File(keyStoreCertsFilepath); File[] directoryListing = dir.listFiles(); if (directoryListing != null) { for (File child : directoryListing) { addCertificate(store, child.getPath()); } store.store(fos, keyStorePassword.toCharArray()); IOUtils.closeQuietly(fos); readKeyStore(keyStoreFilepath, keyStorePassword); } else { System.out.println("No certificates found!"); } } private void addCertificate(KeyStore store, String filepath) throws KeyStoreException, FileNotFoundException { InputStream fis = new FileInputStream(filepath); CertificateToken europanCert = DSSUtils.loadCertificate(fis); System.out.println("Adding certificate " + filepath); displayCertificateDigests(europanCert); store.setCertificateEntry(UUID.randomUUID().toString(), europanCert.getCertificate()); IOUtils.closeQuietly(fis); } private void displayCertificateDigests(CertificateToken europanCert) { byte[] digestSHA256 = DSSUtils.digest(DigestAlgorithm.SHA256, europanCert.getEncoded()); byte[] digestSHA1 = DSSUtils.digest(DigestAlgorithm.SHA1, europanCert.getEncoded()); System.out.println("SHA256 digest (Hex) : " + getPrintableHex(digestSHA256)); System.out.println("SHA1 digest (Hex) : " + getPrintableHex(digestSHA1)); System.out.println("SHA256 digest (Base64) : " + Base64.encodeBase64String(digestSHA256)); System.out.println("SHA1 digest (Base64) : " + Base64.encodeBase64String(digestSHA1)); } private String getPrintableHex(byte[] digest) { String hexString = Hex.encodeHexString(digest); // Add space every two characters return hexString.replaceAll("..", "$0 "); } private void readKeyStore(String keyStoreFilepath, String keyStorePassword) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException { InputStream fis = new FileInputStream(keyStoreFilepath); KeyStore store = KeyStore.getInstance("JKS"); store.load(fis, keyStorePassword.toCharArray()); Enumeration<String> aliases = store.aliases(); while (aliases.hasMoreElements()) { final String alias = aliases.nextElement(); if (store.isCertificateEntry(alias)) { Certificate certificate = store.getCertificate(alias); CertificateToken certificateToken = DSSUtils.loadCertificate(certificate.getEncoded()); System.out.println(certificateToken); } } IOUtils.closeQuietly(fis); } private void createKeystore(String keyStoreFilepath, String keyStorePassword) throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException { KeyStore trustStore = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); trustStore.load(null, keyStorePassword.toCharArray()); Path pathToKeystore = Paths.get(keyStoreFilepath); pathToKeystore.getParent().toFile().mkdirs(); OutputStream fos = new FileOutputStream(keyStoreFilepath); trustStore.store(fos, keyStorePassword.toCharArray()); IOUtils.closeQuietly(fos); } }