/*
 * 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.jackrabbit.oak.spi.security.user.util;

import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.util.Text;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Utility to generate and compare password hashes.
 */
public final class PasswordUtil {

    private static final Logger log = LoggerFactory.getLogger(PasswordUtil.class);

    private static final char DELIMITER = '-';
    private static final int NO_ITERATIONS = 1;
    private static final String ENCODING = "UTF-8";

    /**
     * @since OAK 1.0
     */
    static final String PBKDF2_PREFIX = "PBKDF2";
    
    public static final String DEFAULT_ALGORITHM = "SHA-256";
    public static final int DEFAULT_SALT_SIZE = 8;
    public static final int DEFAULT_ITERATIONS = 1000;

    /**
     * Avoid instantiation
     */
    private PasswordUtil() {}

    /**
     * Generates a hash of the specified password with the default values
     * for algorithm, salt-size and number of iterations.
     *
     * @param password The password to be hashed.
     * @return The password hash.
     * @throws NoSuchAlgorithmException If {@link #DEFAULT_ALGORITHM} is not supported.
     * @throws UnsupportedEncodingException If utf-8 is not supported.
     */
    public static String buildPasswordHash(@NotNull String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        return buildPasswordHash(password, DEFAULT_ALGORITHM, DEFAULT_SALT_SIZE, DEFAULT_ITERATIONS);
    }

    /**
     * Generates a hash of the specified password using the specified algorithm,
     * salt size and number of iterations into account.
     *
     * @param password The password to be hashed.
     * @param algorithm The desired hash algorithm. If the algorith is
     * {@code null} the {@link #DEFAULT_ALGORITHM} will be used.
     * @param saltSize The desired salt size. If the specified integer is lower
     * that {@link #DEFAULT_SALT_SIZE} the default is used.
     * @param iterations The desired number of iterations. If the specified
     * integer is lower than 1 the {@link #DEFAULT_ITERATIONS default} value is used.
     * @return  The password hash.
     * @throws NoSuchAlgorithmException If the specified algorithm is not supported.
     * @throws UnsupportedEncodingException If utf-8 is not supported.
     */
    public static String buildPasswordHash(@NotNull String password,
                                           @Nullable String algorithm,
                                           int saltSize, int iterations) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        checkNotNull(password);
        if (iterations < NO_ITERATIONS) {
            iterations = DEFAULT_ITERATIONS;
        }
        if (saltSize < DEFAULT_SALT_SIZE) {
            saltSize = DEFAULT_SALT_SIZE;
        }
        String salt = generateSalt(saltSize);
        String alg = (algorithm == null) ? DEFAULT_ALGORITHM : algorithm;
        return generateHash(password, alg, salt, iterations);
    }

    /**
     * Same as {@link #buildPasswordHash(String, String, int, int)} but retrieving
     * the parameters for hash generation from the specified configuration.
     *
     * @param password The password to be hashed.
     * @param config The configuration defining the details of the hash generation.
     * @return The password hash.
     * @throws NoSuchAlgorithmException If the specified algorithm is not supported.
     * @throws UnsupportedEncodingException If utf-8 is not supported.
     */
    public static String buildPasswordHash(@NotNull String password,
                                           @NotNull ConfigurationParameters config) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        checkNotNull(config);
        String algorithm = config.getConfigValue(UserConstants.PARAM_PASSWORD_HASH_ALGORITHM, DEFAULT_ALGORITHM);
        int iterations = config.getConfigValue(UserConstants.PARAM_PASSWORD_HASH_ITERATIONS, DEFAULT_ITERATIONS);
        int saltSize = config.getConfigValue(UserConstants.PARAM_PASSWORD_SALT_SIZE, DEFAULT_SALT_SIZE);

        return buildPasswordHash(password, algorithm, saltSize, iterations);
    }

    /**
     * Returns {@code true} if the specified string doesn't start with a
     * valid algorithm name in curly brackets.
     *
     * @param password The string to be tested.
     * @return {@code true} if the specified string doesn't start with a
     * valid algorithm name in curly brackets.
     */
    public static boolean isPlainTextPassword(@Nullable String password) {
        return extractAlgorithm(password) == null;
    }

    /**
     * Returns {@code true} if hash of the specified {@code password} equals the
     * given hashed password.
     *
     * @param hashedPassword Password hash.
     * @param password The password to compare.
     * @return If the hash created from the specified {@code password} equals
     * the given {@code hashedPassword} string.
     */
    public static boolean isSame(@Nullable String hashedPassword, @NotNull char[] password) {
        return isSame(hashedPassword, String.valueOf(password));
    }

    /**
     * Returns {@code true} if hash of the specified {@code password} equals the
     * given hashed password.
     *
     * @param hashedPassword Password hash.
     * @param password The password to compare.
     * @return If the hash created from the specified {@code password} equals
     * the given {@code hashedPassword} string.
     */
    public static boolean isSame(@Nullable String hashedPassword, @NotNull String password) {
        if (hashedPassword == null || password == null) {
            return false;
        }
        try {
            String algorithm = extractAlgorithm(hashedPassword);
            if (algorithm != null) {
                int startPos = algorithm.length()+2;
                String salt = extractSalt(hashedPassword, startPos);
                int iterations = NO_ITERATIONS;
                if (salt != null) {
                    startPos += salt.length()+1;
                    iterations = extractIterations(hashedPassword, startPos);
                }

                String hash = generateHash(password, algorithm, salt, iterations);
                return compareSecure(hashedPassword, hash);
            } // hashedPassword is plaintext -> return false
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            log.warn(e.getMessage());
        }
        return false;
    }
    
    //------------------------------------------------------------< private >---
    /**
     * Compare two strings. The comparison is constant time: it will always loop
     * over all characters and doesn't use conditional operations in the loop to
     * make sure an attacker can not use a timing attack.
     *
     * @param a
     * @param b
     * @return true if both parameters contain the same data.
     */
    private static boolean compareSecure(@NotNull String a, @NotNull String b) {
        int len = a.length();
        if (len != b.length()) {
            return false;
        }
        if (len == 0) {
            return true;
        }
        // don't use conditional operations inside the loop
        int bits = 0;
        for (int i = 0; i < len; i++) {
            // this will never reset any bits
            bits |= a.charAt(i) ^ b.charAt(i);
        }
        return bits == 0;
    }

    @NotNull
    private static String generateHash(@NotNull String pwd, @NotNull String algorithm,
                                       @Nullable String salt, int iterations) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        StringBuilder passwordHash = new StringBuilder();
        passwordHash.append('{').append(algorithm).append('}');
        if (salt != null && !salt.isEmpty()) {
            StringBuilder data = new StringBuilder();
            data.append(salt).append(pwd);

            passwordHash.append(salt).append(DELIMITER);
            if (iterations > NO_ITERATIONS) {
                passwordHash.append(iterations).append(DELIMITER);
            }
            String digest;
            if (algorithm.startsWith(PBKDF2_PREFIX)) {
                digest = generatePBKDF2(pwd, salt, algorithm, iterations, 128);
            } else {
                digest = generateDigest(data.toString(), algorithm, iterations);
            }
            passwordHash.append(digest);
        } else {
            // backwards compatible to jr 2.0: no salt, no iterations
            passwordHash.append(Text.digest(algorithm, pwd.getBytes(ENCODING)));
        }
        return passwordHash.toString();
    }

    @NotNull
    private static String generateSalt(int saltSize) {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[saltSize];
        random.nextBytes(salt);

        return convertBytesToHex(salt);
    }
    
    /**
     * Convert a byte array to a hex encoded string.
     *
     * @param bytes the byte array
     * @return the hex encoded string
     */
    @NotNull
    private static String convertBytesToHex(byte[] bytes) {
        StringBuilder res = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            res.append(Text.hexTable[(b >> 4) & 15]);
            res.append(Text.hexTable[b & 15]);
        }
        return res.toString();
    }
    
    /**
     * Convert a hex encoded string to a byte array.
     *
     * @param s the hex encoded string
     * @return the byte array
     */
    @NotNull
    private static byte[] convertHexToBytes(String s) {
        int len = s.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Not a hex encoded byte array: " + s);
        }
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (
                    (Character.digit(s.charAt(i + i), 16) << 4) + 
                    Character.digit(s.charAt(i + i + 1), 16));
        }
        return bytes;
    }

    @NotNull
    private static String generatePBKDF2(@NotNull String pwd, @NotNull String salt,
                                         @NotNull String algorithm, int iterations, int keyLength) throws NoSuchAlgorithmException {
        // for example PBKDF2WithHmacSHA1
        SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
        byte[] saltBytes = convertHexToBytes(salt);
        KeySpec keyspec = new PBEKeySpec(pwd.toCharArray(), saltBytes, iterations, keyLength);
        try {
            Key key = factory.generateSecret(keyspec);
            byte[] bytes = key.getEncoded();
            return convertBytesToHex(bytes);
        } catch (InvalidKeySpecException e) {
            throw new NoSuchAlgorithmException(algorithm, e);
        }  
    }

    @NotNull
    private static String generateDigest(@NotNull String data, @NotNull String algorithm, int iterations) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        byte[] bytes = data.getBytes(ENCODING);
        MessageDigest md = MessageDigest.getInstance(algorithm);

        for (int i = 0; i < iterations; i++) {
            md.reset();
            bytes = md.digest(bytes);
        }

        return convertBytesToHex(bytes);
    }

    /**
     * Extract the algorithm from the given crypted password string. Returns the
     * algorithm or {@code null} if the given string doesn't have a
     * leading {@code algorithm} such as created by {@code buildPasswordHash}
     * or if the extracted string doesn't represent an available algorithm.
     *
     * @param hashedPwd The password hash.
     * @return The algorithm or {@code null} if the given string doesn't have a
     * leading {@code algorithm} such as created by {@code buildPasswordHash}
     * or if the extracted string isn't a supported algorithm.
     */
    @Nullable
    private static String extractAlgorithm(@Nullable String hashedPwd) {
        if (hashedPwd != null && !hashedPwd.isEmpty()) {
            int end = hashedPwd.indexOf('}');
            if (hashedPwd.charAt(0) == '{' && end > 0 && end < hashedPwd.length()-1) {
                String algorithm = hashedPwd.substring(1, end);
                try {
                    if (algorithm.startsWith(PBKDF2_PREFIX)) {
                        SecretKeyFactory.getInstance(algorithm);
                    } else {
                        MessageDigest.getInstance(algorithm);
                    }
                    return algorithm;
                } catch (NoSuchAlgorithmException e) {
                    log.debug("Invalid algorithm detected " + algorithm, e);
                }
            }
        }

        // not starting with {} or invalid algorithm
        return null;
    }

    @Nullable
    private static String extractSalt(@Nullable String hashedPwd, int start) {
        if (hashedPwd != null) {
            int end = hashedPwd.indexOf(DELIMITER, start);
            if (end > -1) {
                return hashedPwd.substring(start, end);
            }
        }
        // no salt
        return null;
    }

    private static int extractIterations(@Nullable String hashedPwd, int start) {
        if (hashedPwd != null) {
            int end = hashedPwd.indexOf(DELIMITER, start);
            if (end > -1) {
                String str = hashedPwd.substring(start, end);
                try {
                    return Integer.parseInt(str);
                } catch (NumberFormatException e) {
                    log.debug("Expected number of iterations. Found: " + str, e);
                }
            }
        }

        // no extra iterations
        return NO_ITERATIONS;
    }
}
