NIFI-12151 Fixed StandardPrivateKeyService fails due to missing BouncyCastleProvider

This closes #7817

Signed-off-by: David Handermann <exceptionfactory@apache.org>
This commit is contained in:
Peter Turcsanyi 2023-09-29 22:04:01 +02:00 committed by exceptionfactory
parent e93586df11
commit 8c5d85a28d
No known key found for this signature in database
GPG Key ID: 29B6A52D2AAE8DBA
2 changed files with 33 additions and 8 deletions

View File

@ -17,6 +17,7 @@
package org.apache.nifi.key.service.reader;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMException;
@ -42,6 +43,8 @@ import java.security.PrivateKey;
public class BouncyCastlePrivateKeyReader implements PrivateKeyReader {
private static final String INVALID_PEM = "Invalid PEM";
private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
/**
* Read Private Key using Bouncy Castle PEM Parser
*
@ -81,7 +84,9 @@ public class BouncyCastlePrivateKeyReader implements PrivateKeyReader {
private PrivateKeyInfo readEncryptedPrivateKey(final PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo, final char[] keyPassword) {
try {
final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(keyPassword);
final InputDecryptorProvider provider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
.setProvider(BOUNCY_CASTLE_PROVIDER)
.build(keyPassword);
return encryptedPrivateKeyInfo.decryptPrivateKeyInfo(provider);
} catch (final OperatorCreationException e) {
throw new PrivateKeyException("Preparing Private Key Decryption failed", e);
@ -91,7 +96,9 @@ public class BouncyCastlePrivateKeyReader implements PrivateKeyReader {
}
private PrivateKeyInfo readEncryptedPrivateKey(final PEMEncryptedKeyPair encryptedKeyPair, final char[] keyPassword) {
final PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder().build(keyPassword);
final PEMDecryptorProvider provider = new JcePEMDecryptorProviderBuilder()
.setProvider(BOUNCY_CASTLE_PROVIDER)
.build(keyPassword);
try {
final PEMKeyPair pemKeyPair = encryptedKeyPair.decryptKeyPair(provider);
return pemKeyPair.getPrivateKeyInfo();

View File

@ -21,7 +21,8 @@ import org.apache.nifi.util.NoOpProcessor;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.bouncycastle.openssl.PKCS8Generator;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
@ -30,6 +31,8 @@ import org.bouncycastle.operator.OutputEncryptor;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.io.IOException;
import java.io.StringWriter;
@ -42,11 +45,16 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.util.UUID;
import static org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.AES_256_CBC;
import static org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.DES3_CBC;
import static org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.PBE_SHA1_3DES;
import static org.junit.jupiter.api.Assertions.assertEquals;
class StandardPrivateKeyServiceTest {
private static final String SERVICE_ID = StandardPrivateKeyServiceTest.class.getSimpleName();
private static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
private static final String PATH_NOT_FOUND = "/path/not/found";
private static final String KEY_NOT_VALID = "-----BEGIN KEY NOT VALID-----";
@ -103,10 +111,11 @@ class StandardPrivateKeyServiceTest {
assertEquals(generatedPrivateKey, privateKey);
}
@Test
void testGetPrivateKeyEncryptedKey() throws Exception {
@ParameterizedTest
@MethodSource("encryptionAlgorithms")
void testGetPrivateKeyEncryptedKey(final String encryptionAlgorithm) throws Exception {
final String password = UUID.randomUUID().toString();
final OutputEncryptor outputEncryptor = getOutputEncryptor(password);
final OutputEncryptor outputEncryptor = getOutputEncryptor(encryptionAlgorithm, password);
final String encryptedPrivateKey = getEncodedPrivateKey(generatedPrivateKey, outputEncryptor);
final Path keyPath = writeKey(encryptedPrivateKey);
@ -118,6 +127,14 @@ class StandardPrivateKeyServiceTest {
assertEquals(generatedPrivateKey, privateKey);
}
private static String[] encryptionAlgorithms() {
return new String[] {
AES_256_CBC,
DES3_CBC,
PBE_SHA1_3DES
};
}
private Path writeKey(final String encodedPrivateKey) throws IOException {
final Path keyPath = Files.createTempFile(StandardPrivateKeyServiceTest.class.getSimpleName(), RSA_ALGORITHM);
keyPath.toFile().deleteOnExit();
@ -137,8 +154,9 @@ class StandardPrivateKeyServiceTest {
return stringWriter.toString();
}
private OutputEncryptor getOutputEncryptor(final String password) throws OperatorCreationException {
return new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_3DES)
private OutputEncryptor getOutputEncryptor(final String encryptionAlgorithm, final String password) throws OperatorCreationException {
return new JceOpenSSLPKCS8EncryptorBuilder(new ASN1ObjectIdentifier(encryptionAlgorithm))
.setProvider(BOUNCY_CASTLE_PROVIDER)
.setPassword(password.toCharArray())
.build();
}