CryptoUtils.java
package com.renomad.minum.utils;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;
/**
* Handy helpers for dealing with cryptographic functions
*/
public final class CryptoUtils {
private CryptoUtils() {
// cannot construct
}
/**
* Converts an array of bytes to their corresponding hex string
* @param bytes an array of bytes
* @return a hex string of that array
*/
public static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
/**
* Hash the input string with the provided PBKDF2 algorithm, and return a string representation
* Note that the PBKDF2WithHmacSHA1 algorithm is specifically designed to take a long time,
* to slow down an attacker.
* <p>
* See docs/http_protocol/password_storage_cheat_sheet
* </p>
*/
public static String createPasswordHash(String password, String salt) {
return createPasswordHash(password, salt, "PBKDF2WithHmacSHA1");
}
static String createPasswordHash(String password, String salt, String algorithm) {
final KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(StandardCharsets.UTF_8), 65536, 128);
final SecretKeyFactory factory;
try {
factory = SecretKeyFactory.getInstance(algorithm);
final byte[] hashed = factory.generateSecret(spec).getEncoded();
return bytesToHex(hashed);
} catch (Exception e) {
throw new UtilsException(e);
}
}
}