diff --git a/presto-docs/src/main/sphinx/security/password-file.rst b/presto-docs/src/main/sphinx/security/password-file.rst index 5ea6f1522818a..4939262e86157 100644 --- a/presto-docs/src/main/sphinx/security/password-file.rst +++ b/presto-docs/src/main/sphinx/security/password-file.rst @@ -36,6 +36,42 @@ Property Description Defaults to ``1000``. ==================================== ============================================== +Password Validation +------------------- + +Password validation in Presto supports both `PBKDF2WithHmacSHA256` and `PBKDF2WithHmacSHA1` algorithms. +To ensure modern cryptographic standards, clients are encouraged to use `PBKDF2WithHmacSHA256`. +A fallback mechanism is available to maintain compatibility with legacy systems using `PBKDF2WithHmacSHA1`. + +Migration to `PBKDF2WithHmacSHA256` is strongly recommended to maintain security. + +API Method +^^^^^^^^^^ +The following method uses the `PBKDF2WithHmacSHA256` validation mechanism and includes a fallback mechanism: + +.. code-block:: java + + /** + * @Deprecated using PBKDF2WithHmacSHA1 is deprecated and clients should switch to PBKDF2WithHmacSHA256 + */ + public static boolean doesPBKDF2PasswordMatch(String inputPassword, String hashedPassword) + { + PBKDF2Password password = PBKDF2Password.fromString(hashedPassword); + + // Validate using PBKDF2WithHmacSHA256 + if (validatePBKDF2Password(inputPassword, password, "PBKDF2WithHmacSHA256")) { + return true; + } + + // Fallback to PBKDF2WithHmacSHA1 + LOG.warn("Using deprecated PBKDF2WithHmacSHA1 for password validation."); + return validatePBKDF2Password(inputPassword, password, "PBKDF2WithHmacSHA1"); + } + +**Fallback Mechanism** + +If `PBKDF2WithHmacSHA256` fails for legacy reasons, the system gracefully falls back to `PBKDF2WithHmacSHA1` while logging a warning. + Password Files -------------- diff --git a/presto-password-authenticators/src/main/java/com/facebook/presto/password/file/EncryptionUtil.java b/presto-password-authenticators/src/main/java/com/facebook/presto/password/file/EncryptionUtil.java index 2aa6349923719..40334558715a6 100644 --- a/presto-password-authenticators/src/main/java/com/facebook/presto/password/file/EncryptionUtil.java +++ b/presto-password-authenticators/src/main/java/com/facebook/presto/password/file/EncryptionUtil.java @@ -15,6 +15,7 @@ import at.favre.lib.crypto.bcrypt.BCrypt; import at.favre.lib.crypto.bcrypt.IllegalBCryptFormatException; +import com.facebook.airlift.log.Logger; import com.google.common.base.Splitter; import javax.crypto.SecretKeyFactory; @@ -33,6 +34,7 @@ public final class EncryptionUtil { + private static final Logger LOG = Logger.get(EncryptionUtil.class); private static final int BCRYPT_MIN_COST = 8; private static final int PBKDF2_MIN_ITERATIONS = 1000; @@ -58,14 +60,29 @@ public static boolean doesBCryptPasswordMatch(String inputPassword, String hashe return BCrypt.verifyer().verify(inputPassword.toCharArray(), hashedPassword).verified; } + /** + * @Deprecated using PBKDF2WithHmacSHA1 is deprecated and clients should switch to PBKDF2WithHmacSHA256 + */ public static boolean doesPBKDF2PasswordMatch(String inputPassword, String hashedPassword) { PBKDF2Password password = PBKDF2Password.fromString(hashedPassword); + // Validate using PBKDF2WithHmacSHA256 + if (validatePBKDF2Password(inputPassword, password, "PBKDF2WithHmacSHA256")) { + return true; + } + + // Fallback to PBKDF2WithHmacSHA1 + LOG.warn("Using deprecated PBKDF2WithHmacSHA1 for password validation."); + return validatePBKDF2Password(inputPassword, password, "PBKDF2WithHmacSHA1"); + } + + private static boolean validatePBKDF2Password(String inputPassword, PBKDF2Password password, String algorithm) + { try { KeySpec spec = new PBEKeySpec(inputPassword.toCharArray(), password.salt(), password.iterations(), password.hash().length * 8); - SecretKeyFactory key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); - byte[] inputHash = key.generateSecret(spec).getEncoded(); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); + byte[] inputHash = keyFactory.generateSecret(spec).getEncoded(); if (password.hash().length != inputHash.length) { throw new HashedPasswordException("PBKDF2 password input is malformed");