package com.saltedhashed;
import java.util.Arrays;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.mindrot.jbcrypt.BCrypt;
import com.lambdaworks.crypto.SCryptUtil;
import com.saltedhashed.crypto.PBKDF2Algorithms;
import com.saltedhashed.model.Algorithm;
import com.saltedhashed.model.PasswordResponse;
public class Verifier {
private static final int MAX_PKBDF2_ITERATIONS = 1000000;
static {
PBKDF2Algorithms.initialize();
}
public boolean verify(String password, PasswordResponse response) {
if (response.getAlgorithm() == Algorithm.BCRYPT) {
return BCrypt.checkpw(password, response.getHash());
}
if (response.getAlgorithm() == Algorithm.SCRYPT) {
return SCryptUtil.check(password, response.getHash());
}
if (response.getAlgorithm() == Algorithm.PBKDF2) {
if (response.getAlgorithmDetails().getIterations() > MAX_PKBDF2_ITERATIONS) {
throw new IllegalArgumentException("Iterations should not exceed " + MAX_PKBDF2_ITERATIONS);
}
byte[] hash = Base64.decodeBase64(response.getHash());
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), response.getSalt().getBytes(), response
.getAlgorithmDetails().getIterations(), response.getAlgorithmDetails().getKeySize());
try {
SecretKeyFactory skf = PBKDF2Algorithms.getSecretKeyFactory("PBKDF2WithHmac" + response.getAlgorithmDetails().getHashFunction().replace("-", ""));
byte[] expectedHash = skf.generateSecret(spec).getEncoded();
return Arrays.equals(hash, expectedHash);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return true;
}
}