This is an automated email from the ASF dual-hosted git repository.

pvillard31 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new b8487608eba NIFI-16499 Fixed tests for Encrypted Private Keys on Java 
25.0.5 (#11843)
b8487608eba is described below

commit b8487608eba1eaa35ead137a8dd88709bff2ae6b
Author: David Handermann <[email protected]>
AuthorDate: Fri Oct 23 14:23:41 2026 -0500

    NIFI-16499 Fixed tests for Encrypted Private Keys on Java 25.0.5 (#11843)
    
    - Added EncryptedPrivateKeyInfoEncoder with manual DER encoding to avoid 
behavior changes from JDK-8343232
---
 .../service/EncryptedPrivateKeyInfoEncoder.java    | 86 ++++++++++++++++++++++
 .../key/service/StandardPrivateKeyServiceTest.java | 28 +------
 .../reader/StandardPrivateKeyReaderTest.java       | 25 +------
 3 files changed, 91 insertions(+), 48 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/EncryptedPrivateKeyInfoEncoder.java
 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/EncryptedPrivateKeyInfoEncoder.java
new file mode 100644
index 00000000000..22caca0486e
--- /dev/null
+++ 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/EncryptedPrivateKeyInfoEncoder.java
@@ -0,0 +1,86 @@
+/*
+ * 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.key.service;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.util.HexFormat;
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+
+/**
+ * Encodes PKCS8 EncryptedPrivateKeyInfo for testing without using external 
libraries
+ */
+public final class EncryptedPrivateKeyInfoEncoder {
+    private static final HexFormat HEX_FORMAT = HexFormat.of();
+
+    private static final byte[] PBES2_OBJECT_IDENTIFIER = 
HEX_FORMAT.parseHex("06092a864886f70d01050d");
+    private static final String PBES2_CIPHER_PREFIX = "PBEWithHmac";
+
+    private static final int SEQUENCE_TAG = 0x30;
+    private static final int OCTET_STRING_TAG = 0x04;
+    private static final int LONG_FORM_LENGTH_FLAG = 0x80;
+
+    private EncryptedPrivateKeyInfoEncoder() {
+    }
+
+    /**
+     * Encode encrypted PKCS8 private key information using DER with 
constructing PBES2 AlgorithmParameters to avoid Java behavior changes
+     *
+     * @param cipher Cipher initialized for encryption, including algorithm 
parameters
+     * @param encrypted Encrypted private key
+     * @return DER encoded EncryptedPrivateKeyInfo
+     */
+    public static byte[] encode(final Cipher cipher, final byte[] encrypted) 
throws GeneralSecurityException, IOException {
+        final AlgorithmParameters cipherParameters = cipher.getParameters();
+        if (cipherParameters.getAlgorithm().startsWith(PBES2_CIPHER_PREFIX)) {
+            final byte[] parameters = cipherParameters.getEncoded();
+            final byte[] algorithmIdentifier = getDerEncoded(SEQUENCE_TAG, 
PBES2_OBJECT_IDENTIFIER, parameters);
+            final byte[] encryptedOctetString = 
getDerEncoded(OCTET_STRING_TAG, encrypted);
+            return getDerEncoded(SEQUENCE_TAG, algorithmIdentifier, 
encryptedOctetString);
+        }
+
+        return new EncryptedPrivateKeyInfo(cipherParameters, 
encrypted).getEncoded();
+    }
+
+    private static byte[] getDerEncoded(final int tag, final byte[]... 
contents) {
+        final ByteArrayOutputStream contentsStream = new 
ByteArrayOutputStream();
+        for (final byte[] content : contents) {
+            contentsStream.writeBytes(content);
+        }
+
+        final ByteArrayOutputStream encodedStream = new 
ByteArrayOutputStream();
+        encodedStream.write(tag);
+
+        final int length = contentsStream.size();
+        if (length < LONG_FORM_LENGTH_FLAG) {
+            encodedStream.write(length);
+        } else {
+            final byte[] signedLength = 
BigInteger.valueOf(length).toByteArray();
+            final int lengthOffset = signedLength[0] == 0 ? 1 : 0;
+            final int lengthBytes = signedLength.length - lengthOffset;
+            encodedStream.write(LONG_FORM_LENGTH_FLAG | lengthBytes);
+            encodedStream.write(signedLength, lengthOffset, lengthBytes);
+        }
+
+        encodedStream.writeBytes(contentsStream.toByteArray());
+        return encodedStream.toByteArray();
+    }
+}
diff --git 
a/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/StandardPrivateKeyServiceTest.java
 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/StandardPrivateKeyServiceTest.java
index 9fcb5965fac..fafa001a61f 100644
--- 
a/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/StandardPrivateKeyServiceTest.java
+++ 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/StandardPrivateKeyServiceTest.java
@@ -31,7 +31,6 @@ import org.junit.jupiter.params.provider.MethodSource;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.security.AlgorithmParameters;
 import java.security.GeneralSecurityException;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
@@ -41,7 +40,6 @@ import java.util.Base64;
 import java.util.Map;
 import java.util.UUID;
 import javax.crypto.Cipher;
-import javax.crypto.EncryptedPrivateKeyInfo;
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
@@ -63,10 +61,6 @@ class StandardPrivateKeyServiceTest {
 
     private static final String PBE_SHA1_DESEDE = "PBEWithSHA1AndDESede";
 
-    private static final String PBES2_ALGORITHM = "PBES2";
-
-    private static final String PBES2_CIPHER_PREFIX = "PBEWithHmac";
-
     private static final String PRIVATE_KEY_TYPE = "PRIVATE KEY";
 
     private static final String ENCRYPTED_PRIVATE_KEY_TYPE = "ENCRYPTED 
PRIVATE KEY";
@@ -178,26 +172,8 @@ class StandardPrivateKeyServiceTest {
         cipher.init(Cipher.ENCRYPT_MODE, secretKey);
         final byte[] encrypted = cipher.doFinal(privateKey.getEncoded());
 
-        final EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new 
EncryptedPrivateKeyInfo(getEncryptionParameters(cipher), encrypted);
-        return getPem(ENCRYPTED_PRIVATE_KEY_TYPE, 
encryptedPrivateKeyInfo.getEncoded());
-    }
-
-    /**
-     * Get encryption parameters with an algorithm name that 
EncryptedPrivateKeyInfo can resolve to an Object Identifier,
-     * which requires PBES2 instead of cipher names such as 
PBEWithHmacSHA256AndAES_256
-     */
-    private AlgorithmParameters getEncryptionParameters(final Cipher cipher) 
throws GeneralSecurityException, IOException {
-        final AlgorithmParameters cipherParameters = cipher.getParameters();
-
-        final AlgorithmParameters encryptionParameters;
-        if (cipherParameters.getAlgorithm().startsWith(PBES2_CIPHER_PREFIX)) {
-            encryptionParameters = 
AlgorithmParameters.getInstance(PBES2_ALGORITHM);
-            encryptionParameters.init(cipherParameters.getEncoded());
-        } else {
-            encryptionParameters = cipherParameters;
-        }
-
-        return encryptionParameters;
+        final byte[] encoded = EncryptedPrivateKeyInfoEncoder.encode(cipher, 
encrypted);
+        return getPem(ENCRYPTED_PRIVATE_KEY_TYPE, encoded);
     }
 
     private String getPem(final String type, final byte[] encoded) {
diff --git 
a/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/reader/StandardPrivateKeyReaderTest.java
 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/reader/StandardPrivateKeyReaderTest.java
index ee3c6491f11..8fb3419e5e2 100644
--- 
a/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/reader/StandardPrivateKeyReaderTest.java
+++ 
b/nifi-extension-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/test/java/org/apache/nifi/key/service/reader/StandardPrivateKeyReaderTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.key.service.reader;
 
+import org.apache.nifi.key.service.EncryptedPrivateKeyInfoEncoder;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
@@ -26,7 +27,6 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
-import java.security.AlgorithmParameters;
 import java.security.GeneralSecurityException;
 import java.security.KeyPairGenerator;
 import java.security.PrivateKey;
@@ -37,7 +37,6 @@ import java.util.HexFormat;
 import java.util.UUID;
 import java.util.stream.Stream;
 import javax.crypto.Cipher;
-import javax.crypto.EncryptedPrivateKeyInfo;
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
@@ -77,10 +76,6 @@ class StandardPrivateKeyReaderTest {
 
     private static final String PBE_SHA1_DESEDE = "PBEWithSHA1AndDESede";
 
-    private static final String PBES2_ALGORITHM = "PBES2";
-
-    private static final String PBES2_CIPHER_PREFIX = "PBEWithHmac";
-
     private static final String PBKDF2_HMAC_SHA256 = "PBKDF2WithHmacSHA256";
 
     private static final int PBKDF2_ITERATION_COUNT = 2048;
@@ -242,22 +237,8 @@ class StandardPrivateKeyReaderTest {
         cipher.init(Cipher.ENCRYPT_MODE, secretKey);
         final byte[] encrypted = cipher.doFinal(privateKey.getEncoded());
 
-        final EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new 
EncryptedPrivateKeyInfo(getEncryptionParameters(cipher), encrypted);
-        return getPem(ENCRYPTED_PRIVATE_KEY_TYPE, 
encryptedPrivateKeyInfo.getEncoded());
-    }
-
-    private static AlgorithmParameters getEncryptionParameters(final Cipher 
cipher) throws GeneralSecurityException, IOException {
-        final AlgorithmParameters cipherParameters = cipher.getParameters();
-
-        final AlgorithmParameters encryptionParameters;
-        if (cipherParameters.getAlgorithm().startsWith(PBES2_CIPHER_PREFIX)) {
-            encryptionParameters = 
AlgorithmParameters.getInstance(PBES2_ALGORITHM);
-            encryptionParameters.init(cipherParameters.getEncoded());
-        } else {
-            encryptionParameters = cipherParameters;
-        }
-
-        return encryptionParameters;
+        final byte[] encoded = EncryptedPrivateKeyInfoEncoder.encode(cipher, 
encrypted);
+        return getPem(ENCRYPTED_PRIVATE_KEY_TYPE, encoded);
     }
 
     private static String getPbes2DesEde3Pem(final PrivateKey privateKey) 
throws GeneralSecurityException {

Reply via email to