Initial commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package com.mzh.library.util;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
|
||||
public final class PasswordHasher {
|
||||
private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
|
||||
private static final String PREFIX = "pbkdf2_sha256";
|
||||
private static final int DEFAULT_ITERATIONS = 60000;
|
||||
private static final int SALT_BYTES = 16;
|
||||
private static final int HASH_BYTES = 32;
|
||||
|
||||
private PasswordHasher() {
|
||||
}
|
||||
|
||||
public static String hash(String password) {
|
||||
byte[] salt = new byte[SALT_BYTES];
|
||||
new SecureRandom().nextBytes(salt);
|
||||
byte[] hash = derive(password, salt, DEFAULT_ITERATIONS);
|
||||
return PREFIX + "$" + DEFAULT_ITERATIONS + "$"
|
||||
+ Base64.getEncoder().encodeToString(salt) + "$"
|
||||
+ Base64.getEncoder().encodeToString(hash);
|
||||
}
|
||||
|
||||
public static boolean verify(String password, String storedHash) {
|
||||
if (password == null || storedHash == null || storedHash.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] parts = storedHash.split("\\$");
|
||||
if (parts.length != 4 || !PREFIX.equals(parts[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
int iterations = Integer.parseInt(parts[1]);
|
||||
byte[] salt = Base64.getDecoder().decode(parts[2]);
|
||||
byte[] expected = Base64.getDecoder().decode(parts[3]);
|
||||
byte[] actual = derive(password, salt, iterations);
|
||||
return MessageDigest.isEqual(expected, actual);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] derive(String password, byte[] salt, int iterations) {
|
||||
char[] passwordChars = password.toCharArray();
|
||||
try {
|
||||
PBEKeySpec spec = new PBEKeySpec(passwordChars, salt, iterations, HASH_BYTES * 8);
|
||||
return SecretKeyFactory.getInstance(ALGORITHM).generateSecret(spec).getEncoded();
|
||||
} catch (GeneralSecurityException ex) {
|
||||
throw new IllegalStateException("Unable to hash password", ex);
|
||||
} finally {
|
||||
Arrays.fill(passwordChars, '\0');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user