Sha512.java

package sk.iway.iwcm.users.crypto;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import com.google.crypto.tink.subtle.Hex;

import sk.iway.iwcm.Constants;
import sk.iway.iwcm.users.PasswordSecurityAlgorithm;
import sk.iway.iwcm.users.UnknownHashAlgorithm;

/**
 * Hashovanie hesiel pomocou Sha-512 algoritmu
 */
public class Sha512 implements PasswordSecurityAlgorithm {

    /**
	 * Generates a random HEX string
	 * chars = [0-9a-f]{16}, lowercase only
	 *
	 * @return {@link String} random hex string
	 */
	public String generateSalt() {
		byte[] randomBytes = new byte[8];
		new SecureRandom().nextBytes(randomBytes);
		return Hex.encode(randomBytes).toLowerCase();
	}

    /**
	 * Generates a hash combining password and a salt using concatenation.
	 *
	 * Algorithm employed: SHA-512
	 *
	 * @param password any String
	 * @param salt Generated by generateSalt, must match ^[0-9a-f]{16}$, otherwise rejected
	 * @return [0-9a-f]{128} String
	 */
	public String calculateHash(String password, String salt)
	{
		if (!salt.matches("^[0-9a-f]{16}$"))
			throw new IllegalArgumentException("Salt has invalid form, not matching [0-9a-f]{16}");
		try {
			int passwordUseHashIterations = Constants.getInt("passwordUseHashIterations");

			if (passwordUseHashIterations < 2) {
				//povodna marosova implementacia
				MessageDigest hash = MessageDigest.getInstance("SHA-512");
				byte bytesHash[] = hash.digest((password+salt).getBytes());
				return Hex.encode(bytesHash).toLowerCase();
			} else {
				//presne podla OWASP - https://www.owasp.org/index.php/Hashing_Java
				MessageDigest digest = MessageDigest.getInstance("SHA-512");
				digest.reset();
				digest.update(salt.getBytes());
				byte[] input = digest.digest(password.getBytes());
				for (int i = 0; i < passwordUseHashIterations; i++) {
					digest.reset();
					input = digest.digest(input);
				}
				return Hex.encode(input).toLowerCase();
			}
		} catch (NoSuchAlgorithmException e) { throw new UnknownHashAlgorithm(); }
	}

    public boolean isPasswordCorrect(String password, String salt, String hash) {
        String calculated = calculateHash(password, salt);
        return calculated.equals(hash);
    }
}