Hey there! How's it going? :)
In order to promote application security and develop my skills in .NET applications, I'm starting this series of posts about tools that can protect your application against cyber attacks and data leakage!
In this first article, I will talk about password hash and how you can apply this functionality in your application using BCript!
So without futher ado, let's get started!
First of all, what is Password Hash and why is it important?
Imagine you just found the best application for ice cream delivery, and in order to use this application you have to sign up on the app. You go to the sign up page, type a login and a password, and after submitting your credentials, you're ready to order your favorite vanilla ice cream with chocolate and caramel coating.
But couple weeks later, you just found out that a bunch of people using the Guy Fawkes mask just leaked the IceCreamApp database, with all the logins and passwords, which means that they know that your login is ryanRaynolds98
and your password is iceCreamL0v3r
. Besides that, now all services you use are compromised since you use the same credentials for all of them. Pretty sad, isn't it?
You know that it's not safe using the same credentials for different services, but you keep doing it because it's easier to remember, and I'm not gonna judge you for doing that (ok, I'll judge you a little bit). But in case you're really lazy and have memory problems, I have a solution for you:
You could use a password manager!
A password manager is a software that helps you generating strong and different passwords for each service you use, and keep them in a safe place! So, problem solved, right?
Unfortunatelly, there's no much people that knows about this type of software...
Having said that, what can we do as developers to protect our users from this type of attack? Is it possible to keep the users information in the database in a way that even if it's leaked, it's not readable for the hackers?
The answer is YES, and it's called Password Hash!
Instead of saving the password in plain text in the database like this:
ryanRaynolds98
you can hash the password and save it like this:
$2a$12$MaFASh9BC4tagsX2KH90Gu3om.Y.pwWqulHlh8CLeAV5a9VHcMJLW
This sequence of random numbers and letters represents the same ryanRaynolds98
, but in a 'hidden' way, and even if I change a single letter on it, the hash is going to be completely different! Check this out:
ryanRaynoldz98
turns into
$2a$12$RInj41FxAUtWKO6uCBz/9OOJLZToStW5NzU9UhaP4f6KodxpnaU66
Cool, right?
Hashing a password means use cryptography for turning the password readable only for the ones who have authorization for it!
There are any different types of cryptography. One of them is known as "Caesar cipher", in which each letter of the text is replaced by the letter some fixed positions distant from it.
For example, the password "icecream"
encrypted using the Caesar cipher could be like "lfhfuhdp"
if you replace each letter by the third letter just after it in the alphabet.
But it's kinda easy to decrypt a password like this... A hacker could find it out in seconds! Look at their face if you use a hashing like this:
So, what type of cryptography would be better for this situation and avoid Hannibal to steal your credentials?
Coding your own hash is really complex and besides taking you hours of hard work, your final job can be prone to errors and vulnerabilities. So, it's recommended to use an existent library for helping you with that!
The BCript pattern is a really good tool you can use to help you with hashing, and it's supported by lots of different programing languages!
By the way, it doesn't just hash your original password, but it adds a different "salt" on it in order to have a different hash even if you use the same password! For example:
If your password is icecream
, BCript is going to add a "Salt" like sX4VDN6iRH
before hashing, turning it into sX4VDN6iRHicecream
. After hashing, it's gonna be like this:
$2a$12$Uf1nLbgEPgkIBGKAjK4/peJ4hJuFFT/XOD6elOkT9/wWQF/PI.kIe
But if someone uses the same password as you, BCript is going to add another "Salt" like Z5zmBaJanH
and the password is going to be hashed like Z5zmBaJanHicecream
. The result is that below:
$2a$12$457.RA6A15Xl8nDgXbFJVuA0RQRzZj6pJmaJnqTqn7vP4jiCZBYq.
Okay, but now that you know it, you may ask yourself: OMG, how can I use BCript in my project?
Just like the Swedish House Mafia used to say, "Don't you worry, child...", I'm here to guide you through this!
So put on your Avril Lavigne playlist and let's get the hands dirty!
Coding part!
To get things started, I'm gonna use Visual Studio and create a Web Api on .NET 5 just for educational purposes ;)
Once it's created, I'm gonna delete all those "weather forecast" classes from the default application, because we ain't gonna use them.
After that, I'll create a new Model folder and add an User class only with Id, Login and Password parameters, just like this:
I'm also using the [Key] data annotation on the Id paramenter because it's needed for the ORM. In this case, I'm using a relational database and this data annotation tells the ORM that the Id is the primary key.
The ORM I'm using is the Entity Framework Core and, just like most of ORMs, it's gonna create a new Id for every user I post to the database, so since I don't want the user to input any value to that paramenter, I'm also gonna create an UserDto which is going to present to the user only the parameters they have to input.
I ain't gonna focus on the ORM configuration and connection to the Database, but if you're interested on it, just leave a comment and I might create a post about it.
Okay, now that we have an User model, let's jump to the Controller. I'm gonna create an User Controller and a POST request on it. This POST request will take all the information from the body and save it in the database.
I'm also going to create a GET request, so we can take all users on the database.
Before configuring BCript, let's see how the database is saving the users. I'll run the application and set up the information on Swagger just like this:
The response body returns the 201 code, which means that the user was created!
But the password on the database is still saved like this
So let's fix this!
Time to BCript!
Okay, to use BCript we have to install the nuget package first! To do this, go to Tools, then to NuGet Package Maneger and finally click on Package Manager Console
In the console, you're gonna write the command below and press Enter
Install-Package BCrypt.Net-Next
Just like this:
Now, we go back to the POST request and, before saving the password itself on the Database, we're going to hash it using the comand
BCrypt.Net.BCrypt.HashPassword(user.password)
It's enough return the password hash just as expected!
After hashing it, you can save it on the database normally. The instance of User class is gonna be like this:
and the database after sending a new request with the same credentials as before is gonna be like this:
Magical, isn't it?
Okay, you know that everything works as expected, but now you may ask yourself: How can I compare the user password with the hash???
So, in order to authenticate the user, I'm gonna create a new POST request with an Authorize method and use BCript to validate the password submited by the user and the hash on the database.
To do it, we can use the comand below:
BCrypt.Net.BCrypt.Verify(password, hash)
The first parameter is the password submited and the second one is the hash from the database. If the password matches with the hash, the method will return True
. Otherwise, it's gonna return False
.
So, in order to wrap everything up, you can write your code like this:
and after running the application, it's gonna work perfectly!
That's it! Easy peasy lemon squeezy
Now you know how to implement password hash in your application!
If you have any question or suggestions, don't hesitate to leave a comment or send me a message on linkedin!
You can also check all the code here on my GitHub repository
See you next time!
Top comments (0)