· 9 years ago · Dec 19, 2016, 08:01 PM
1import java.math.BigInteger;
2import java.security.NoSuchAlgorithmException;
3import java.security.SecureRandom;
4import java.security.spec.InvalidKeySpecException;
5
6import javax.crypto.SecretKeyFactory;
7import javax.crypto.spec.PBEKeySpec;
8
9public class SecureHashing {
10 private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA512";
11 private static final String SECURE_RANDOM_ALGORITHM = "SHA1PRNG";
12 private static final int ITERATIONS = 10000;
13 private static final int HASH_BYTE_SIZE = 64 * 8;
14 private static final int SALT_BYTE_SIZE = 64 * 8;
15
16
17
18 public SecureHashing() {
19
20 }
21
22
23 private String convertHexBytesToString(byte[] array) throws NoSuchAlgorithmException {
24 BigInteger bigInteger = new BigInteger(1, array);
25 String hex = bigInteger.toString(16);
26
27 int paddingLength = (array.length * 2) - hex.length();
28 if (paddingLength > 0) {
29 return String.format("%0" + paddingLength + "d", 0) + hex;
30 } else {
31 return hex;
32 }
33 }
34 private byte[] convertHexStringToBytes(String hex) throws NoSuchAlgorithmException {
35 byte[] bytes = new byte[hex.length() / 2];
36
37 for (int i = 0; i < bytes.length; i++) {
38 bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
39 }
40
41 return bytes;
42 }
43 private boolean slowEqualsForBytes(byte[] a, byte[] b) {
44 int diff = a.length ^ b.length;
45 for (int i = 0; i < a.length && i < b.length; i++) {
46 diff |= a[i] ^ b[i];
47 }
48
49 return diff == 0;
50 }
51 private byte[] generateSalt() throws NoSuchAlgorithmException {
52 SecureRandom secureRandom = SecureRandom.getInstance(SECURE_RANDOM_ALGORITHM);
53
54 byte[] salt = new byte[SALT_BYTE_SIZE];
55 secureRandom.nextBytes(salt);
56
57 return salt;
58 }
59 private byte[] encode(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
60 PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, iterations, bytes);
61 SecretKeyFactory secretKey = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
62
63 return secretKey.generateSecret(pbeKeySpec).getEncoded();
64 }
65
66
67
68
69 private String generateStorngPasswordHash(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
70 byte[] salt = generateSalt();
71
72 byte[] hash = encode(password, salt, ITERATIONS, HASH_BYTE_SIZE);
73
74 return ITERATIONS + ":" + convertHexBytesToString(salt) + ":" + convertHexBytesToString(hash);
75 }
76 private boolean validatePassword(char[] originalPassword, String storedPassword) throws NoSuchAlgorithmException, InvalidKeySpecException {
77 String[] decodedPassword = storedPassword.split(":");
78 byte[] salt = convertHexStringToBytes(decodedPassword[1]);
79 byte[] hash = convertHexStringToBytes(decodedPassword[2]);
80
81 byte[] validate = encode(originalPassword, salt, ITERATIONS, HASH_BYTE_SIZE);
82
83 return slowEqualsForBytes(hash, validate);
84 }
85
86
87
88 public String generateStorngPasswordHash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
89 return generateStorngPasswordHash(password.toCharArray());
90 }
91 public boolean validatePassword(String originalPassword, String storedPassword) throws NoSuchAlgorithmException, InvalidKeySpecException {
92 return validatePassword(originalPassword.toCharArray(), storedPassword);
93 }
94 public byte[] createSalt() throws NoSuchAlgorithmException {
95 return generateSalt();
96 }
97
98}