Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple example Java class to safely generate and verify bcrypt password hashes for use in authentication systems.
/**
* Author: Ian Gallagher <igallagher@securityinnovation.com>
*
* This code utilizes jBCrypt, which you need installed to use.
* jBCrypt: http://www.mindrot.org/projects/jBCrypt/
*/
public class Password {
// Define the BCrypt workload to use when generating password hashes. 10-31 is a valid value.
private static int workload = 12;
/**
* This method can be used to generate a string representing an account password
* suitable for storing in a database. It will be an OpenBSD-style crypt(3) formatted
* hash string of length=60
* The bcrypt workload is specified in the above static variable, a value from 10 to 31.
* A workload of 12 is a very reasonable safe default as of 2013.
* This automatically handles secure 128-bit salt generation and storage within the hash.
* @param password_plaintext The account's plaintext password as provided during account creation,
* or when changing an account's password.
* @return String - a string of length 60 that is the bcrypt hashed password in crypt(3) format.
*/
public static String hashPassword(String password_plaintext) {
String salt = BCrypt.gensalt(workload);
String hashed_password = BCrypt.hashpw(password_plaintext, salt);
return(hashed_password);
}
/**
* This method can be used to verify a computed hash from a plaintext (e.g. during a login
* request) with that of a stored hash from a database. The password hash from the database
* must be passed as the second variable.
* @param password_plaintext The account's plaintext password, as provided during a login request
* @param stored_hash The account's stored password hash, retrieved from the authorization database
* @return boolean - true if the password matches the password of the stored hash, false otherwise
*/
public static boolean checkPassword(String password_plaintext, String stored_hash) {
boolean password_verified = false;
if(null == stored_hash || !stored_hash.startsWith("$2a$"))
throw new java.lang.IllegalArgumentException("Invalid hash provided for comparison");
password_verified = BCrypt.checkpw(password_plaintext, stored_hash);
return(password_verified);
}
/**
* A simple test case for the main method, verify that a pre-generated test hash verifies successfully
* for the password it represents, and also generate a new hash and ensure that the new hash verifies
* just the same.
*/
public static void main(String[] args) {
String test_passwd = "abcdefghijklmnopqrstuvwxyz";
String test_hash = "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC";
System.out.println("Testing BCrypt Password hashing and verification");
System.out.println("Test password: " + test_passwd);
System.out.println("Test stored hash: " + test_hash);
System.out.println("Hashing test password...");
System.out.println();
String computed_hash = hashPassword(test_passwd);
System.out.println("Test computed hash: " + computed_hash);
System.out.println();
System.out.println("Verifying that hash and stored hash both match for the test password...");
System.out.println();
String compare_test = checkPassword(test_passwd, test_hash)
? "Passwords Match" : "Passwords do not match";
String compare_computed = checkPassword(test_passwd, computed_hash)
? "Passwords Match" : "Passwords do not match";
System.out.println("Verify against stored hash: " + compare_test);
System.out.println("Verify against computed hash: " + compare_computed);
}
}
@sangramanand

This comment has been minimized.

Copy link

@sangramanand sangramanand commented Dec 4, 2015

Thanks!!! 👍

@klaudi007

This comment has been minimized.

Copy link

@klaudi007 klaudi007 commented May 22, 2016

how this can be true if salt is not as a input param ? checkPassword(String password_plaintext, String stored_hash).

saving process : save hashed(salt+pass_plaintext) with salt

controlling process : control (salt+pass_plaintext , stored_hash)

ok or not?)))

@ipoletti

This comment has been minimized.

Copy link

@ipoletti ipoletti commented May 31, 2016

@klaudi007
The hashed password contains the salt.

From https://en.wikipedia.org/wiki/Bcrypt
The bcrypt function is the default password hash algorithm for BSD and other systems including some Linux distributions such as SUSE Linux.[2] The prefix "$2a$" or "$2b$" (or "$2y$") in a hash string in a shadow password file indicates that hash string is a bcrypt hash in modular crypt format.[3] The rest of the hash string includes the cost parameter, a 128-bit salt (base-64 encoded as 22 characters), and 184 bits of the resulting hash value (base-64 encoded as 31 characters).[4] The cost parameter specifies a key expansion iteration count as a power of two, which is an input to the crypt algorithm.

For example, the shadow password record $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy specifies a cost parameter of 10, indicating 210 key expansion rounds. The salt is N9qo8uLOickgx2ZMRZoMye and the resulting hash is IjZAgcfl7p92ldGxad68LJZdL17lhWy. Per standard practice, the user's password itself is not stored.

@anilhk

This comment has been minimized.

Copy link

@anilhk anilhk commented Oct 12, 2017

Hi Ian Gallagher, @craSH

I was looking at your code and i am new to hash, salt and pepper and trying to digest this. Based on what i have read on tutorials and what I see here, it looks like in the code you have the same salt for all the users. I am trying to grasp that if this is true does the below questions make sense ?

  1. If 2 users have the same password, their hashed password would be same. Since its the same salt.

  2. If the salt is the same for all the users, cant the hacker figure out its the same salt and identify the salt from the hashed password and remove it ?

  3. question might be a bit too much but hey he is a hacker for a reason :)

@lucasduete

This comment has been minimized.

Copy link

@lucasduete lucasduete commented Oct 16, 2017

Thanks, helped me a lot.

@ryankshah

This comment has been minimized.

Copy link

@ryankshah ryankshah commented Jan 4, 2018

@anilhk It does not use the same salt for all the users, the same function is called however. It generates a different salt based on the work factor given.

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented May 2, 2018

Nice one

@IvanCl4udio

This comment has been minimized.

Copy link

@IvanCl4udio IvanCl4udio commented May 27, 2019

Thanks!!

@ayushGhimire

This comment has been minimized.

Copy link

@ayushGhimire ayushGhimire commented Jun 7, 2019

what library should be included to use BCrypt?

@alessandrojr1998

This comment has been minimized.

Copy link

@alessandrojr1998 alessandrojr1998 commented Apr 15, 2020

Thanks!!!

@ValeriyaChudnay

This comment has been minimized.

Copy link

@ValeriyaChudnay ValeriyaChudnay commented May 15, 2021

what library should be included to use BCrypt?

org.springframework.security

@craSH

This comment has been minimized.

Copy link
Owner Author

@craSH craSH commented May 15, 2021

what library should be included to use BCrypt?

org.springframework.security

In this example code I used http://www.mindrot.org/projects/jBCrypt/ - but this gist of mine is fairly old at this point, I've not checked to see if it still holds up! Use at your own risk and please research the specifics to understand any risks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment