· 9 years ago · Nov 03, 2016, 09:22 PM
1import java.security.NoSuchAlgorithmException;
2import java.security.SecureRandom;
3import java.security.spec.InvalidKeySpecException;
4import java.util.Base64;
5
6import javax.crypto.SecretKey;
7import javax.crypto.SecretKeyFactory;
8import javax.crypto.spec.PBEKeySpec;
9
10public class Password {
11
12 private static final int DEFAULT_ITERATIONS = 100000;
13 private static final int DEFAULT_KEY_LENGTH = 512;
14 private static final int SALT_BYTE_LENGTH = 32;
15 private static final String KEY_DERIVATION_ALGORITHM = "PBKDF2WithHmacSHA512";
16 private static final String STORED_HASH_TEMPLATE = "%d$%d$%s$%s";
17
18 public static boolean matches(String password, String storedHash) {
19 String[] tokens = storedHash.split("\\$");
20
21 int iterations = Integer.parseInt(tokens[0]);
22 int keyLength = Integer.parseInt(tokens[1]);
23 byte[] salt = Base64.getDecoder().decode(tokens[2]);
24 String hash = tokens[3];
25
26 return matches(password, salt, hash, iterations, keyLength);
27 }
28
29 private static boolean matches(String password, byte[] salt, String hash, int iterations, int keyLength) {
30 return hash.equals(generate(password, salt, iterations, keyLength));
31 }
32
33 public static String generate(String password) {
34 byte[] salt = randomSalt();
35 String hash = generate(password, salt, DEFAULT_ITERATIONS, DEFAULT_KEY_LENGTH);
36 String base64Salt = Base64.getEncoder().encodeToString(salt);
37
38 return String.format(STORED_HASH_TEMPLATE, DEFAULT_ITERATIONS, DEFAULT_KEY_LENGTH, base64Salt, hash);
39 }
40
41 private static String generate(String password, byte[] salt, int iterations, int keyLength) {
42 try {
43 SecretKeyFactory skf = SecretKeyFactory.getInstance(KEY_DERIVATION_ALGORITHM);
44 PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
45 SecretKey key = skf.generateSecret(spec);
46
47 return Base64.getEncoder().encodeToString(key.getEncoded());
48
49 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
50 throw new RuntimeException(e);
51 }
52 }
53
54 private static byte[] randomSalt() {
55 byte[] salt = new byte[SALT_BYTE_LENGTH];
56
57 SecureRandom r = new SecureRandom();
58 r.nextBytes(salt);
59 return salt;
60 }
61
62 public static void main(String[] args) {
63 String secret = "123456";
64 String hash = Password.generate(secret);
65 System.out.println(hash);
66 assert(Password.matches(secret, hash));
67
68 String storedHash ="100000$512$Zzua/MrUuR2HHC6FkGejhg9DkUTaQFj8dXBCQDf3M38=$9zYltu2d2QLs"
69 + "lSYpl3voJAaNT9L/R4hiXbRWN9goSSt7nAcITu8JdniKRe1jDh35CWo9p2SSrlQnK6Le4ObveA==";
70 assert(Password.matches("hunter2", storedHash));
71 }
72
73}