Understanding Password Encoder in Springboot:
In this blog I will help you understand the Bcrypt cryptography algorithm and how to use the decrypt password encoder in a spring boot project with spring security.
What is Bcrypt? It is a password hashing function based on BlowFish symmetric block cipher algorithm and crypt which your password hashing function in UNIX. Bcrypt is highly secure because a slat is used to protect against rainbow table attacks and it is an adaptive hashing function with the cryptographic chunk that can be increased when computer hardware gets faster that means the hashing function can be configured to run slower which also means it can slow down attacks.
Let's understand the Bcrypt algorithm with some pseudo-code. Suppose that we want to generate a hash value for a given password. So, the input of the algorithm is the cost of the chunks of the algorithm, salt and a given password and then it initializes the state by setting up an expensive key using a BlowFish algorithm for the cost, salt and password.
Then the ciphertext is chosen with the magic value(OrpheanBeholderScryDoubt) and then the ciphertext is encrypted repeatedly 64 times and finally, it returns the hash string, which is the concatenation of the cost, salt and ciphertext.
That means for a given password the Bcrypt algorithm produced a hash string which is a result of encrypting the magic text here 64 times using BlowFish algorithm with the private key is a given password. It means the password itself is not encrypted hashed even it is used as a private key to hash this magic value 64 times.
Bcrypt(anyPlainpassword) = encrypted_Password;
It encrypts the special initial Bcrypt text 64 times using BlowFish with a private key and this private key is nothing but the given password.
Bcrypt Hashing Technique
Now let's read carefully here that the format of the hash string produced by the Bcrypt. The prefix is a “version” and is followed by the dollar sign($) and the check strength of the algorithm dollar sign and the next 22 characters is SALT and the last 31 characters are the hashed value of the magic ciphertext.
Here's an example of hash chunks produced by Bcrypt as you can see the version number is dollar 2a, the chunk or the Cost is 10 and this characters as a Salt and this characters as a hash value of magic ciphertext and the versions can be dollar 2a/2b and the chunked or strength of the Cost of the algorithm ranging from 4 to 31.
|Versions=||$2a, $2b, $2y|
|SALT||16 Bytes Base64 Encoded to 22 total number of Characters|
|Hash String||24 Bytes Base64 Encoded to 31 total number of Characters|
|Cost or Strength = 4 to 31 & Total Length = 60 Chars|
The higher the chunk or strength value, the more computational power it needs to generate the hash string and the size of the salt is 128 bit base64encoded to 22 characters. The size of the hash is 192 bits by 64 encoded to 31 characters.
So, the total length of the hash String produced by the Bcrypt is 60 characters so when designing a column in the database make sure that the size of the data type of the column is equal to or greater than 60 characters.
How to implement Bcrypt Password Encoder in Spring Security
Let's understand how spring security supports Bcrypt to use the BCrypt password encoder in a Spring boot project. We need to import classes from this package (org.springframework.security.crypto.bcrypt) and the api class is BCrypt password encoder. We have to use this class to encode our password into a hash string and we also use this class to verify your password against an encoded value and the algorithm implementation class is BCrypt.
This class is used by the BCrypt password encoder class and for the versions of the BCrypt algorithm, spring-security defines an Enum BCryptVersion inside the BCryptPasswordEncoder class.
In spring-security, the default strength of the Bcrypt algorithm is 10. The salt is random, and the default version is dollar 2a.
Now I am going to explain to you some good examples with we BCrypt password encoder in the spring boot project. You see this a spring boot project, to use BCrypt password encoder, you need to have this spring security starter dependency available in the project POM file.
I have created a new test class here called as BCryptPass.class and here we can write a JUnit test to encode a very simple robust password. I have created a method to encode a password string and method name is encodePlainPassword(). In this method, we will encode a sample raw password string i.e. let’s say “Hello Password String”.
So, then we have to create a new instance of the BCrypt password encoder class. As you can see there are several contractors for the BCryptPasswordEncoder(), so we have to choose the default no-argument constructor or we can use the constructor that allows us to define to specify the version or the strength here. I have used the no-argument constructor.
As you know the strength is 10 and the version is a dollar 2a default and then we have to encode the password by calling the encode() method of the BCryptPasswordEncoder class. And then we bring the encoded password to the standard output. The encoding method is used to generate a hash hashed string value for a given password.
If I run this test method then you can see the hash value here you can see the version number dollar 2a, strength 10 and followed by the salt and then the actual hash value so. It's very quick to write with the default strength 10 here.
But when using a password encoder code in spring security, you can use the method matches() to verify your password against an encoded value. Then this match method returns the Boolean value if a match is true. Then I have used assert statements to verify if the match value returned is true or not.
Note that the salt used by the Bcrypt algorithm is random. So, even with the same password if you run this test method again, you will see the value of the hash string will be different. Now I am going to modify the code to create a new instance of Bcrypt password encoder class with a specified version and strength number. This is really very interesting.
So, here I will be using use this constructor which accepts version $2b and strength is 7. So, it will generate the hashed string like below:
Example of Bcrypt Password encoder in the DAO layer
We have already implemented spring security using spring boot in above example. Let's say you can be able to login using user name and password which is being fetched from Database. To achieve that we can use Authentication Provider Bean where we have to create a DAOAuthenticationProvider class instance.
Then we can assign customer service objects. But the main thing is to notice that here we have used the password encoder. Here we can specify the Bcrypt password encoder.
Dependency in Pom file:
It is not recommended to use your password as plain text. If anyone can hack your Java Web Application Development or database, they will be seeing all your user passwords. At least your user details should be secured. For using Bcrypt in spring boot project, we don’t have to use any library. By default, in spring boot, we have a library for Bcrypt. Please refer to the above code.
Spring JDBC DataSource authentication using Bcrypt
I am using it here for enabling the JDBC authentication. For using the JDBC authentication we need to configure datasoruce instance first and for that, I have autowired it. Then I have created a bean of type BCryptPasswordEncoder.
Then you have to specify this encoder in the JDBC authentication so that spring security will know that the password that it is going to fetch from the database will be in the Bcrypt encoded format. Accordingly, it will have to handle this encoded password for authentication. Please refer to the below code snippet.
The above code takes care of the Bcrypt encoding during the login, however, during saving the password into a database, we have to save it in an encrypted format so that it gets securely stored in DB.
Now what I will do is, I am going to autowire the password Encode class and using this I am going to first encrypt the password that we get from customer and then this will be passed to the User object in our code. This is how encryption and encoding can be done.
Please refer to the above code where the password that we are receiving from the user we are encrypting this and then storing it into a database.
Here in the above example, you can see that I have a Rest endpoint for Customer registration API and here I am accepting the customer details as a payload from the user including the plain password.
Before storing the password to a Customer object, first I am encoding the password using Bcrypt password encoder and then passing the encoded password to the Customer Object which is then passed to the DAO layer for storing it in database.
During the authentication, the same password is retrieved from the database and then it is decrypted and then verified against the customer’s password. Once it matches with the customer password then login is success otherwise an exception is thrown from the code as “Invalid username or Password”.
Subject: Implementing password encryption and encoding in Java Spring Boot Security using Bcrypt
It is a password hashing function based on BlowFish symmetric block cipher algorithm and crypt which your password hashing function in Unix. Bcrypt is highly secure because a slat is used to protect against rainbow table attacks.
For a given password the Bcrypt algorithm produced a hash string which is a result of encrypting the magic text here 64 times using BlowFish algorithm with the private key is a given password. It means the password itself is not encrypted hashed even it is used as a private key to hash this magic value 64 times
Firstly, need to include the spring security dependency in the pom file and then automatically spring security brings all the required packages of BCrypt password encoder. For more details please read the complete blog.
There are multiple constructors including the default constructor as well. Some constructor takes one parameter with the version and other with both version and strength etc.
The entire code is given in this blog. You have to autowire the required classes and then use them with Bcrypt encoder for password encoding.