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);
}
}