mirror of https://github.com/apache/nifi.git
NIFI-8451 Updated KeyStoreUtils to use KeyStore.getInstance() with provider
- Refactored and consolidated KeyStoreUtils unit tests - Corrected KeyStoreUtils.loadEmptyKeyStore() to use KeyStoreUtils.getKeyStore() Signed-off-by: Nathan Gough <thenatog@gmail.com> This closes #5015.
This commit is contained in:
parent
1ef1905461
commit
ed6d5bacba
|
@ -41,7 +41,6 @@ import java.security.cert.CertificateException;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
@ -110,13 +109,12 @@ public class KeyStoreUtils {
|
|||
* @throws KeyStoreException if a KeyStore of the given type cannot be instantiated
|
||||
*/
|
||||
public static KeyStore getKeyStore(String keyStoreType) throws KeyStoreException {
|
||||
String keyStoreProvider = getKeyStoreProvider(keyStoreType);
|
||||
final String keyStoreProvider = getKeyStoreProvider(keyStoreType);
|
||||
if (StringUtils.isNotEmpty(keyStoreProvider)) {
|
||||
try {
|
||||
return KeyStore.getInstance(keyStoreType, keyStoreProvider);
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to load " + keyStoreProvider + " " + keyStoreType
|
||||
+ " keystore. This may cause issues getting trusted CA certificates as well as Certificate Chains for use in TLS.", e);
|
||||
} catch (final Exception e) {
|
||||
logger.error("KeyStore Type [{}] Provider [{}] instance creation failed", keyStoreType, keyStoreProvider, e);
|
||||
}
|
||||
}
|
||||
return KeyStore.getInstance(keyStoreType);
|
||||
|
@ -526,15 +524,12 @@ public class KeyStoreUtils {
|
|||
* @return an empty keystore
|
||||
* @throws KeyStoreException if a keystore of the given type cannot be instantiated
|
||||
*/
|
||||
private static KeyStore loadEmptyKeyStore(KeystoreType keyStoreType) throws KeyStoreException, CertificateException, NoSuchAlgorithmException {
|
||||
final KeyStore keyStore;
|
||||
private static KeyStore loadEmptyKeyStore(final KeystoreType keyStoreType) throws KeyStoreException, CertificateException, NoSuchAlgorithmException {
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(
|
||||
Objects.requireNonNull(keyStoreType).getType());
|
||||
final KeyStore keyStore = getKeyStore(keyStoreType.getType());
|
||||
keyStore.load(null, null);
|
||||
return keyStore;
|
||||
} catch (IOException e) {
|
||||
logger.error("Encountered an error loading keystore: {}", e.getLocalizedMessage());
|
||||
} catch (final IOException e) {
|
||||
throw new UncheckedIOException("Error loading keystore", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.nifi.security.util
|
||||
|
||||
import org.apache.nifi.util.StringUtils
|
||||
import org.junit.After
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
import javax.net.ssl.SSLSocket
|
||||
import javax.net.ssl.SSLSocketFactory
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.security.KeyStore
|
||||
import java.security.cert.Certificate
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
class KeyStoreUtilsGroovyTest extends GroovyTestCase {
|
||||
private static final Logger logger = LoggerFactory.getLogger(KeyStoreUtilsGroovyTest.class)
|
||||
|
||||
private static final String TEST_KEYSTORE_PASSWORD = "keystorepassword"
|
||||
private static final String TEST_KEY_PASSWORD = "keypassword"
|
||||
private static final String TEST_TRUSTSTORE_PASSWORD = "truststorepassword"
|
||||
private static final KeystoreType DEFAULT_STORE_TYPE = KeystoreType.JKS
|
||||
private static final KeystoreType PKCS12_STORE_TYPE = KeystoreType.PKCS12
|
||||
|
||||
private static TlsConfiguration tlsConfigParam
|
||||
private static TlsConfiguration tlsConfiguration
|
||||
|
||||
@BeforeClass
|
||||
static void setUpOnce() {
|
||||
logger.metaClass.methodMissing = { String name, args ->
|
||||
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
|
||||
}
|
||||
|
||||
tlsConfigParam = new StandardTlsConfiguration(null, TEST_KEYSTORE_PASSWORD, TEST_KEY_PASSWORD, DEFAULT_STORE_TYPE, null, TEST_TRUSTSTORE_PASSWORD, null)
|
||||
|
||||
tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore(tlsConfigParam)
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
static void afterClass() throws Exception {
|
||||
deleteKeystoreTruststore(tlsConfiguration);
|
||||
}
|
||||
|
||||
@Before
|
||||
void setUp() {
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
void tearDown() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldVerifyKeystoreIsValid() {
|
||||
// Arrange
|
||||
final URL ksUrl = getKeystorePathAsUrl(tlsConfiguration.getKeystorePath())
|
||||
|
||||
// Act
|
||||
boolean keystoreIsValid = KeyStoreUtils.isStoreValid(ksUrl, DEFAULT_STORE_TYPE, TEST_KEYSTORE_PASSWORD.toCharArray())
|
||||
|
||||
// Assert
|
||||
assert keystoreIsValid
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldVerifyKeystoreIsNotValid() {
|
||||
// Arrange
|
||||
final URL ksUrl = getKeystorePathAsUrl(tlsConfiguration.getKeystorePath())
|
||||
|
||||
// Act
|
||||
boolean keystoreIsValid = KeyStoreUtils.isStoreValid(ksUrl, DEFAULT_STORE_TYPE, TEST_KEYSTORE_PASSWORD.reverse().toCharArray())
|
||||
|
||||
// Assert
|
||||
assert !keystoreIsValid
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldVerifyKeyPasswordIsValid() {
|
||||
// Arrange
|
||||
final URL ksUrl = getKeystorePathAsUrl(tlsConfiguration.getKeystorePath())
|
||||
|
||||
// Act
|
||||
boolean keyPasswordIsValid = KeyStoreUtils.isKeyPasswordCorrect(ksUrl, DEFAULT_STORE_TYPE, TEST_KEYSTORE_PASSWORD.toCharArray(), TEST_KEY_PASSWORD.toCharArray())
|
||||
|
||||
// Assert
|
||||
assert keyPasswordIsValid
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldVerifyKeyPasswordIsNotValid() {
|
||||
// Arrange
|
||||
final URL ksUrl = getKeystorePathAsUrl(tlsConfiguration.getKeystorePath())
|
||||
|
||||
// Act
|
||||
boolean keyPasswordIsValid = KeyStoreUtils.isKeyPasswordCorrect(ksUrl, tlsConfiguration.getKeystoreType(), TEST_KEYSTORE_PASSWORD.toCharArray(), TEST_KEY_PASSWORD.reverse().toCharArray())
|
||||
|
||||
// Assert
|
||||
assert !keyPasswordIsValid
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Used to create passwordless truststore file for testing NIFI-6770")
|
||||
void createPasswordlessTruststore() {
|
||||
// Retrieve the public certificate from https://nifi.apache.org
|
||||
String hostname = "nifi.apache.org"
|
||||
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory()
|
||||
SSLSocket socket = (SSLSocket) factory.createSocket(hostname, 443)
|
||||
socket.startHandshake()
|
||||
List<Certificate> certs = socket.session.peerCertificateChain as List<Certificate>
|
||||
Certificate nodeCert = CertificateUtils.formX509Certificate(certs.first().encoded)
|
||||
|
||||
// Create a JKS truststore containing that cert as a trustedCertEntry and do not put a password on the truststore
|
||||
KeyStore truststore = KeyStore.getInstance("JKS")
|
||||
// Explicitly set the second parameter to empty to avoid a password
|
||||
truststore.load(null, "".chars)
|
||||
truststore.setCertificateEntry("nifi.apache.org", nodeCert)
|
||||
|
||||
// Save the truststore to disk
|
||||
FileOutputStream fos = new FileOutputStream("target/nifi.apache.org.ts.jks")
|
||||
truststore.store(fos, "".chars)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Used to create passwordless truststore file for testing NIFI-6770")
|
||||
void createLocalPasswordlessTruststore() {
|
||||
KeyStore truststoreWithPassword = KeyStore.getInstance("JKS")
|
||||
truststoreWithPassword.load(new FileInputStream("/Users/alopresto/Workspace/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/truststore.jks"), "passwordpassword".chars)
|
||||
Certificate nodeCert = truststoreWithPassword.getCertificate("nifi-cert")
|
||||
|
||||
// Create a JKS truststore containing that cert as a trustedCertEntry and do not put a password on the truststore
|
||||
KeyStore truststore = KeyStore.getInstance("JKS")
|
||||
// Explicitly set the second parameter to empty to avoid a password
|
||||
truststore.load(null, "".chars)
|
||||
truststore.setCertificateEntry("nifi.apache.org", nodeCert)
|
||||
|
||||
// Save the truststore to disk
|
||||
FileOutputStream fos = new FileOutputStream("/Users/alopresto/Workspace/nifi/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/truststore.no-password.jks")
|
||||
truststore.store(fos, "".chars)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldValidateTlsConfigAndNewKeystoreTruststoreWithParams() {
|
||||
// Assert
|
||||
assert tlsConfiguration.getKeystorePath()
|
||||
assert tlsConfiguration.getTruststorePath()
|
||||
assert tlsConfiguration.getKeystoreType() == DEFAULT_STORE_TYPE
|
||||
assert tlsConfiguration.getTruststoreType() == PKCS12_STORE_TYPE
|
||||
assert tlsConfiguration.getKeystorePassword() == TEST_KEYSTORE_PASSWORD
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldValidateTlsConfigAndNewKeystoreTruststoreWithoutParams() {
|
||||
// Act
|
||||
TlsConfiguration testTlsConfig = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore()
|
||||
deleteKeystoreTruststore(testTlsConfig)
|
||||
|
||||
// Assert
|
||||
assert testTlsConfig.getKeystorePath()
|
||||
assert testTlsConfig.getKeyPassword() == testTlsConfig.getKeystorePassword()
|
||||
assert testTlsConfig.getTruststorePassword()
|
||||
assert testTlsConfig.getKeystoreType() == PKCS12_STORE_TYPE
|
||||
assert testTlsConfig.getTruststoreType() == PKCS12_STORE_TYPE
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldValidateTlsConfigWithoutKeyPasswordParam() {
|
||||
// Arrange
|
||||
TlsConfiguration testTlsConfigParam = new StandardTlsConfiguration(null, TEST_KEYSTORE_PASSWORD, null, DEFAULT_STORE_TYPE, null, TEST_TRUSTSTORE_PASSWORD, DEFAULT_STORE_TYPE)
|
||||
|
||||
// Act
|
||||
final TlsConfiguration testTlsConfig = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore(testTlsConfigParam)
|
||||
deleteKeystoreTruststore(testTlsConfig)
|
||||
|
||||
// Assert
|
||||
assert testTlsConfig.getKeyPassword() == testTlsConfig.getKeystorePassword()
|
||||
}
|
||||
|
||||
private static URL getKeystorePathAsUrl(String path) {
|
||||
return new File(path).toURI().toURL()
|
||||
}
|
||||
|
||||
private static void deleteKeystoreTruststore(TlsConfiguration tlsConfig) {
|
||||
if (tlsConfig != null) {
|
||||
try {
|
||||
if (StringUtils.isNotBlank(tlsConfig.getKeystorePath())) {
|
||||
Files.deleteIfExists(Paths.get(tlsConfig.getKeystorePath()))
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOException("There was an error deleting a keystore: ${e.getMessage()}, ${e}");
|
||||
}
|
||||
|
||||
try {
|
||||
if (StringUtils.isNotBlank(tlsConfig.getTruststorePath())) {
|
||||
Files.deleteIfExists(Paths.get(tlsConfig.getTruststorePath()))
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOException("There was an error deleting a truststore: ${e.getMessage()}, ${e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.apache.nifi.security.util;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
|
@ -28,6 +29,8 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -36,113 +39,87 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class KeyStoreUtilsTest {
|
||||
public static final String SIGNING_ALGORITHM = "SHA256withRSA";
|
||||
public static final int DURATION_DAYS = 365;
|
||||
public static final char[] BAD_TEST_PASSWORD_DONT_USE_THIS = "changek".toCharArray();
|
||||
public static final char[] BAD_KEY_STORE_TEST_PASSWORD_DONT_USE_THIS = "changes".toCharArray();
|
||||
public static final String ALIAS = "alias";
|
||||
|
||||
private static KeyPair caCertKeyPair;
|
||||
private static X509Certificate caCertificate;
|
||||
|
||||
private static KeyPair issuedCertificateKeyPair;
|
||||
private static X509Certificate issuedCertificate;
|
||||
private static final String SIGNING_ALGORITHM = "SHA256withRSA";
|
||||
private static final int DURATION_DAYS = 365;
|
||||
private static final char[] KEY_PASSWORD = UUID.randomUUID().toString().toCharArray();
|
||||
private static final char[] STORE_PASSWORD = UUID.randomUUID().toString().toCharArray();
|
||||
private static final String ALIAS = "alias";
|
||||
private static final String KEY_ALGORITHM = "RSA";
|
||||
private static final String SUBJECT_DN = "CN=localhost";
|
||||
private static KeyPair keyPair;
|
||||
private static X509Certificate certificate;
|
||||
|
||||
@BeforeClass
|
||||
public static void generateKeysAndCertificates() throws NoSuchAlgorithmException, CertificateException {
|
||||
caCertKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
issuedCertificateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
|
||||
caCertificate = CertificateUtils.generateSelfSignedX509Certificate(caCertKeyPair, "CN=testca,O=Apache,OU=NiFi", SIGNING_ALGORITHM, DURATION_DAYS);
|
||||
issuedCertificate = CertificateUtils.generateIssuedCertificate("CN=testcert,O=Apache,OU=NiFi", issuedCertificateKeyPair.getPublic(), caCertificate, caCertKeyPair, SIGNING_ALGORITHM,
|
||||
DURATION_DAYS);
|
||||
keyPair = KeyPairGenerator.getInstance(KEY_ALGORITHM).generateKeyPair();
|
||||
certificate = CertificateUtils.generateSelfSignedX509Certificate(keyPair, SUBJECT_DN, SIGNING_ALGORITHM, DURATION_DAYS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBcfksKeyStoreRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testKeyStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.BCFKS.toString().toLowerCase()));
|
||||
public void testCreateTlsConfigAndNewKeystoreTruststore() throws GeneralSecurityException, IOException {
|
||||
final TlsConfiguration configuration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore();
|
||||
final File keystoreFile = new File(configuration.getKeystorePath());
|
||||
assertTrue("Keystore File not found", keystoreFile.exists());
|
||||
keystoreFile.deleteOnExit();
|
||||
|
||||
final File truststoreFile = new File(configuration.getTruststorePath());
|
||||
assertTrue("Truststore File not found", truststoreFile.exists());
|
||||
truststoreFile.deleteOnExit();
|
||||
|
||||
assertEquals("Keystore Type not matched", KeystoreType.PKCS12, configuration.getKeystoreType());
|
||||
assertEquals("Truststore Type not matched", KeystoreType.PKCS12, configuration.getTruststoreType());
|
||||
|
||||
assertTrue("Keystore not valid", KeyStoreUtils.isStoreValid(keystoreFile.toURI().toURL(), configuration.getKeystoreType(), configuration.getKeystorePassword().toCharArray()));
|
||||
assertTrue("Truststore not valid", KeyStoreUtils.isStoreValid(truststoreFile.toURI().toURL(), configuration.getTruststoreType(), configuration.getTruststorePassword().toCharArray()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJksKeyStoreRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testKeyStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.JKS.toString().toLowerCase()));
|
||||
public void testKeystoreTypesPrivateKeyEntry() throws GeneralSecurityException, IOException {
|
||||
for (final KeystoreType keystoreType : KeystoreType.values()) {
|
||||
final KeyStore sourceKeyStore = KeyStoreUtils.getKeyStore(keystoreType.getType());
|
||||
final KeyStore destinationKeyStore = KeyStoreUtils.getKeyStore(keystoreType.getType());
|
||||
assertKeyEntryStoredLoaded(sourceKeyStore, destinationKeyStore);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPkcs12KeyStoreBcRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testKeyStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.PKCS12.toString().toLowerCase()));
|
||||
public void testKeystoreTypesCertificateEntry() throws GeneralSecurityException, IOException {
|
||||
for (final KeystoreType keystoreType : KeystoreType.values()) {
|
||||
final KeyStore sourceKeyStore = KeyStoreUtils.getKeyStore(keystoreType.getType());
|
||||
final KeyStore destinationKeyStore = KeyStoreUtils.getKeyStore(keystoreType.getType());
|
||||
assertCertificateEntryStoredLoaded(sourceKeyStore, destinationKeyStore);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPkcs12KeyStoreRoundTripBcReload() throws GeneralSecurityException, IOException {
|
||||
// Pkcs12 Bouncy Castle needs same key and keystore password to interoperate with Java provider
|
||||
testKeyStoreRoundTrip(() -> KeyStore.getInstance(KeystoreType.PKCS12.toString().toLowerCase()),
|
||||
() -> KeyStoreUtils.getKeyStore(KeystoreType.PKCS12.toString().toLowerCase()), BAD_KEY_STORE_TEST_PASSWORD_DONT_USE_THIS);
|
||||
private void assertCertificateEntryStoredLoaded(final KeyStore sourceKeyStore, final KeyStore destinationKeyStore) throws GeneralSecurityException, IOException {
|
||||
sourceKeyStore.load(null, null);
|
||||
sourceKeyStore.setCertificateEntry(ALIAS, certificate);
|
||||
|
||||
final KeyStore copiedKeyStore = copyKeyStore(sourceKeyStore, destinationKeyStore);
|
||||
assertEquals(String.format("[%s] Certificate not matched", sourceKeyStore.getType()), certificate, copiedKeyStore.getCertificate(ALIAS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBcfksTrustStoreRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testTrustStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.BCFKS.toString().toLowerCase()));
|
||||
private void assertKeyEntryStoredLoaded(final KeyStore sourceKeyStore, final KeyStore destinationKeyStore) throws GeneralSecurityException, IOException {
|
||||
sourceKeyStore.load(null, null);
|
||||
final Certificate[] certificateChain = new Certificate[]{certificate};
|
||||
sourceKeyStore.setKeyEntry(ALIAS, keyPair.getPrivate(), KEY_PASSWORD, certificateChain);
|
||||
|
||||
final KeyStore copiedKeyStore = copyKeyStore(sourceKeyStore, destinationKeyStore);
|
||||
final KeyStore.Entry entry = copiedKeyStore.getEntry(ALIAS, new KeyStore.PasswordProtection(KEY_PASSWORD));
|
||||
assertTrue(String.format("[%s] Private Key entry not found", sourceKeyStore.getType()), entry instanceof KeyStore.PrivateKeyEntry);
|
||||
final KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
|
||||
|
||||
final Certificate[] entryCertificateChain = privateKeyEntry.getCertificateChain();
|
||||
assertArrayEquals(String.format("[%s] Certificate Chain not matched", sourceKeyStore.getType()), certificateChain, entryCertificateChain);
|
||||
assertEquals(String.format("[%s] Private Key not matched", sourceKeyStore.getType()), keyPair.getPrivate(), privateKeyEntry.getPrivateKey());
|
||||
assertEquals(String.format("[%s] Public Key not matched", sourceKeyStore.getType()), keyPair.getPublic(), entryCertificateChain[0].getPublicKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJksTrustStoreRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testTrustStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.JKS.toString().toLowerCase()));
|
||||
}
|
||||
private KeyStore copyKeyStore(final KeyStore sourceKeyStore, final KeyStore destinationKeyStore) throws GeneralSecurityException, IOException {
|
||||
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
sourceKeyStore.store(byteArrayOutputStream, STORE_PASSWORD);
|
||||
|
||||
@Test
|
||||
public void testPkcs12TrustStoreBcRoundTrip() throws GeneralSecurityException, IOException {
|
||||
testTrustStoreRoundTrip(() -> KeyStoreUtils.getKeyStore(KeystoreType.PKCS12.toString().toLowerCase()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPkcs12TrustStoreRoundTripBcReload() throws GeneralSecurityException, IOException {
|
||||
testTrustStoreRoundTrip(() -> KeyStore.getInstance(KeystoreType.PKCS12.toString().toLowerCase()), () -> KeyStoreUtils.getKeyStore(KeystoreType.PKCS12.toString().toLowerCase()));
|
||||
}
|
||||
|
||||
private void testTrustStoreRoundTrip(KeyStoreSupplier keyStoreSupplier) throws GeneralSecurityException, IOException {
|
||||
testTrustStoreRoundTrip(keyStoreSupplier, keyStoreSupplier);
|
||||
}
|
||||
|
||||
private void testTrustStoreRoundTrip(KeyStoreSupplier initialKeyStoreSupplier, KeyStoreSupplier reloadKeyStoreSupplier) throws GeneralSecurityException, IOException {
|
||||
KeyStore trustStore = initialKeyStoreSupplier.get();
|
||||
trustStore.load(null, null);
|
||||
trustStore.setCertificateEntry(ALIAS, caCertificate);
|
||||
|
||||
KeyStore roundTrip = roundTrip(trustStore, reloadKeyStoreSupplier);
|
||||
assertEquals(caCertificate, roundTrip.getCertificate(ALIAS));
|
||||
}
|
||||
|
||||
private void testKeyStoreRoundTrip(KeyStoreSupplier keyStoreSupplier) throws GeneralSecurityException, IOException {
|
||||
testKeyStoreRoundTrip(keyStoreSupplier, keyStoreSupplier, BAD_TEST_PASSWORD_DONT_USE_THIS);
|
||||
}
|
||||
|
||||
private void testKeyStoreRoundTrip(KeyStoreSupplier initialKeyStoreSupplier, KeyStoreSupplier reloadKeyStoreSupplier, char[] keyPassword) throws GeneralSecurityException, IOException {
|
||||
KeyStore keyStore = initialKeyStoreSupplier.get();
|
||||
keyStore.load(null, null);
|
||||
keyStore.setKeyEntry(ALIAS, issuedCertificateKeyPair.getPrivate(), keyPassword, new Certificate[]{issuedCertificate, caCertificate});
|
||||
|
||||
KeyStore roundTrip = roundTrip(keyStore, reloadKeyStoreSupplier);
|
||||
KeyStore.Entry entry = roundTrip.getEntry(ALIAS, new KeyStore.PasswordProtection(keyPassword));
|
||||
assertTrue(entry instanceof KeyStore.PrivateKeyEntry);
|
||||
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) entry;
|
||||
|
||||
Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
|
||||
assertArrayEquals(new Certificate[]{issuedCertificate, caCertificate}, certificateChain);
|
||||
assertEquals(issuedCertificateKeyPair.getPrivate(), privateKeyEntry.getPrivateKey());
|
||||
assertEquals(issuedCertificateKeyPair.getPublic(), certificateChain[0].getPublicKey());
|
||||
}
|
||||
|
||||
private KeyStore roundTrip(KeyStore keyStore, KeyStoreSupplier keyStoreSupplier) throws GeneralSecurityException, IOException {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
keyStore.store(byteArrayOutputStream, BAD_KEY_STORE_TEST_PASSWORD_DONT_USE_THIS);
|
||||
|
||||
KeyStore result = keyStoreSupplier.get();
|
||||
result.load(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), BAD_KEY_STORE_TEST_PASSWORD_DONT_USE_THIS);
|
||||
return result;
|
||||
}
|
||||
|
||||
private interface KeyStoreSupplier {
|
||||
KeyStore get() throws GeneralSecurityException;
|
||||
destinationKeyStore.load(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), STORE_PASSWORD);
|
||||
return destinationKeyStore;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue