io.polyglotted.common.util.PasswordAuth Maven / Gradle / Ivy
package io.polyglotted.common.util;
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 java.util.Base64;
import java.util.Random;
public abstract class PasswordAuth {
private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
private static final Random RANDOM = new SecureRandom();
public static String hashPassword(char[] password) {
byte[] salt = new byte[16];
RANDOM.nextBytes(salt);
byte[] dk = pbkdf2(password, salt);
byte[] hash = new byte[salt.length + dk.length];
System.arraycopy(salt, 0, hash, 0, salt.length);
System.arraycopy(dk, 0, hash, salt.length, dk.length);
return Base64.getUrlEncoder().withoutPadding().encodeToString(hash);
}
public static boolean authenticate(char[] password, String token) {
byte[] hash = Base64.getUrlDecoder().decode(token);
byte[] salt = Arrays.copyOfRange(hash, 0, 16);
byte[] check = pbkdf2(password, salt);
int zero = 0;
for (int idx = 0; idx < check.length; ++idx)
zero |= hash[salt.length + idx] ^ check[idx];
return zero == 0;
}
private static byte[] pbkdf2(char[] password, byte[] salt) {
KeySpec spec = new PBEKeySpec(password, salt, 65536, 16);
try {
SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
return f.generateSecret(spec).getEncoded();
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
throw new IllegalStateException("Invalid Security", ex);
}
}
}