Java tutorial
/** * Copyright (c) 2002-2016 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.neo4j.driver.v1.util; import org.bouncycastle.asn1.x500.X500Name; 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.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter; import org.junit.Test; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import javax.security.auth.x500.X500Principal; import org.neo4j.driver.internal.util.CertificateTool; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.neo4j.driver.internal.util.CertificateTool.saveX509Cert; public class CertificateToolTest { static { // adds the Bouncy castle provider to java security Security.addProvider(new BouncyCastleProvider()); } public static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); keyPairGenerator.initialize(2048, new SecureRandom()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); return keyPair; } public static X509Certificate generateCert(X500Name issuer, X500Name subject, KeyPair issuerKeys, PublicKey publicKey) throws GeneralSecurityException, IOException, OperatorCreationException { // Create x509 certificate Date startDate = new Date(System.currentTimeMillis()); Date endDate = new Date(System.currentTimeMillis() + 365L * 24L * 60L * 60L * 1000L); BigInteger serialNum = BigInteger.valueOf(System.currentTimeMillis()); X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(issuer, serialNum, startDate, endDate, subject, publicKey); // Get the certificate back ContentSigner signer = new JcaContentSignerBuilder("SHA512WithRSAEncryption") .build(issuerKeys.getPrivate()); X509CertificateHolder certHolder = certBuilder.build(signer); X509Certificate certificate = new JcaX509CertificateConverter().setProvider("BC") .getCertificate(certHolder); certificate.verify(issuerKeys.getPublic()); return certificate; } public static class SelfSignedCertificateGenerator { private final KeyPair keyPair; private final X509Certificate certificate; public SelfSignedCertificateGenerator() throws GeneralSecurityException, IOException, OperatorCreationException { // Create the public/private rsa key pair keyPair = generateKeyPair(); // Create x509 certificate certificate = generateCert(new X500Name("CN=NEO4J_JAVA_DRIVER_TEST_ROOT"), new X500Name("CN=NEO4J_JAVA_DRIVER_TEST_ROOT"), keyPair, keyPair.getPublic()); } public void savePrivateKey(File saveTo) throws IOException { writePem("PRIVATE KEY", keyPair.getPrivate().getEncoded(), saveTo); } public void saveSelfSignedCertificate(File saveTo) throws CertificateEncodingException, IOException { writePem("CERTIFICATE", certificate.getEncoded(), saveTo); } public X509Certificate sign(PKCS10CertificationRequest csr, PublicKey csrPublicKey) throws GeneralSecurityException, IOException, OperatorCreationException { X509Certificate certificate = generateCert( X500Name.getInstance(this.certificate.getSubjectX500Principal().getEncoded()), csr.getSubject(), keyPair, csrPublicKey); return certificate; } } public static class CertificateSigningRequestGenerator { // ref: http://senthadev.com/generating-csr-using-java-and-bouncycastle-api.html private final KeyPair keyPair; private final PKCS10CertificationRequest csr; public CertificateSigningRequestGenerator() throws NoSuchAlgorithmException, OperatorCreationException { KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(2048, new SecureRandom()); keyPair = gen.generateKeyPair(); X500Principal subject = new X500Principal("CN=NEO4j_JAVA_DRIVER_TEST_SERVER"); ContentSigner signGen = new JcaContentSignerBuilder("SHA512WithRSAEncryption") .build(keyPair.getPrivate()); PKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(subject, keyPair.getPublic()); csr = builder.build(signGen); } public PrivateKey privateKey() { return keyPair.getPrivate(); } public PublicKey publicKey() { return keyPair.getPublic(); } public PKCS10CertificationRequest certificateSigningRequest() { return csr; } public void savePrivateKey(File saveTo) throws IOException { writePem("PRIVATE KEY", keyPair.getPrivate().getEncoded(), saveTo); } } /** * Create a random certificate * * @return a random certificate * @throws GeneralSecurityException, IOException, OperatorCreationException */ public static X509Certificate generateSelfSignedCertificate() throws GeneralSecurityException, IOException, OperatorCreationException { return new SelfSignedCertificateGenerator().certificate; } private static void writePem(String type, byte[] encodedContent, File path) throws IOException { if (path.getParentFile() != null && path.getParentFile().exists()) path.getParentFile().mkdirs(); try (PemWriter writer = new PemWriter(new FileWriter(path))) { writer.writeObject(new PemObject(type, encodedContent)); writer.flush(); } } @Test public void shouldLoadMultipleCertsIntoKeyStore() throws Throwable { // Given File certFile = File.createTempFile("3random", ".cer"); certFile.deleteOnExit(); X509Certificate cert1 = generateSelfSignedCertificate(); X509Certificate cert2 = generateSelfSignedCertificate(); X509Certificate cert3 = generateSelfSignedCertificate(); saveX509Cert(new Certificate[] { cert1, cert2, cert3 }, certFile); KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(null, null); // When CertificateTool.loadX509Cert(certFile, keyStore); // Then Enumeration<String> aliases = keyStore.aliases(); assertTrue(aliases.hasMoreElements()); assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); assertTrue(aliases.hasMoreElements()); assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); assertTrue(aliases.hasMoreElements()); assertTrue(aliases.nextElement().startsWith("neo4j.javadriver.trustedcert")); assertFalse(aliases.hasMoreElements()); } }