Using Bcrypt for User Validation

Posted by Megan Comeau on June 7, 2020

Another project week is coming to a close! And once again I have learned so much while working on this sinatra project. One of the primary requirements for this project was to include user accounts that have unique login attributes. In order to accomplish this and also ensure that the user information stored in the database is secure, I used a very cool Ruby gem called ‘bcrypt-ruby.’ I’ve always found the topic of cryptography fascinating so I decided I’d use this blog post to talk about how and why bcrypt can be used in programs to protect user information.

In order to support user accounts a web application has to be able to store that user information in a database and that means the information can be stolen. In order to protect users sensitive information computers can use a password hashing function to encrypt that information before it is stored in the database. Bcrypt is a password hashing function that has been around since 1999 and has been implemented across numerous programming languages. The bcrypt function is kind of like a transformation machine! It takes in a password and puts out a hash which basically looks like a giant string of random numbers and letters. A specific password will always produce the same hash through bcrypt and it is nearly impossible to turn the hash back into the plain password.

You may be thinking, this project is just a little web application that nobody would ever actually store important information on, why do the passwords need to be secure anyways? The truth is a lot of people use the same passwords across multiple websites and applications. This means, that if my little program gets hacked by somebody, that indivdual could then try using the account information across other web applications (like email or banking websites) to access our users private information! Yikes! It is a web developers responsibility to make sure user information is secure.

So back to the bcrypt gem. The hashed password that it puts out is known as a password-digest and as previously mentioned it is nearly impossible to change it back into the plain password. Unfortunately there are a lot of very determined people on the hunt for personal information that isn’t theirs and they can use something called a dictionary attack (a name which offers an interesting visual but, I digress). This is when a hacker creates something known as a rainbow table (another interesting name…) which contains a huge list of commonly used passwords (abc123, hello, password, etc.) and their associated bcrypt password hash. This way a hacker is able to compare their stolen passwords to the rainbow table in order to decrypt the password digest. But never fear! Bcrypt has a solution: Before it encrypts a password it adds an extra random string onto it known as a password salt. So now, the algorithm will put out a different password-digest that wouldn’t match up to anything in the hackers rainbow table.

Another interesting thing to note is that what sets bcrypt apart from other password hashing algorithms such as MD5 and SHA1 is that bcrypt is much SLOWER. It was designed to be that way! Why? Because it makes it harder for hackers to create those crazy rainbow tables. To give you some idea of the difference in speed: a hacker using Ruby could check ~140,000 passwords per second using MD5 versus ~450 passwords per second using bcrypt. Thats a pretty big difference! And thus at the end of the day bcrypt makes hacking passwords take too much effort to be worth it. Success.

Using the bcrypt gem in a ruby app is so easy. You can either type ‘gem install bcrypt’ in your terminal or add the line “require ‘bcrypt’” to your Gemfile and then run bundle install. For the database, make sure that instead of a column named password you use ‘password_digest’ which will take a string as an input. Bcrypt works with a macro, has_secure_passwords, which can be included in the User model in order to gain access to some important methods (yay metaprogramming!). This macro makes it so that even though a hashed password is stored in the database as password_digest, it is still accessed in the program using the call password. It also ensures that there must be a password present upon creation in order to be saved to the database. Most importantly it gives the User model a method called authenticate which takes in a string to be compared to the password_digest attribute. If the strings match the method will return the user object that it was called upon, otherwise it will return false. This method can be used during a program to ensure that users only have editing abilities for their own resources. For example, a blogging website would want to make sure that a user could only edit or delete a blog post that belongs to the user. The authenticate method gives our programs this ability.

In conclusion, the bcrypt function adds a nice layer of security for the users of a program. User security is a very interesting topic that I look forward to learning more about in the future.