· 4 years ago · Jan 05, 2021, 01:02 PM
1import javax.crypto.SecretKey;
2import javax.crypto.SecretKeyFactory;
3import javax.crypto.spec.PBEKeySpec;
4import java.security.SecureRandom;
5import org.apache.commons.codec.binary.Base64;
6
7public class Password {
8 // The higher the number of iterations the more
9 // expensive computing the hash is for us and
10 // also for an attacker.
11 private static final int iterations = 20*1000;
12 private static final int saltLen = 32;
13 private static final int desiredKeyLen = 256;
14
15 /** Computes a salted PBKDF2 hash of given plaintext password
16 suitable for storing in a database.
17 Empty passwords are not supported. */
18 public static String getSaltedHash(String password) throws Exception {
19 byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
20 // store the salt with the password
21 return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
22 }
23
24 /** Checks whether given plaintext password corresponds
25 to a stored salted hash of the password. */
26 public static boolean check(String password, String stored) throws Exception{
27 String[] saltAndHash = stored.split("\\$");
28 if (saltAndHash.length != 2) {
29 throw new IllegalStateException(
30 "The stored password must have the form 'salt$hash'");
31 }
32 String hashOfInput = hash(password, Base64.decodeBase64(saltAndHash[0]));
33 return hashOfInput.equals(saltAndHash[1]);
34 }
35
36 // using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
37 // cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
38 private static String hash(String password, byte[] salt) throws Exception {
39 if (password == null || password.length() == 0)
40 throw new IllegalArgumentException("Empty passwords are not supported.");
41 SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
42 SecretKey key = f.generateSecret(new PBEKeySpec(
43 password.toCharArray(), salt, iterations, desiredKeyLen));
44 return Base64.encodeBase64String(key.getEncoded());
45 }
46}