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;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.util.Arrays;
import java.util.Date;
+import java.util.Objects;
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;
* 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_PRIVATE + '/' + CmsConstants.NODE + ".p12";
+
+ static final String DEFAULT_TRUSTSTORE_PATH = KernelConstants.DIR_PRIVATE + "/trusted.p12";
+
+ static final String DEFAULT_PEM_KEY_PATH = KernelConstants.DIR_PRIVATE + '/' + CmsConstants.NODE + ".key";
+
+ static final String DEFAULT_PEM_CERT_PATH = KernelConstants.DIR_PRIVATE + '/' + CmsConstants.NODE + ".crt";
- private final static String SECURITY_PROVIDER;
+ 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 SUN_JSSE_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";
+ SUN_JSSE_SECURITY_PROVIDER = "SunJSSE";
}
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);
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());
public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) {
try {
- KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER);
+ KeyStore store = KeyStore.getInstance(keyStoreType, SUN_JSSE_SECURITY_PROVIDER);
if (Files.exists(keyStoreFile)) {
try (InputStream fis = Files.newInputStream(keyStoreFile)) {
store.load(fis, keyStorePassword);
// return bos.toByteArray();
// }
- public static void loadPem(KeyStore keyStore, Reader key, char[] keyPassword, Reader cert) {
- PrivateKey privateKey = loadPemPrivateKey(key, keyPassword);
- X509Certificate certificate = loadPemCertificate(cert);
+ public static void loadPrivateCertificatePem(KeyStore keyStore, String alias, Reader key, char[] keyPassword,
+ Reader cert) {
+ Objects.requireNonNull(keyStore);
+ Objects.requireNonNull(key);
+ try {
+ X509Certificate certificate = loadPemCertificate(cert);
+ PrivateKey privateKey = loadPemPrivateKey(key, keyPassword);
+ keyStore.setKeyEntry(alias, privateKey, keyPassword, new java.security.cert.Certificate[] { certificate });
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("Cannot store PEM certificate", e);
+ }
+ }
+
+ public static void loadTrustedCertificatePem(KeyStore keyStore,char[] keyStorePassword, Reader cert) {
try {
- keyStore.setKeyEntry(certificate.getSubjectX500Principal().getName(), privateKey, keyPassword,
- new java.security.cert.Certificate[] { certificate });
+ X509Certificate certificate = loadPemCertificate(cert);
+ TrustedCertificateEntry trustedCertificateEntry = new TrustedCertificateEntry(certificate);
+ keyStore.setEntry(certificate.getSubjectX500Principal().getName(), trustedCertificateEntry, null);
} catch (KeyStoreException e) {
throw new RuntimeException("Cannot store PEM certificate", e);
}
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) {
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) {
}
+ 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");
+ }
+ }
+
}