Skip to content

Commit

Permalink
Added isValidPassword to PasswordHasher
Browse files Browse the repository at this point in the history
  • Loading branch information
robinsp committed Mar 3, 2026
1 parent 0a4721e commit eed6f98
Showing 1 changed file with 57 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
package ntnu.sytemutvikling.team6.models;

import javax.crypto.SecretKeyFactory;
import javax.crypto.interfaces.PBEKey;
import javax.crypto.spec.PBEKeySpec;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

/**
* A password hasher
* A utility for hashing and verifying passwords using PBKDF2.
*
* <p>
* Description
* <p/>
* <p>The generated hash contains both a random salt and the hashed password,
* encoded as Base64 string.
* </p>
*
* @author Robin Strand Prestmo
*/
public final class PasswordHasher {
private static final SecureRandom RNG = new SecureRandom();

/**
* Get the hash of the password
* Hashes a password using PBKDF2 and a random salt.
*
* @param password a string password
* @return a hash secured password
* @param password the password to hash.
* @return a Base64 string containing the salt and the hashed password.
* @throws IllegalArgumentException if the password is null or blank.
*/
public String getHashPassword(String password) {
String hasPass = "";
if (password == null || password.isBlank()) {
throw new IllegalArgumentException("Password cannot be null or blank.");
}

String hashPass = "";

try {
// 1. Create salt
byte[] salt = new byte[16];
RNG.nextBytes(salt);

// 2. Create PBKDF2 Hash value
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 100000, 32*8);
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 100000, 32 * 8);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();

Expand All @@ -42,11 +47,47 @@ public String getHashPassword(String password) {
System.arraycopy(salt, 0, hashBytes, 0, 16);
System.arraycopy(hash, 0, hashBytes, 16, 32);

//4. Turn the combined salt+hash into a string.
hasPass = Base64.getEncoder().encodeToString(hashBytes);
// 4. Turn the combined salt+hash into a string.
hashPass = Base64.getEncoder().encodeToString(hashBytes);
} catch (Exception e) {
throw new RuntimeException("Error while hashing password.", e);
}
return hashPass;
}

/**
* Checks if the password matches a perviously stored hash.
*
* @param password The password the user types.
* @param hashPass Is the stored hashed password
* @return True if password is valid, otherwise false.
*/
public boolean isValidPassword(String password, String hashPass) {
if (password == null || password.isBlank()) {
return false;
}

try {
// Extract the bytes
byte[] hashBytes = Base64.getDecoder().decode(hashPass);

// Get salt
byte[] salt = new byte[16];
System.arraycopy(hashBytes, 0, salt, 0, 16);

// Compute the hash on the password the user entered
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 100000, 32 * 8);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();

// Compare results
byte[] storedHash = new byte[32];
System.arraycopy(hashBytes, 16, storedHash, 0, 32);

return MessageDigest.isEqual(storedHash, hash);

} catch (Exception e) {
throw new RuntimeException("Error while hasing password.", e);
throw new RuntimeException("Error while validating password.", e);
}
return hasPass;
}
}

0 comments on commit eed6f98

Please sign in to comment.