X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fruntime%2FPkiUtils.java;h=5bf62e3aab9be2064282681f58fbc8a0e8485321;hb=d38892dfeb706f58e8daf89c7d60fc7d2f6c7339;hp=474a8995061040ca824a0b54fd8d373af54403db;hpb=f4da6777015da3fc392138f0c01cea2f2add9ed3;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java index 474a89950..5bf62e3aa 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java @@ -5,12 +5,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.math.BigInteger; +import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; +import java.security.KeyStore.TrustedCertificateEntry; import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.SecureRandom; @@ -18,10 +20,13 @@ import java.security.Security; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Date; import javax.security.auth.x500.X500Principal; +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsLog; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; @@ -43,18 +48,37 @@ import org.bouncycastle.pkcs.PKCSException; * implementations. */ class PkiUtils { + private final static CmsLog log = CmsLog.getLog(PkiUtils.class); + final static String PKCS12 = "PKCS12"; + final static String JKS = "JKS"; + + static final String DEFAULT_KEYSTORE_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".p12"; + + static final String DEFAULT_TRUSTSTORE_PATH = KernelConstants.DIR_NODE + "/trusted.p12"; + + static final String DEFAULT_PEM_KEY_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".key"; - private final static String SECURITY_PROVIDER; + static final String DEFAULT_PEM_CERT_PATH = KernelConstants.DIR_NODE + '/' + CmsConstants.NODE + ".crt"; + + static final String IPA_PEM_CA_CERT_PATH = "/etc/ipa/ca.crt"; + + static final String DEFAULT_KEYSTORE_PASSWORD = "changeit"; + + private final static String SUN_SECURITY_PROVIDER; + private final static String BC_SECURITY_PROVIDER; static { Security.addProvider(new BouncyCastleProvider()); - SECURITY_PROVIDER = "BC"; + // BouncyCastle does not store trusted certificates properly + // TODO report it + BC_SECURITY_PROVIDER = "BC"; + SUN_SECURITY_PROVIDER = "SUN"; } public static X509Certificate generateSelfSignedCertificate(KeyStore keyStore, X500Principal x500Principal, int keySize, char[] keyPassword) { try { - KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER); + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", BC_SECURITY_PROVIDER); kpGen.initialize(keySize, new SecureRandom()); KeyPair pair = kpGen.generateKeyPair(); Date notBefore = new Date(System.currentTimeMillis() - 10000); @@ -62,9 +86,9 @@ class PkiUtils { 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) + ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption") + .setProvider(BC_SECURITY_PROVIDER).build(pair.getPrivate()); + X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC_SECURITY_PROVIDER) .getCertificate(certGen.build(sigGen)); cert.checkValidity(new Date()); cert.verify(cert.getPublicKey()); @@ -78,7 +102,7 @@ class PkiUtils { public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) { try { - KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER); + KeyStore store = KeyStore.getInstance(keyStoreType, "SunJSSE"); if (Files.exists(keyStoreFile)) { try (InputStream fis = Files.newInputStream(keyStoreFile)) { store.load(fis, keyStorePassword); @@ -139,11 +163,16 @@ class PkiUtils { // } public static void loadPem(KeyStore keyStore, Reader key, char[] keyPassword, Reader cert) { - PrivateKey privateKey = loadPemPrivateKey(key, keyPassword); - X509Certificate certificate = loadPemCertificate(cert); try { - keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword, - new java.security.cert.Certificate[] { certificate }); + X509Certificate certificate = loadPemCertificate(cert); + if (key != null) { + PrivateKey privateKey = loadPemPrivateKey(key, keyPassword); + keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword, + new java.security.cert.Certificate[] { certificate }); + } else { + TrustedCertificateEntry trustedCertificateEntry = new TrustedCertificateEntry(certificate); + keyStore.setEntry(certificate.getSubjectX500Principal().getName(), trustedCertificateEntry, null); + } } catch (KeyStoreException e) { throw new RuntimeException("Cannot store PEM certificate", e); } @@ -151,7 +180,7 @@ class PkiUtils { public static PrivateKey loadPemPrivateKey(Reader reader, char[] keyPassword) { try (PEMParser pemParser = new PEMParser(reader)) { - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider(BC_SECURITY_PROVIDER); Object object = pemParser.readObject(); PrivateKeyInfo privateKeyInfo; if (object instanceof PKCS8EncryptedPrivateKeyInfo) { @@ -173,7 +202,7 @@ class PkiUtils { public static X509Certificate loadPemCertificate(Reader reader) { try (PEMParser pemParser = new PEMParser(reader)) { X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject(); - X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) + X509Certificate cert = new JcaX509CertificateConverter().setProvider(SUN_SECURITY_PROVIDER) .getCertificate(certHolder); return cert; } catch (IOException | CertificateException e) { @@ -256,4 +285,33 @@ class PkiUtils { } + public static void createSelfSignedKeyStore(Path keyStorePath, char[] keyStorePassword, String keyStoreType) { + // for (Provider provider : Security.getProviders()) + // System.out.println(provider.getName()); + // File keyStoreFile = keyStorePath.toFile(); + char[] keyPwd = Arrays.copyOf(keyStorePassword, keyStorePassword.length); + if (!Files.exists(keyStorePath)) { + try { + Files.createDirectories(keyStorePath.getParent()); + KeyStore keyStore = getKeyStore(keyStorePath, keyStorePassword, keyStoreType); + generateSelfSignedCertificate(keyStore, + new X500Principal("CN=" + InetAddress.getLocalHost().getHostName() + ",OU=UNSECURE,O=UNSECURE"), + 1024, keyPwd); + saveKeyStore(keyStorePath, keyStorePassword, keyStore); + if (log.isDebugEnabled()) + log.debug("Created self-signed unsecure keystore " + keyStorePath); + } catch (Exception e) { + try { + if (Files.size(keyStorePath) == 0) + Files.delete(keyStorePath); + } catch (IOException e1) { + // silent + } + log.error("Cannot create keystore " + keyStorePath, e); + } + } else { + throw new IllegalStateException("Keystore " + keyStorePath + " already exists"); + } + } + }