Class PasswordUtil

    • Field Detail

      • SHA256_LENGTH

        public static final int SHA256_LENGTH
        The SHA256 hash length
        See Also:
        Constant Field Values
      • SHA384_LENGTH

        public static final int SHA384_LENGTH
        The SHA384 hash length
        See Also:
        Constant Field Values
      • SHA512_LENGTH

        public static final int SHA512_LENGTH
        The SHA512 hash length
        See Also:
        Constant Field Values
      • PKCS5S2_LENGTH

        public static final int PKCS5S2_LENGTH
        The PKCS5S2 hash length
        See Also:
        Constant Field Values
      • CRYPT_LENGTH

        public static final int CRYPT_LENGTH
        The CRYPT (DES) hash length
        See Also:
        Constant Field Values
      • CRYPT_MD5_LENGTH

        public static final int CRYPT_MD5_LENGTH
        The CRYPT (MD5) hash length
        See Also:
        Constant Field Values
      • CRYPT_SHA256_LENGTH

        public static final int CRYPT_SHA256_LENGTH
        The CRYPT (SHA-256) hash length
        See Also:
        Constant Field Values
      • CRYPT_SHA512_LENGTH

        public static final int CRYPT_SHA512_LENGTH
        The CRYPT (SHA-512) hash length
        See Also:
        Constant Field Values
      • CRYPT_BCRYPT_LENGTH

        public static final int CRYPT_BCRYPT_LENGTH
        The CRYPT (BCrypt) hash length
        See Also:
        Constant Field Values
      • CRYPT_SALT_CHARS

        private static final byte[] CRYPT_SALT_CHARS
    • Constructor Detail

      • PasswordUtil

        private PasswordUtil()
    • Method Detail

      • findAlgorithm

        public static LdapSecurityConstants findAlgorithm​(byte[] credentials)
        Get the algorithm from the stored password. It can be found on the beginning of the stored password, between curly brackets.
        Parameters:
        credentials - the credentials of the user
        Returns:
        the name of the algorithm to use
      • createStoragePassword

        public static byte[] createStoragePassword​(byte[] credentials,
                                                   LdapSecurityConstants algorithm)
        create a hashed password in a format that can be stored in the server. If the specified algorithm requires a salt then a random salt of 8 byte size is used
        Parameters:
        credentials - the plain text password
        algorithm - the hashing algorithm to be applied
        Returns:
        the password after hashing with the given algorithm
      • compareCredentials

        public static boolean compareCredentials​(byte[] receivedCredentials,
                                                 byte[] storedCredentials)
        Compare the credentials. We have at least 6 algorithms to encrypt the password :
        • - SHA
        • - SSHA (salted SHA)
        • - SHA-2(256, 384 and 512 and their salted versions)
        • - MD5
        • - SMD5 (slated MD5)
        • - PKCS5S2 (PBKDF2)
        • - crypt (unix crypt)
        • - plain text, ie no encryption.

        If we get an encrypted password, it is prefixed by the used algorithm, between brackets : {SSHA}password ...

        If the password is using SSHA, SMD5 or crypt, some 'salt' is added to the password :
        • - length(password) - 20, starting at 21st position for SSHA
        • - length(password) - 16, starting at 16th position for SMD5
        • - length(password) - 2, starting at 3rd position for crypt

        For (S)SHA, SHA-256 and (S)MD5, we have to transform the password from Base64 encoded text to a byte[] before comparing the password with the stored one.

        For PKCS5S2 the salt is stored in the beginning of the password

        For crypt, we only have to remove the salt.

        At the end, we use the digest() method for (S)SHA and (S)MD5, the crypt() method for the CRYPT algorithm and a straight comparison for PLAIN TEXT passwords.

        The stored password is always using the unsalted form, and is stored as a bytes array.

        Parameters:
        receivedCredentials - the credentials provided by user
        storedCredentials - the credentials stored in the server
        Returns:
        true if they are equal, false otherwise
      • compareBytes

        private static boolean compareBytes​(byte[] provided,
                                            byte[] stored)
        Compare two byte[] in a constant time. This is necessary because using an Array.equals() is not Timing attack safe ([1], [2] and [3]), a breach that can be exploited to break some hashes. [1] https://en.wikipedia.org/wiki/Timing_attack [2] http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/ [3] https://cryptocoding.net/index.php/Coding_rules
        Parameters:
        provided - The provided password
        stored - The stored password
        Returns:
        true if the compared passwords are equal
      • encryptPassword

        private static byte[] encryptPassword​(byte[] credentials,
                                              LdapSecurityConstants algorithm,
                                              byte[] salt)
        encrypts the given credentials based on the algorithm name and optional salt
        Parameters:
        credentials - the credentials to be encrypted
        algorithm - the algorithm to be used for encrypting the credentials
        salt - value to be used as salt (optional)
        Returns:
        the encrypted credentials
      • digest

        private static byte[] digest​(LdapSecurityConstants algorithm,
                                     byte[] password,
                                     byte[] salt)
        Compute the hashed password given an algorithm, the credentials and an optional salt.
        Parameters:
        algorithm - the algorithm to use
        password - the credentials
        salt - the optional salt
        Returns:
        the digested credentials
      • splitCredentials

        public static PasswordDetails splitCredentials​(byte[] credentials)
        Decompose the stored password in an algorithm, an eventual salt and the password itself. If the algorithm is SHA, SSHA, MD5 or SMD5, the part following the algorithm is base64 encoded
        Parameters:
        credentials - The byte[] containing the credentials to split
        Returns:
        The password
      • getCredentials

        private static PasswordDetails getCredentials​(byte[] credentials,
                                                      int algoLength,
                                                      int hashLen,
                                                      LdapSecurityConstants algorithm)
        Compute the credentials
        Parameters:
        credentials - the credentials
        algoLength - The algorithm length
        hashLen - The hash length
        algorithm - the algorithm to use
        Returns:
        The split password string, containing the credentials, the salt and the password
      • split

        private static void split​(byte[] all,
                                  int offset,
                                  byte[] left,
                                  byte[] right)
      • merge

        private static void merge​(byte[] all,
                                  byte[] left,
                                  byte[] right)
      • isPwdExpired

        public static boolean isPwdExpired​(String pwdChangedZtime,
                                           int pwdMaxAgeSec,
                                           org.apache.directory.api.util.TimeProvider timeProvider)
        checks if the given password's change time is older than the max age
        Parameters:
        pwdChangedZtime - time when the password was last changed
        pwdMaxAgeSec - the max age value in seconds
        timeProvider - The TimeProvider instance to use
        Returns:
        true if expired, false otherwise
      • generatePbkdf2Hash

        private static byte[] generatePbkdf2Hash​(byte[] credentials,
                                                 LdapSecurityConstants algorithm,
                                                 byte[] salt)
        generates a hash based on the PKCS5S2 spec Note: this has been implemented to generate hashes compatible with what JIRA generates. See the JIRA's passlib
        Parameters:
        credentials - the credentials
        algorithm - the algorithm to use
        salt - the optional salt
        Returns:
        the digested credentials
      • getPbkdf2Credentials

        private static PasswordDetails getPbkdf2Credentials​(byte[] credentials,
                                                            int algoLength,
                                                            LdapSecurityConstants algorithm)
        Gets the credentials from a PKCS5S2 hash. The salt for PKCS5S2 hash is prepended to the password
        Parameters:
        credentials - The password
        algoLength - The length of the algorithm part
        algorithm - The algorithm in use
        Returns:
        The split credentials, containing the algorithm, the salt and the password
      • generateCryptSalt

        private static byte[] generateCryptSalt​(int length)