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

enapps-enorman pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-base.git


The following commit(s) were added to refs/heads/master by this push:
     new e4c70d5  SLING-13223 Improve TopologyRequestValidator encryption (#21)
e4c70d5 is described below

commit e4c70d56889bcf2522b3fb49ea5f3a33417e9254
Author: Eric Norman <[email protected]>
AuthorDate: Fri May 29 13:40:53 2026 -0700

    SLING-13223 Improve TopologyRequestValidator encryption (#21)
---
 pom.xml                                            |  14 ++-
 .../connectors/ping/TopologyRequestValidator.java  | 103 +++++++++------------
 2 files changed, 57 insertions(+), 60 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8cd16e7..937f9ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,8 @@
 
     <properties>
         <jackrabbit.version>2.14.3</jackrabbit.version>
+        <surefire.maxmem>-Xmx2048m</surefire.maxmem>
+        <surefire.argline>${surefire.maxmem}</surefire.argline>
     </properties>
 
     <build>
@@ -51,7 +53,7 @@
                  <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
                     <redirectTestOutputToFile>true</redirectTestOutputToFile>
-                    <argLine>-Xmx2048m</argLine>
+                    <argLine>${surefire.argline}</argLine>
                     
<excludedGroups>${sling.excluded.surefire.groups}</excludedGroups>
                 </configuration>
             </plugin>
@@ -285,4 +287,14 @@
         </dependency>
     </dependencies>
 
+    <profiles>
+        <!-- override to pass the extra jacoco arguments to surefire-->
+        <profile>
+            <id>jacoco-report</id>
+            <properties>
+                <surefire.argline>${surefire.maxmem} 
${jacoco.command}</surefire.argline>
+            </properties>
+        </profile>
+    </profiles>
+
 </project>
diff --git 
a/src/main/java/org/apache/sling/discovery/base/connectors/ping/TopologyRequestValidator.java
 
b/src/main/java/org/apache/sling/discovery/base/connectors/ping/TopologyRequestValidator.java
index a5f9545..c1a0e38 100644
--- 
a/src/main/java/org/apache/sling/discovery/base/connectors/ping/TopologyRequestValidator.java
+++ 
b/src/main/java/org/apache/sling/discovery/base/connectors/ping/TopologyRequestValidator.java
@@ -21,7 +21,7 @@ import java.io.IOException;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
-import java.security.AlgorithmParameters;
+import java.nio.charset.StandardCharsets;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
@@ -29,7 +29,6 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.spec.InvalidKeySpecException;
-import java.security.spec.InvalidParameterSpecException;
 import java.security.spec.KeySpec;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -45,7 +44,7 @@ import javax.crypto.Mac;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.GCMParameterSpec;
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.SecretKeySpec;
 import jakarta.json.Json;
@@ -83,6 +82,16 @@ public class TopologyRequestValidator {
      */
     private static final int MINKEYS = 3;
 
+    /**
+     * GCM authentication tag length in bits.
+     */
+    private static final int GCM_TAG_LENGTH = 128;
+
+    /**
+     * GCM nonce length in bytes.
+     */
+    private static final int GCM_NONCE_LENGTH = 12;
+
     /**
      * true if trust information should be in request headers.
      */
@@ -153,24 +162,9 @@ public class TopologyRequestValidator {
                 StringWriter writer = new StringWriter();
                 Json.createGenerator(writer).write(json.build()).close();
                 return writer.toString();
-            } catch (InvalidKeyException e) {
-                e.printStackTrace();
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (IllegalBlockSizeException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (BadPaddingException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (UnsupportedEncodingException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (NoSuchAlgorithmException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (NoSuchPaddingException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (JsonException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (InvalidKeySpecException e) {
-                throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
-            } catch (InvalidParameterSpecException e) {
+            } catch (InvalidKeyException | IllegalBlockSizeException | 
BadPaddingException | NoSuchAlgorithmException
+                    | NoSuchPaddingException | JsonException | 
InvalidKeySpecException
+                    | InvalidAlgorithmParameterException e) {
                 throw new IOException("Unable to Encrypt Message " + 
e.getMessage());
             }
 
@@ -227,22 +221,10 @@ public class TopologyRequestValidator {
                         if (json.containsKey("payload")) {
                             return decrypt(json.getJsonArray("payload"));
                         }
-                    } catch (JsonException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (InvalidKeyException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (IllegalBlockSizeException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (BadPaddingException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (NoSuchAlgorithmException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (NoSuchPaddingException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (InvalidAlgorithmParameterException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
-                    } catch (InvalidKeySpecException e) {
-                        throw new IOException("Encrypted Message is in the 
correct json format");
+                    } catch (JsonException | InvalidKeyException | 
IllegalBlockSizeException | BadPaddingException
+                            | NoSuchAlgorithmException | 
NoSuchPaddingException | InvalidAlgorithmParameterException
+                            | InvalidKeySpecException e) {
+                        throw new IOException("Encrypted Message is not in the 
correct json format");
                     }
 
                 }
@@ -419,9 +401,9 @@ public class TopologyRequestValidator {
     }
 
     /**
-     * Decrypt the body.
+     * Decrypt the body using AES/GCM mode with authenticated encryption.
      *
-     * @param jsonArray the encrypted payload
+     * @param jsonArray the encrypted payload (nonce, ciphertext, authTag)
      * @return the decrypted payload.
      * @throws IllegalBlockSizeException
      * @throws BadPaddingException
@@ -433,18 +415,21 @@ public class TopologyRequestValidator {
      * @throws InvalidAlgorithmParameterException
      */
     private String decrypt(JsonArray jsonArray) throws 
IllegalBlockSizeException,
-            BadPaddingException, UnsupportedEncodingException, 
InvalidKeyException,
-            NoSuchAlgorithmException, NoSuchPaddingException, 
InvalidAlgorithmParameterException, InvalidKeySpecException {
-        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        cipher.init(Cipher.DECRYPT_MODE, 
getCipherKey(Base64.decodeBase64(jsonArray.get(0).toString().getBytes("UTF-8"))),
 new 
IvParameterSpec(Base64.decodeBase64(jsonArray.get(1).toString().getBytes("UTF-8"))));
-        return new 
String(cipher.doFinal(Base64.decodeBase64(jsonArray.get(2).toString().getBytes("UTF-8"))));
+            BadPaddingException, InvalidKeyException, NoSuchAlgorithmException,
+            NoSuchPaddingException, InvalidAlgorithmParameterException, 
InvalidKeySpecException {
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        byte[] nonce = 
Base64.decodeBase64(jsonArray.get(0).toString().getBytes(StandardCharsets.UTF_8));
+        byte[] ciphertext = 
Base64.decodeBase64(jsonArray.get(1).toString().getBytes(StandardCharsets.UTF_8));
+        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, nonce);
+        cipher.init(Cipher.DECRYPT_MODE, getCipherKey(nonce), spec);
+        return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8);
     }
 
     /**
-     * Encrypt a payload with the numbed key/
+     * Encrypt a payload with AES/GCM mode with authenticated encryption.
      *
      * @param payload the payload.
-     * @return an encrypted version.
+     * @return an encrypted version (nonce, ciphertext).
      * @throws IllegalBlockSizeException
      * @throws BadPaddingException
      * @throws UnsupportedEncodingException
@@ -452,20 +437,20 @@ public class TopologyRequestValidator {
      * @throws NoSuchAlgorithmException
      * @throws NoSuchPaddingException
      * @throws InvalidKeySpecException
-     * @throws InvalidParameterSpecException
+     * @throws InvalidAlgorithmParameterException
      */
     private List<String> encrypt(String payload) throws 
IllegalBlockSizeException,
-            BadPaddingException, UnsupportedEncodingException, 
InvalidKeyException,
-            NoSuchAlgorithmException, NoSuchPaddingException, 
InvalidKeySpecException, InvalidParameterSpecException {
-        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-        byte[] salt = new byte[9];
-        random.nextBytes(salt);
-        cipher.init(Cipher.ENCRYPT_MODE, getCipherKey(salt));
-        AlgorithmParameters params = cipher.getParameters();
-        List<String> encrypted = new ArrayList<String>();
-        encrypted.add(new String(Base64.encodeBase64(salt)));
-        encrypted.add(new 
String(Base64.encodeBase64(params.getParameterSpec(IvParameterSpec.class).getIV())));
-        encrypted.add(new 
String(Base64.encodeBase64(cipher.doFinal(payload.getBytes("UTF-8")))));
+            BadPaddingException, InvalidKeyException, NoSuchAlgorithmException,
+            NoSuchPaddingException, InvalidKeySpecException, 
InvalidAlgorithmParameterException {
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        byte[] nonce = new byte[GCM_NONCE_LENGTH];
+        random.nextBytes(nonce);
+        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, nonce);
+        cipher.init(Cipher.ENCRYPT_MODE, getCipherKey(nonce), spec);
+        byte[] ciphertext = 
cipher.doFinal(payload.getBytes(StandardCharsets.UTF_8));
+        List<String> encrypted = new ArrayList<>();
+        encrypted.add(new String(Base64.encodeBase64(nonce), 
StandardCharsets.UTF_8));
+        encrypted.add(new String(Base64.encodeBase64(ciphertext), 
StandardCharsets.UTF_8));
         return encrypted;
     }
 
@@ -480,7 +465,7 @@ public class TopologyRequestValidator {
         // The NIST guidelines suggest the iteration count to be at least 10000
         // Using longer hashes (SHA-256 and higher) increases the attacker's 
costs
         SecretKeyFactory factory = 
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
-        KeySpec spec = new PBEKeySpec(sharedKey.toCharArray(), salt, 10000, 
128);
+        KeySpec spec = new PBEKeySpec(sharedKey.toCharArray(), salt, 10000, 
256);
         SecretKey tmp = factory.generateSecret(spec);
         return new SecretKeySpec(tmp.getEncoded(), "AES");
     }

Reply via email to