package auth;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import exceptions.PoseidonException;
import org.apache.commons.codec.binary.Base64;
import play.mvc.Http;
public class PasswordHasher {
public PasswordHash createHash(String givenPassword) throws NoSuchAlgorithmException, InvalidKeySpecException {
String defaultAlgorithm = "PBKDF2WithHmacSHA1";
int defaultIterations = 20000;
byte[] salt = generateSalt();
byte[] encrypted = getEncryptedPassword(givenPassword, salt, defaultAlgorithm, defaultIterations);
return new PasswordHash(defaultAlgorithm, defaultIterations, Base64.encodeBase64String(salt), Base64.encodeBase64String(encrypted));
}
public boolean authenticate(String attemptedPassword, PasswordHash storedHash) {
byte[] encryptedAttemptedPassword;
try {
encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, Base64.decodeBase64(storedHash.salt), storedHash.algorithm, storedHash.iterations);
}
catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new PoseidonException(Http.Status.INTERNAL_SERVER_ERROR,e.getMessage());
}
return Arrays.equals(Base64.decodeBase64(storedHash.hash), encryptedAttemptedPassword);
}
public byte[] getEncryptedPassword(String password, byte[] salt, String algorithm, int iterations) throws NoSuchAlgorithmException, InvalidKeySpecException {
int derivedKeyLength = 160;
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);
SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);
return f.generateSecret(spec).getEncoded();
}
public byte[] generateSalt() throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[8];
random.nextBytes(salt);
return salt;
}
}