X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FPkiUtils.java;h=2105e05d01c91911874d5472683ac9490f0f6827;hb=48a1bccfd878f84300c798b3b6508682d5429cd9;hp=67f8f01c65ee8ca5a62bb236ef046e7a3f7bc57d;hpb=b4c772a263e0f19f6c283dbbb87d04794072b284;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java index 67f8f01c6..2105e05d0 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java @@ -1,33 +1,50 @@ package org.argeo.cms.internal.kernel; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; import java.math.BigInteger; +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.KeyStoreException; +import java.security.PrivateKey; import java.security.SecureRandom; import java.security.Security; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import javax.security.auth.x500.X500Principal; -import org.argeo.ArgeoException; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.cert.X509CertificateHolder; 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.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder; import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.InputDecryptorProvider; +import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; +import org.bouncycastle.pkcs.PKCSException; /** * Utilities around private keys and certificate, mostly wrapping BouncyCastle * implementations. */ class PkiUtils { + final static String PKCS12 = "PKCS12"; + private final static String SECURITY_PROVIDER; static { Security.addProvider(new BouncyCastleProvider()); @@ -41,7 +58,7 @@ class PkiUtils { kpGen.initialize(keySize, new SecureRandom()); KeyPair pair = kpGen.generateKeyPair(); Date notBefore = new Date(System.currentTimeMillis() - 10000); - Date notAfter = new Date(System.currentTimeMillis() + 24L * 3600 * 1000); + Date notAfter = new Date(System.currentTimeMillis() + 365 * 24L * 3600 * 1000); BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(x500Principal, serial, notBefore, notAfter, x500Principal, pair.getPublic()); @@ -54,105 +71,188 @@ class PkiUtils { keyStore.setKeyEntry(x500Principal.getName(), pair.getPrivate(), keyPassword, new Certificate[] { cert }); return cert; - } catch (Exception e) { - throw new ArgeoException("Cannot generate self-signed certificate", e); + } catch (GeneralSecurityException | OperatorCreationException e) { + throw new RuntimeException("Cannot generate self-signed certificate", e); } } - public static KeyStore getKeyStore(File keyStoreFile, char[] keyStorePassword) { + public static KeyStore getKeyStore(Path keyStoreFile, char[] keyStorePassword, String keyStoreType) { try { - KeyStore store = KeyStore.getInstance("PKCS12", SECURITY_PROVIDER); - if (keyStoreFile.exists()) { - try (FileInputStream fis = new FileInputStream(keyStoreFile)) { + KeyStore store = KeyStore.getInstance(keyStoreType, SECURITY_PROVIDER); + if (Files.exists(keyStoreFile)) { + try (InputStream fis = Files.newInputStream(keyStoreFile)) { store.load(fis, keyStorePassword); } } else { store.load(null); } return store; - } catch (Exception e) { - throw new ArgeoException("Cannot load keystore " + keyStoreFile, e); + } catch (GeneralSecurityException | IOException e) { + throw new RuntimeException("Cannot load keystore " + keyStoreFile, e); } } - public static void saveKeyStore(File keyStoreFile, char[] keyStorePassword, KeyStore keyStore) { + public static void saveKeyStore(Path keyStoreFile, char[] keyStorePassword, KeyStore keyStore) { try { - try (FileOutputStream fis = new FileOutputStream(keyStoreFile)) { + try (OutputStream fis = Files.newOutputStream(keyStoreFile)) { keyStore.store(fis, keyStorePassword); } - } catch (Exception e) { - throw new ArgeoException("Cannot save keystore " + keyStoreFile, e); + } catch (GeneralSecurityException | IOException e) { + throw new RuntimeException("Cannot save keystore " + keyStoreFile, e); } } - public static void main(String[] args) { +// public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) +// throws Exception { +// // Get the private key +// FileReader reader = new FileReader(keyFile); +// +// PEMReader pem = new PemReader(reader, new PasswordFinder() { +// @Override +// public char[] getPassword() { +// return password.toCharArray(); +// } +// }); +// +// PrivateKey key = ((KeyPair) pem.readObject()).getPrivate(); +// +// pem.close(); +// reader.close(); +// +// // Get the certificate +// reader = new FileReader(cerFile); +// pem = new PEMReader(reader); +// +// X509Certificate cert = (X509Certificate) pem.readObject(); +// +// pem.close(); +// reader.close(); +// +// // Put them into a PKCS12 keystore and write it to a byte[] +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// KeyStore ks = KeyStore.getInstance("PKCS12"); +// ks.load(null); +// ks.setKeyEntry("alias", (Key) key, password.toCharArray(), new java.security.cert.Certificate[] { cert }); +// ks.store(bos, password.toCharArray()); +// bos.close(); +// return bos.toByteArray(); +// } + + 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 }); + } 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"); + Object object = pemParser.readObject(); + PrivateKeyInfo privateKeyInfo; + if (object instanceof PKCS8EncryptedPrivateKeyInfo) { + if (keyPassword == null) + throw new IllegalArgumentException("A key password is required"); + InputDecryptorProvider decProv = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(keyPassword); + privateKeyInfo = ((PKCS8EncryptedPrivateKeyInfo) object).decryptPrivateKeyInfo(decProv); + } else if (object instanceof PrivateKeyInfo) { + privateKeyInfo = (PrivateKeyInfo) object; + } else { + throw new IllegalArgumentException("Unsupported format for private key"); + } + return converter.getPrivateKey(privateKeyInfo); + } catch (IOException | OperatorCreationException | PKCSException e) { + throw new RuntimeException("Cannot read private key", e); + } + } + + public static X509Certificate loadPemCertificate(Reader reader) { + try (PEMParser pemParser = new PEMParser(reader)) { + X509CertificateHolder certHolder = (X509CertificateHolder) pemParser.readObject(); + X509Certificate cert = new JcaX509CertificateConverter().setProvider(SECURITY_PROVIDER) + .getCertificate(certHolder); + return cert; + } catch (IOException | CertificateException e) { + throw new RuntimeException("Cannot read private key", e); + } + } + + public static void main(String[] args) throws Exception { final String ALGORITHM = "RSA"; final String provider = "BC"; SecureRandom secureRandom = new SecureRandom(); long begin = System.currentTimeMillis(); for (int i = 512; i < 1024; i = i + 2) { try { - KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM,provider); + KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM, provider); keyGen.initialize(i, secureRandom); keyGen.generateKeyPair(); } catch (Exception e) { System.err.println(i + " : " + e.getMessage()); } } - System.out.println( (System.currentTimeMillis() - begin) + " ms"); - -// // String text = "a"; -// String text = "testtesttesttesttesttesttesttesttesttesttesttesttesttesttest"; -// try { -// System.out.println(text); -// PrivateKey privateKey; -// PublicKey publicKey; -// char[] password = "changeit".toCharArray(); -// String alias = "CN=test"; -// KeyStore keyStore = KeyStore.getInstance("pkcs12"); -// File p12file = new File("test.p12"); -// p12file.delete(); -// if (!p12file.exists()) { -// keyStore.load(null); -// generateSelfSignedCertificate(keyStore, new X500Principal(alias), 513, password); -// try (OutputStream out = new FileOutputStream(p12file)) { -// keyStore.store(out, password); -// } -// } -// try (InputStream in = new FileInputStream(p12file)) { -// keyStore.load(in, password); -// privateKey = (PrivateKey) keyStore.getKey(alias, password); -// publicKey = keyStore.getCertificateChain(alias)[0].getPublicKey(); -// } -// // KeyPair key; -// // final KeyPairGenerator keyGen = -// // KeyPairGenerator.getInstance(ALGORITHM); -// // keyGen.initialize(4096, new SecureRandom()); -// // long begin = System.currentTimeMillis(); -// // key = keyGen.generateKeyPair(); -// // System.out.println((System.currentTimeMillis() - begin) + " ms"); -// // keyStore.load(null); -// // keyStore.setKeyEntry("test", key.getPrivate(), password, null); -// // try(OutputStream out=new FileOutputStream(p12file)) { -// // keyStore.store(out, password); -// // } -// // privateKey = key.getPrivate(); -// // publicKey = key.getPublic(); -// -// Cipher encrypt = Cipher.getInstance(ALGORITHM); -// encrypt.init(Cipher.ENCRYPT_MODE, publicKey); -// byte[] encrypted = encrypt.doFinal(text.getBytes()); -// String encryptedBase64 = Base64.getEncoder().encodeToString(encrypted); -// System.out.println(encryptedBase64); -// byte[] encryptedFromBase64 = Base64.getDecoder().decode(encryptedBase64); -// -// Cipher decrypt = Cipher.getInstance(ALGORITHM); -// decrypt.init(Cipher.DECRYPT_MODE, privateKey); -// byte[] decrypted = decrypt.doFinal(encryptedFromBase64); -// System.out.println(new String(decrypted)); -// } catch (Exception e) { -// e.printStackTrace(); -// } + System.out.println((System.currentTimeMillis() - begin) + " ms"); + + // // String text = "a"; + // String text = + // "testtesttesttesttesttesttesttesttesttesttesttesttesttesttest"; + // try { + // System.out.println(text); + // PrivateKey privateKey; + // PublicKey publicKey; + // char[] password = "changeit".toCharArray(); + // String alias = "CN=test"; + // KeyStore keyStore = KeyStore.getInstance("pkcs12"); + // File p12file = new File("test.p12"); + // p12file.delete(); + // if (!p12file.exists()) { + // keyStore.load(null); + // generateSelfSignedCertificate(keyStore, new X500Principal(alias), + // 513, password); + // try (OutputStream out = new FileOutputStream(p12file)) { + // keyStore.store(out, password); + // } + // } + // try (InputStream in = new FileInputStream(p12file)) { + // keyStore.load(in, password); + // privateKey = (PrivateKey) keyStore.getKey(alias, password); + // publicKey = keyStore.getCertificateChain(alias)[0].getPublicKey(); + // } + // // KeyPair key; + // // final KeyPairGenerator keyGen = + // // KeyPairGenerator.getInstance(ALGORITHM); + // // keyGen.initialize(4096, new SecureRandom()); + // // long begin = System.currentTimeMillis(); + // // key = keyGen.generateKeyPair(); + // // System.out.println((System.currentTimeMillis() - begin) + " ms"); + // // keyStore.load(null); + // // keyStore.setKeyEntry("test", key.getPrivate(), password, null); + // // try(OutputStream out=new FileOutputStream(p12file)) { + // // keyStore.store(out, password); + // // } + // // privateKey = key.getPrivate(); + // // publicKey = key.getPublic(); + // + // Cipher encrypt = Cipher.getInstance(ALGORITHM); + // encrypt.init(Cipher.ENCRYPT_MODE, publicKey); + // byte[] encrypted = encrypt.doFinal(text.getBytes()); + // String encryptedBase64 = + // Base64.getEncoder().encodeToString(encrypted); + // System.out.println(encryptedBase64); + // byte[] encryptedFromBase64 = + // Base64.getDecoder().decode(encryptedBase64); + // + // Cipher decrypt = Cipher.getInstance(ALGORITHM); + // decrypt.init(Cipher.DECRYPT_MODE, privateKey); + // byte[] decrypted = decrypt.doFinal(encryptedFromBase64); + // System.out.println(new String(decrypted)); + // } catch (Exception e) { + // e.printStackTrace(); + // } }