Skip to content
Snippets Groups Projects
Commit a2334ac9 authored by Goik Martin's avatar Goik Martin
Browse files

Providing log info

Cleaner code avoiding regular expressions
Treating null values correctly
parent fbbe88fc
No related branches found
No related tags found
No related merge requests found
......@@ -20,66 +20,87 @@ import org.apache.logging.log4j.Logger;
*
*/
public class HashProvider {
static private final Logger log = LogManager.getLogger(HashProvider.class);
// The higher the number of iterations the more
// expensive computing the hash is for us
// and also for a brute force attack.
private static final int iterations = 10*1024;
private static final int saltLen = 32;
private static final int desiredKeyLen = 256;
/**
* Computes a salted PBKDF2 hash of given plain text password
static final Logger log = LogManager.getLogger(HashProvider.class);
/**
* Separator between password hash and seed. Consider:
*
* GWTllfNq1vUHaY2iGm+QI1i21fUOEaU7shVvHzNgi+g=$v3juEYYE4fNAqAVnkQLROr8E2hReZHxE2ijpxcey5Yc=
*
* With "$" being the separator token "GWTllfNq1vUHaY2iGm+QI1i21fUOEaU7shVvHzNgi+g="
* will be the password's hash and "v3juEYYE4fNAqAVnkQLROr8E2hReZHxE2ijpxcey5Yc="
* its corresponding seed both being base64 encoded.
*/
static public final char separatorToken = '$';
// The higher the number of iterations the more
// expensive computing the hash is for us
// and also for a brute force attack.
private static final int iterations = 10*1024;
private static final int saltLen = 32;
private static final int desiredKeyLen = 256;
/**
* Computes a salted PBKDF2 hash of given plain text password
suitable for storing in a database
* @param password The plain text password
* @return the generated hash separated from salt by "$"
*/
public static String getSaltedHash(char [] password) {
* @param password The plain text password
* @return the generated hash separated from salt by "$"
*/
public static String getSaltedHash(char [] password) {
try {
final byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
final byte[] salt =
SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
// store the salt with the password
return Base64.encodeBase64String(salt) + "$" + hash(password, salt);
return Base64.encodeBase64String(salt) + separatorToken +
hash(password, salt);
} catch (final NoSuchAlgorithmException e) {
log.fatal("Unable to create hash: " + e);
}
return null;
}
}
/**
* Checks whether given plain text password corresponds
/**
* Checks whether given plain text password corresponds
to a stored salted hash of the password.
* @param password The plain text password
* @param stored the salt/hash to be verified against
* @return true if input matches, false otherwise
*/
public static boolean check(char[] password, String stored){
final String[] saltAndPass = stored.split("\\$");
if (saltAndPass.length != 2) {
log.error("No salt detected!");
return false;
} else {
final String hashOfInput = hash(password, Base64.decodeBase64(saltAndPass[0]));
return null != hashOfInput && hashOfInput.equals(saltAndPass[1]);
}
}
* @param password The plain text password
* @param stored the salt/hash to be verified against
* @return true if input matches, false otherwise
*/
public static boolean check(final char[] password, final String stored) {
if (null == password || null == stored) {
return false;
} else { // Find hash / seed separator token
final int separatorPosition = stored.indexOf(separatorToken);
// using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
// cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
private static String hash(char [] password, byte[] salt) {
if (separatorPosition < 0) {
log.info("No salt detected!");
return false;
} else {
final String hashOfInput = hash(password,Base64.decodeBase64(
stored.substring(0, separatorPosition)));
return null != hashOfInput && hashOfInput.equals(
stored.substring(1 + separatorPosition));
}
}
}
// using PBKDF2 from Sun, an alternative is https://github.com/wg/scrypt
// cf. http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
private static String hash(char [] password, byte[] salt) {
try {
final SecretKey key =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(
new PBEKeySpec(password, salt, iterations, desiredKeyLen));
final SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").
generateSecret(
new PBEKeySpec(password, salt, iterations, desiredKeyLen));
return Base64.encodeBase64String(key.getEncoded());
} catch (NoSuchAlgorithmException e) {
} catch (final NoSuchAlgorithmException e) {
log.fatal("Unable to create hash: " + e);
} catch (InvalidKeySpecException e) {
} catch (final InvalidKeySpecException e) {
log.fatal("Unable to create hash: " + e);
}
return null;
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@
<Logger name="de.hdm_stuttgart.mi.sda1.alignimg.App" level="warn">
<AppenderRef ref="A1"/>
</Logger>
<Root level="warn">
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
......
......@@ -18,5 +18,6 @@ public class TestDecrypt {
System.out.println(saltedHash);
Assert.assertTrue(HashProvider.check(clearText.toCharArray(), saltedHash));
Assert.assertFalse(HashProvider.check(clearText.toCharArray(), "noDollarSeparatorSign"));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment