github-advanced-security[bot] commented on code in PR #19828:
URL: https://github.com/apache/druid/pull/19828#discussion_r3684992904


##########
processing/src/main/java/org/apache/druid/crypto/CryptoService.java:
##########
@@ -132,29 +158,91 @@
   public byte[] decrypt(byte[] data)
   {
     try {
-      EncryptedData encryptedData = EncryptedData.fromByteArray(data);
-
-      SecretKey tmp = getKeyFromPassword(passPhrase, encryptedData.getSalt());
-      SecretKey secret = new SecretKeySpec(tmp.getEncoded(), cipherAlgName);
-
-      // error-prone warns if the transformation is not a compile-time constant
-      // since it cannot check it for insecure combinations.
-      @SuppressWarnings("InsecureCryptoUsage")
-      Cipher dcipher = Cipher.getInstance(transformation);
-      dcipher.init(Cipher.DECRYPT_MODE, secret, new 
IvParameterSpec(encryptedData.getIv()));
-      return dcipher.doFinal(encryptedData.getCipher());
+      if (hasAuthenticatedFormatMagic(data)) {
+        return decryptAuthenticated(data);
+      } else {
+        return decryptLegacy(EncryptedData.fromByteArray(data));
+      }
     }
     catch (Exception ex) {
       log.noStackTrace().warn(ex, "Decryption failed");
       throw InternalServerError.exception("Decryption failed. Check service 
logs.");
     }
   }
 
-  private SecretKey getKeyFromPassword(char[] passPhrase, byte[] salt)
+  private byte[] decryptAuthenticated(final byte[] data) throws Exception
+  {
+    Preconditions.checkArgument(
+        data.length >= AUTHENTICATED_FORMAT_HEADER.length
+        && Arrays.equals(
+            data,
+            0,
+            AUTHENTICATED_FORMAT_HEADER.length,
+            AUTHENTICATED_FORMAT_HEADER,
+            0,
+            AUTHENTICATED_FORMAT_HEADER.length
+        ),
+        "Unsupported encrypted data version"
+    );
+
+    final EncryptedData encryptedData = EncryptedData.fromByteArray(
+        Arrays.copyOfRange(data, AUTHENTICATED_FORMAT_HEADER.length, 
data.length)
+    );
+    Preconditions.checkArgument(encryptedData.getIv().length == GCM_IV_SIZE, 
"Invalid GCM IV size");
+
+    final SecretKey tmp = getKeyFromPassword(passPhrase, 
encryptedData.getSalt());
+    final SecretKey secret = new SecretKeySpec(tmp.getEncoded(), 
AUTHENTICATED_CIPHER_ALGORITHM);
+    final Cipher dcipher = 
Cipher.getInstance(AUTHENTICATED_CIPHER_TRANSFORMATION);
+    dcipher.init(
+        Cipher.DECRYPT_MODE,
+        secret,
+        new GCMParameterSpec(GCM_TAG_LENGTH_BITS, encryptedData.getIv())
+    );
+    dcipher.updateAAD(AUTHENTICATED_FORMAT_HEADER);
+    return dcipher.doFinal(encryptedData.getCipher());
+  }
+
+  /**
+   * Decrypts the unversioned CBC format written before authenticated 
encryption was introduced. This path is retained
+   * so that short-lived pac4j session cookies remain readable during rolling 
upgrades. New ciphertext is never written
+   * with this configurable transformation.
+   */
+  @SuppressWarnings({"InsecureCryptoUsage", 
"java/potentially-weak-cryptographic-algorithm"})
+  private byte[] decryptLegacy(final EncryptedData encryptedData) throws 
Exception
+  {
+    final SecretKey tmp = getKeyFromPassword(passPhrase, 
encryptedData.getSalt());
+    final SecretKey secret = new SecretKeySpec(tmp.getEncoded(), 
legacyCipherAlgName);
+    // This configurable transformation is used exclusively to read ciphertext 
written by earlier versions.
+    // codeql[java/potentially-weak-cryptographic-algorithm]
+    final Cipher dcipher = Cipher.getInstance(legacyTransformation);

Review Comment:
   ## CodeQL / Use of a potentially broken or risky cryptographic algorithm
   
   Cryptographic algorithm [CBC](1) may not be secure. Consider using a 
different algorithm.
   Cryptographic algorithm [PKCS5Padding](2) may not be secure. Consider using 
a different algorithm.
   Cryptographic algorithm [CBC](3) may not be secure. Consider using a 
different algorithm.
   Cryptographic algorithm [PKCS5Padding](4) may not be secure. Consider using 
a different algorithm.
   Cryptographic algorithm [%s/%s/%s](5) may not be secure. Consider using a 
different algorithm.
   
   [Show more 
details](https://github.com/apache/druid/security/code-scanning/11434)



##########
processing/src/main/java/org/apache/druid/crypto/CryptoService.java:
##########
@@ -132,29 +158,91 @@
   public byte[] decrypt(byte[] data)
   {
     try {
-      EncryptedData encryptedData = EncryptedData.fromByteArray(data);
-
-      SecretKey tmp = getKeyFromPassword(passPhrase, encryptedData.getSalt());
-      SecretKey secret = new SecretKeySpec(tmp.getEncoded(), cipherAlgName);
-
-      // error-prone warns if the transformation is not a compile-time constant
-      // since it cannot check it for insecure combinations.
-      @SuppressWarnings("InsecureCryptoUsage")
-      Cipher dcipher = Cipher.getInstance(transformation);
-      dcipher.init(Cipher.DECRYPT_MODE, secret, new 
IvParameterSpec(encryptedData.getIv()));
-      return dcipher.doFinal(encryptedData.getCipher());
+      if (hasAuthenticatedFormatMagic(data)) {
+        return decryptAuthenticated(data);
+      } else {
+        return decryptLegacy(EncryptedData.fromByteArray(data));
+      }
     }
     catch (Exception ex) {
       log.noStackTrace().warn(ex, "Decryption failed");
       throw InternalServerError.exception("Decryption failed. Check service 
logs.");
     }
   }
 
-  private SecretKey getKeyFromPassword(char[] passPhrase, byte[] salt)
+  private byte[] decryptAuthenticated(final byte[] data) throws Exception
+  {
+    Preconditions.checkArgument(
+        data.length >= AUTHENTICATED_FORMAT_HEADER.length
+        && Arrays.equals(
+            data,
+            0,
+            AUTHENTICATED_FORMAT_HEADER.length,
+            AUTHENTICATED_FORMAT_HEADER,
+            0,
+            AUTHENTICATED_FORMAT_HEADER.length
+        ),
+        "Unsupported encrypted data version"
+    );
+
+    final EncryptedData encryptedData = EncryptedData.fromByteArray(
+        Arrays.copyOfRange(data, AUTHENTICATED_FORMAT_HEADER.length, 
data.length)
+    );
+    Preconditions.checkArgument(encryptedData.getIv().length == GCM_IV_SIZE, 
"Invalid GCM IV size");
+
+    final SecretKey tmp = getKeyFromPassword(passPhrase, 
encryptedData.getSalt());
+    final SecretKey secret = new SecretKeySpec(tmp.getEncoded(), 
AUTHENTICATED_CIPHER_ALGORITHM);
+    final Cipher dcipher = 
Cipher.getInstance(AUTHENTICATED_CIPHER_TRANSFORMATION);
+    dcipher.init(
+        Cipher.DECRYPT_MODE,
+        secret,
+        new GCMParameterSpec(GCM_TAG_LENGTH_BITS, encryptedData.getIv())
+    );
+    dcipher.updateAAD(AUTHENTICATED_FORMAT_HEADER);
+    return dcipher.doFinal(encryptedData.getCipher());
+  }
+
+  /**
+   * Decrypts the unversioned CBC format written before authenticated 
encryption was introduced. This path is retained
+   * so that short-lived pac4j session cookies remain readable during rolling 
upgrades. New ciphertext is never written
+   * with this configurable transformation.
+   */
+  @SuppressWarnings({"InsecureCryptoUsage", 
"java/potentially-weak-cryptographic-algorithm"})
+  private byte[] decryptLegacy(final EncryptedData encryptedData) throws 
Exception
+  {
+    final SecretKey tmp = getKeyFromPassword(passPhrase, 
encryptedData.getSalt());
+    final SecretKey secret = new SecretKeySpec(tmp.getEncoded(), 
legacyCipherAlgName);
+    // This configurable transformation is used exclusively to read ciphertext 
written by earlier versions.
+    // codeql[java/potentially-weak-cryptographic-algorithm]
+    final Cipher dcipher = Cipher.getInstance(legacyTransformation);
+    dcipher.init(Cipher.DECRYPT_MODE, secret, new 
IvParameterSpec(encryptedData.getIv()));
+    return dcipher.doFinal(encryptedData.getCipher());
+  }
+
+  @SuppressWarnings("InsecureCryptoUsage")
+  private void validateLegacyCipherConfiguration()
+  {
+    try {
+      // Preserve eager validation of the backward-compatible decryption 
configuration.
+      // codeql[java/potentially-weak-cryptographic-algorithm]
+      Cipher.getInstance(legacyTransformation);

Review Comment:
   ## CodeQL / Use of a potentially broken or risky cryptographic algorithm
   
   Cryptographic algorithm [CBC](1) may not be secure. Consider using a 
different algorithm.
   Cryptographic algorithm [PKCS5Padding](2) may not be secure. Consider using 
a different algorithm.
   Cryptographic algorithm [CBC](3) may not be secure. Consider using a 
different algorithm.
   Cryptographic algorithm [PKCS5Padding](4) may not be secure. Consider using 
a different algorithm.
   Cryptographic algorithm [%s/%s/%s](5) may not be secure. Consider using a 
different algorithm.
   
   [Show more 
details](https://github.com/apache/druid/security/code-scanning/11435)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to