Explain Codes LogoExplain Codes Logo

How can I hash a password in Java?

java
password-hashing
security-best-practices
java-security
Alex KataevbyAlex KataevΒ·Nov 3, 2024
⚑TLDR

For secure password hashing in Java, you can employ the MessageDigest class with the SHA-256 algorithm. Make sure to use a unique salt to prevent rainbow table attacks. Here’s a quick method:

import java.security.MessageDigest; import java.util.Base64; String saltedHash(byte[] salt, String password) throws Exception { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(salt); return Base64.getEncoder().encodeToString(md.digest(password.getBytes())); // Rainbows are cool, but not in password hashing! 🌈🚫 }

Invoke this with a non-repeating salt for each user. Store the resulting hash and salt securely. This is just the tip of the iceberg, but it's a good start to robust and resistant password storage.

Put SHA-256 on the bench

While the fast answer is a method to hash passwords, SHA-256 might not meet all of today's security standards due to its fast computation. It's vulnerable to brute-force attacks. Let's explore more secure alternatives: PBKDF2, BCrypt, or Argon2.

Better methods: PBKDF2, BCrypt, and Argon2

PBKDF2: Not your ordinary password encryption

If you're seeking more security, use the Password-Based Key Derivation Function 2 (PBKDF2). I promise it's not as complicated as it sounds!

import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import java.security.SecureRandom; import java.util.Base64; String generateStrongPasswordHash(String password) throws Exception { int iterations = 10000; // Turn up the heat, but careful not to burn the toast! char[] chars = password.toCharArray(); byte[] salt = getSalt(); PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, 64 * 8); SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512"); byte[] hash = skf.generateSecret(spec).getEncoded(); return Base64.getEncoder().encodeToString(hash); // Smooth as a whistle } private static byte[] getSalt() throws Exception { SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); byte[] salt = new byte[16]; sr.nextBytes(salt); return salt; // "Sir, you've got some SALTy encryption there!" }

Remember to save the iterations, salt, and hash in the database. The higher the iterations, the slower your hash function and the harder to brute-force. They're not feats of strength, these hackers!

BCrypt: Strong and steady wins the race

BCrypt uses a variant of the Blowfish encryption algorithm for a catch: it automatically handles salt generation. Say goodbye to the kitchen salt!

import org.mindrot.jbcrypt.BCrypt; String hashPassword(String plainTextPassword){ return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt(12)); // "Mirror, mirror, on the wall, who's the saltiest of them all?" } boolean checkPassword(String plainTextPassword, String hashedPassword) { return BCrypt.checkpw(plainTextPassword, hashedPassword); // "Your password is... OF COURSE, SECURE!" }

Argon2: The heavyweight champ of password hashing

Argon2 is another modern and recommended option for hashing passwords. It won the Password Hashing competition. That's like the Olympics for password hashing!

Make it rain(bow) secure salts and hashes

Salts: The spice of life...and cryptography

Securely generate a salt using SecureRandom:

byte[] salt = new byte[16]; new SecureRandom().nextBytes(salt); // Let it rain...SALT! πŸŒ§οΈπŸ§‚

Checking our secure hashes

When users login, retrieve their hash and salt from the database and compare them to the hash of the submitted password:

boolean passwordMatch(String submittedPassword, String storedHash, byte[] salt) throws Exception { // Hash the submitted password with the same salt String hashedSubmittedPassword = generateStrongPasswordHash(submittedPassword, salt); // Compare the hashed submitted password with the stored one return hashedSubmittedPassword.equals(storedHash); // "You shall not pass...unless you have the right password!" - Gandalf probably }