Storing Passwords Securely with Bcrypt and Java


07 May 2018  Sergio Martin Rubio  3 mins read.

Storing passwords is a difficult task when we need to satisfy all the data protection laws, and it is getting even tougher with the rise of GDPR, the new European regulation in data privacy. Therefore, we have to make sure all your sensitive data is encrypted and, to do that, we can use hashing algorithms.

When we want to hash passwords to store them in a database, Bcrypt is the way to go and there are many libraries for different languages.

Java Implementation

If you language of choice is Java you can use BCrypt with the library included in the Spring Security module.

<dependency>      
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>

JBcrypt hashes passwords using a version of Bruce Schneier’s Blowfish block cipher with modifications designed to raise the cost of off-line password cracking. The computation cost of the algorithm is parameterized, so it can be increased as computers get faster.

Operations:

  1. Hash password:

     BCrypt.hashpw(plainTextPassword, BCrypt.gensalt())
    

    where plainTextPassword is the password we want to hash and BCrypt.gensalt() is a salt generated randomly.

    In case we want to increment the complexity, an optional parameter (log_rounds) has to be provided to BCrypt.gensalt(), which determines the computational complexity of the hashing. log_rounds is exponential (\(2^{log\_rounds}\)) and it specifies how many times to run the internal hash function. The default value is 10, and the valid values are between 4 and 31.

    The output strings after running hashpw() will look like:

    $bcrypt_id$log_rounds$128_bits_salt184_bits_hash

    hashpw() is smart enough to extract the salt from the string, so you do not need to worry about the salt value anymore, only the hashed string.

  2. Check hashed password:

     BCrypt.checkpw(unencryptedPassword, hashPassword)
    

    This method checks that an unencrypted password matches the one that was previously hashed and ensures that it is stored somewhere.

Conclusion

BCrypt is very good hash algorithm for preventing rainbow table attacks by keeping the salt as part of the output from the BCrypt function. The idea is that every password has an unique salt that is incorporated in the password hash so a hacker cannot create a rainbow table for every password, since a rainbow table works on the principle that more than one plain text password can have the same hash value. If a rainbow table wants to be generated, it will take an enormous amount of time, so it makes brute-forcing pointless.

A Rainbow table is a precomputed table that contains plaintext passwords and their corresponding hash values that can be used to find the text that generates a particular hash. Hackers can use it for cracking hashed passwords stored in a database.

Bcrypt is 10,000 times slower than sha1 to run. If we have a machine that is able to run it in 100ms, this is probably fast enough for login, but it might be too slow if we want to execute Bcrypt against a long list of passwords. In consequence, if a hacker wants to run Bcrypt a billion times by using the same computational power, it will take 27,777 hours.

Source Code