From ee672c3672924ca54b89a7c429ee06f01b9f6caa Mon Sep 17 00:00:00 2001 From: Joanna Jeremicz Date: Wed, 26 Feb 2020 14:30:36 +0100 Subject: Transform pem files into pkcs12 Transform from received from CertService pem files into pkcs12 Issue-ID: AAF-996 Signed-off-by: Joanna Jeremicz Change-Id: I39b71cf3f267c5ca701b3d4cf456fc6d81ae5f81 --- .../conversion/KeystoreTruststoreCreatorTest.java | 80 +++++++++ .../conversion/PKCS12FilesCreatorTest.java | 111 ++++++++++++ .../conversion/PemToPKCS12ConverterTest.java | 197 +++++++++++++++++++++ .../conversion/RandomPasswordGeneratorTest.java | 32 ++++ 4 files changed, 420 insertions(+) create mode 100644 certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java create mode 100644 certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java create mode 100644 certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java create mode 100644 certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java (limited to 'certServiceClient/src/test/java/org') diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java new file mode 100644 index 00000000..04bccf0b --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/KeystoreTruststoreCreatorTest.java @@ -0,0 +1,80 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.client.certification.conversion; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.security.PrivateKey; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class KeystoreTruststoreCreatorTest { + + private PKCS12FilesCreator filesCreator = mock(PKCS12FilesCreator.class); + private RandomPasswordGenerator passwordGenerator = mock(RandomPasswordGenerator.class); + private PemToPKCS12Converter converter = mock(PemToPKCS12Converter.class); + private PrivateKey privateKey = mock(PrivateKey.class); + + @Test + void createKeystoreShouldCallRequiredMethods() throws PemToPKCS12ConverterException { + // given + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List certificates = List.of("a", "b"); + final int passwordLength = 24; + final String alias = "certificate"; + final byte[] keystoreBytes = "this is a keystore test".getBytes(); + KeystoreTruststoreCreator creator = new KeystoreTruststoreCreator(filesCreator, passwordGenerator, converter); + + // when + when(passwordGenerator.generate(passwordLength)).thenReturn(password); + when(converter.convertKeystore(certificates, password, alias, privateKey)).thenReturn(keystoreBytes); + creator.createKeystore(certificates, privateKey); + + // then + verify(passwordGenerator, times(1)).generate(passwordLength); + verify(converter, times(1)).convertKeystore(certificates, password, alias, privateKey); + verify(filesCreator, times(1)).saveKeystoreData(keystoreBytes, password.getPassword()); + } + + @Test + void createTruststoreShouldCallRequiredMethods() throws PemToPKCS12ConverterException { + // given + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List certificates = List.of("a", "b"); + final int passwordLength = 24; + final String alias = "trusted-certificate-"; + final byte[] truststoreBytes = "this is a truststore test".getBytes(); + KeystoreTruststoreCreator creator = new KeystoreTruststoreCreator(filesCreator, passwordGenerator, converter); + + // when + when(passwordGenerator.generate(passwordLength)).thenReturn(password); + when(converter.convertTruststore(certificates, password, alias)).thenReturn(truststoreBytes); + creator.createTruststore(certificates); + + // then + verify(passwordGenerator, times(1)).generate(passwordLength); + verify(converter, times(1)).convertTruststore(certificates, password, alias); + verify(filesCreator, times(1)).saveTruststoreData(truststoreBytes, password.getPassword()); + } +} \ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java new file mode 100644 index 00000000..8e6e03c6 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PKCS12FilesCreatorTest.java @@ -0,0 +1,111 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.client.certification.conversion; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class PKCS12FilesCreatorTest { + + private static final String RESOURCES_PATH = "src/test/resources"; + private static final String OUTPUT_PATH = RESOURCES_PATH + "/generatedFiles/"; + private static final String KEYSTORE_PATH = OUTPUT_PATH + "keystore.jks"; + private static final String KEYSTORE_PASS_PATH = OUTPUT_PATH + "keystore.pass"; + private static final String TRUSTSTORE_PATH = OUTPUT_PATH + "truststore.jks"; + private static final String TRUSTSTORE_PASS_PATH = OUTPUT_PATH + "truststore.pass"; + private static final String ERROR_MESSAGE = "java.io.FileNotFoundException: src/test/resources/generatedFiles/thisPathDoesNotExist/keystore.jks (No such file or directory)"; + + private File outputDirectory = new File(OUTPUT_PATH); + + @BeforeEach + void createDirectory() { + outputDirectory.mkdir(); + } + + @AfterEach + void cleanUpFiles() { + List.of(outputDirectory.listFiles()).forEach(f -> f.delete()); + outputDirectory.delete(); + } + + @Test + void saveKeystoreDataShouldCreateFilesWithDataInGivenLocation() throws PemToPKCS12ConverterException, IOException { + // given + final byte[] data = new byte[]{-128, 1, 127}; + final String password = "onap123"; + File keystore = new File(KEYSTORE_PATH); + File keystorePass = new File(KEYSTORE_PASS_PATH); + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH); + + // when + filesCreator.saveKeystoreData(data, password); + + // then + assertTrue(keystore.exists()); + assertTrue(keystorePass.exists()); + assertArrayEquals(data, Files.readAllBytes(Path.of(KEYSTORE_PATH))); + assertEquals(password, Files.readString(Path.of(KEYSTORE_PASS_PATH), StandardCharsets.UTF_8)); + } + + @Test + void saveTruststoreDataShouldCreateFilesWithDataInGivenLocation() + throws PemToPKCS12ConverterException, IOException { + // given + final byte[] data = new byte[]{-128, 1, 2, 3, 127}; + final String password = "nokia321"; + File truststore = new File(TRUSTSTORE_PATH); + File truststorePass = new File(TRUSTSTORE_PASS_PATH); + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH); + + // when + filesCreator.saveTruststoreData(data, password); + + // then + assertTrue(truststore.exists()); + assertTrue(truststorePass.exists()); + assertArrayEquals(data, Files.readAllBytes(Path.of(TRUSTSTORE_PATH))); + assertEquals(password, Files.readString(Path.of(TRUSTSTORE_PASS_PATH), StandardCharsets.UTF_8)); + } + + @Test + void saveKeystoreDataShouldThrowPemToPKCS12ConverterExceptionWhenOutputDirectoryDoesNotExist() { + // given + final byte[] data = new byte[]{-128, 1, 2, 3, 0}; + final String password = "123aikon"; + PKCS12FilesCreator filesCreator = new PKCS12FilesCreator(OUTPUT_PATH + "thisPathDoesNotExist/"); + + // when then + assertThatThrownBy(() -> filesCreator.saveKeystoreData(data, password)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(ERROR_MESSAGE); + } +} \ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java new file mode 100644 index 00000000..35043409 --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/PemToPKCS12ConverterTest.java @@ -0,0 +1,197 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.client.certification.conversion; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.aaf.certservice.client.certification.EncryptionAlgorithmConstants; +import org.onap.aaf.certservice.client.certification.exception.PemToPKCS12ConverterException; + +class PemToPKCS12ConverterTest { + + private static final String RESOURCES_PATH = "src/test/resources"; + private static final String CERT1_PATH = RESOURCES_PATH + "/cert1.pem"; + private static final String CERT2_PATH = RESOURCES_PATH + "/cert2.pem"; + private static final String KEY_PATH = RESOURCES_PATH + "/privateKey"; + private static final String EXPECTED_KEYSTORE_PATH = RESOURCES_PATH + "/expectedKeystore.jks"; + private static final String EXPECTED_TRUSTSTORE_PATH = RESOURCES_PATH + "/expectedTruststore.jks"; + private static final String PKCS12 = "PKCS12"; + private static final String PKCS8 = "PKCS#8"; + private static final String KEY_ERROR_MSG = "java.security.KeyStoreException: Key protection algorithm not found: java.lang.NullPointerException"; + private static final String CERTIFICATES_ERROR_MSG = "The certificate couldn't be parsed correctly. certificate1"; + private static final String PASSWORD_ERROR_MSG = "Password should be min. 16 chars long and should contain only alphanumeric characters and special characters like Underscore (_), Dollar ($) and Pound (#)"; + private static byte[] key; + private PrivateKey privateKey = mock(PrivateKey.class); + + @BeforeAll + static void setUpForAll() throws IOException { + key = Files.readAllBytes(Path.of(KEY_PATH)); + } + + @Test + void convertKeystoreShouldReturnKeystoreWithGivenPrivateKeyAndCertificateChain() + throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, PemToPKCS12ConverterException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + final KeyStore expectedKeyStore = KeyStore.getInstance(PKCS12); + expectedKeyStore.load(new ByteArrayInputStream(Files.readAllBytes(Path.of(EXPECTED_KEYSTORE_PATH))), + password.toCharArray()); + final Certificate[] expectedChain = expectedKeyStore.getCertificateChain(alias); + privateKeyMockSetup(); + + // when + final byte[] result = converter.convertKeystore(certificateChain, password, alias, privateKey); + + // then + final KeyStore actualKeyStore = KeyStore.getInstance(PKCS12); + actualKeyStore.load(new ByteArrayInputStream(result), password.toCharArray()); + final Certificate[] actualChain = actualKeyStore.getCertificateChain(alias); + + assertArrayEquals(key, actualKeyStore.getKey(alias, password.toCharArray()).getEncoded()); + assertEquals(2, expectedChain.length); + assertArrayEquals(expectedChain, actualChain); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPassword() throws IOException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("apple"); + final List certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + privateKeyMockSetup(); + + // when + Exception exception = assertThrows(PemToPKCS12ConverterException.class, () -> + converter.convertKeystore(certificateChain, password, alias, privateKey) + ); + + // then + assertEquals(PASSWORD_ERROR_MSG, exception.getMessage()); + } + + @Test + void convertTruststoreShouldReturnTruststoreWithGivenCertificatesArray() + throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, PemToPKCS12ConverterException { + + // given + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + final String alias = "trusted-certificate-"; + final String alias1 = alias + 1; + final String alias2 = alias + 2; + final Password password = new Password("9z6oFx1epRSCuBWU4Er8i_0y"); + final List trustedCertificates = getCertificates(); + final KeyStore expectedTrustStore = KeyStore.getInstance(PKCS12); + expectedTrustStore.load(new ByteArrayInputStream(Files.readAllBytes(Path.of(EXPECTED_TRUSTSTORE_PATH))), + password.toCharArray()); + + // when + final byte[] result = converter.convertTruststore(trustedCertificates, password, alias); + + // then + final KeyStore actualKeyStore = KeyStore.getInstance(PKCS12); + actualKeyStore.load(new ByteArrayInputStream(result), password.toCharArray()); + + assertTrue(actualKeyStore.containsAlias(alias1)); + assertTrue(actualKeyStore.containsAlias(alias2)); + assertEquals(expectedTrustStore.getCertificate(alias1), actualKeyStore.getCertificate(alias1)); + assertEquals(expectedTrustStore.getCertificate(alias2), actualKeyStore.getCertificate(alias2)); + } + + @Test + void convertTruststoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPassword() throws IOException { + // given + final String alias = "trusted-certificate-"; + final Password password = new Password("nokia"); + final List trustedCertificates = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + + // when then + assertThatThrownBy(() -> + converter.convertTruststore(trustedCertificates, password, alias)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(PASSWORD_ERROR_MSG); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongPrivateKey() throws IOException { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List certificateChain = getCertificates(); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + + // when then + assertThatThrownBy(() -> converter.convertKeystore(certificateChain, password, alias, privateKey)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(KEY_ERROR_MSG); + } + + @Test + void convertKeystoreShouldThrowPemToPKCS12ConverterExceptionBecauseOfWrongCertificates() { + // given + final String alias = "keystore-entry"; + final Password password = new Password("d9D_u8LooYaXH4G48DtN#vw0"); + final List certificateChain = List.of("certificate1", "certificate2"); + final PemToPKCS12Converter converter = new PemToPKCS12Converter(); + privateKeyMockSetup(); + + // when then + assertThatThrownBy(() -> converter.convertKeystore(certificateChain, password, alias, privateKey)) + .isInstanceOf(PemToPKCS12ConverterException.class).hasMessage(CERTIFICATES_ERROR_MSG); + } + + private void privateKeyMockSetup() { + when(privateKey.getEncoded()).thenReturn(key); + when(privateKey.getAlgorithm()).thenReturn(EncryptionAlgorithmConstants.RSA_ENCRYPTION_ALGORITHM); + when(privateKey.getFormat()).thenReturn(PKCS8); + } + + private List getCertificates() throws IOException { + return List.of( + Files.readString( + Path.of(CERT1_PATH), StandardCharsets.UTF_8), + Files.readString( + Path.of(CERT2_PATH), StandardCharsets.UTF_8) + ); + } +} \ No newline at end of file diff --git a/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java new file mode 100644 index 00000000..169ce98a --- /dev/null +++ b/certServiceClient/src/test/java/org/onap/aaf/certservice/client/certification/conversion/RandomPasswordGeneratorTest.java @@ -0,0 +1,32 @@ +/*============LICENSE_START======================================================= + * aaf-certservice-client + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.aaf.certservice.client.certification.conversion; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; + +class RandomPasswordGeneratorTest { + + @Test + void shouldGenerateRandomPasswordOfGivenLengthMatchingThePattern() { + Password password = new RandomPasswordGenerator().generate(24); + assertTrue(password.isCorrectPasswordPattern()); + } +} \ No newline at end of file -- cgit 1.2.3-korg