Using bcrypt-ruby in Rails
What is bcrypt?
bcrypt is a password-hashing function based on the Blowfish cipher. It was designed by Niels Provos and David Mazières and is the default password hash algorithm for OpenBSD. bcrypt incorporates a salt to protect against rainbow-table attacks. bcrypt-ruby is the Ruby implementation of bcrypt.
bcrypt Versions
The latest ruby gems available are:
- 3.1.18 — May 16, 2022 java (69.5 KB)
- 3.1.18 — May 16, 2022 (54.5 KB)
- 3.1.17 — March 14, 2022 java (69.5 KB)
- 3.1.17 — March 14, 2022 (54.5 KB)
- 3.1.16 — September 03, 2020 java (68.5 KB)
- 3.1.12 — May 16, 2018 (43.5 KB)
Development Dependencies :
- rake-compiler ~> 1.2.0
- rspec >= 3
How to install the bcrypt gem
gem install bcrypt
How bcrypt works
To see how the BCrypt class works, type the following into IRB. Remember if you create the same password as below, the hash will be different because of salting. Salting is when some random data is added to the password before it is hashed. This makes it more difficult / time consuming for hackers using Rainbow tables. To find out more about Rainbow tables, check out this wikipedia article.
require 'bcrypt'
=> true
pw1 = BCrypt::Password.create("mypassword")
=> "$2a$12$5scgl6wb3P7eeaOniiendeHX4N1JMoRFSQ6AF9gEB.vii/pWk.LJi"
The hash is split between the salt and the checksum. You can view each of them with the following commands.
pw1.salt
=> "$2a$12$5scgl6wb3P7eeaOniiende"
pw1.checksum
=> "HX4N1JMoRFSQ6AF9gEB.vii/pWk.LJi"
When using encryption, it is important to understand what the cost factor is. Cost factor is basically the amount of time the processor takes to create the hash. In some situations you may need to lower the cost factor to conserve processor utilization. bcrypt allows you to change the cost factor depending on your needs.
BCrypt::Engine.cost = 8
=> 8
pw2 = BCrypt::Password.create("mypassword")
=> "$2a$08$uTUc7IHwjUrV7mCmNcb9OexGzgTOsLDunrZp04yd.DKEd2W37UUmG"
pw2.cost
=> 8
The default cost value for bcrypt is 12. Lower numbers decrease processor utilization.
Configuring Ruby on Rails to use bcrypt
This configuration uses Rails version ≥ 3. Create a User model with the following schema. It is important to create the password_digest
columns in your database for bcrypt to work.
create_table “users”, do |t|
t.string “username”
t.string “password_digest”
end
Create a User model and add has_secure_password
to the top of the User class. When using ActiveRecord, ActiveModel::SecurePassword
is automatically included.
class User < ApplicationRecord
has_secure_password
end
The following examples use the methods that are available after adding has_secure_password
to the User model.
user = User.new(username: 'joe', password: '', password_confirmation: 'nomatch')
user.save
# => false, password required
user.password = 'mUc3m00RsqyRe'
user.save
# => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save
# => true
user.recovery_password = "42password"
user.recovery_password_digest
# =>”"$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"
user.save
# => true
user.authenticate('notright')
# => false
user.authenticate('mUc3m00RsqyRe')
# => user
user.authenticate_recovery_password('42password')
# => user
User.find_by(name: 'joe')&.authenticate('notright')
# => false
User.find_by(name: 'joe')&.authenticate('mUc3m00RsqyRe')
# => user
Create a user account
To create a user account, add the following to the users_controller.rb file.
class UsersController < ApplicationController
def create
user = User.create(params[:user, :password, :password_confirmation])
end
end
It’s a good idea to use sessions when working with user accounts in Ruby on Rails. Sessions enable your application to maintain user-specific state. This allows users to authenticate once and remain signed in for future requests until you log out. To know more about sessions and cookies see: https://guides.rubyonrails.org/security.html
For more information on using has_secure_password in Ruby on Rails, check out the following document. Also, check out the the rubydocs.info on bcrypt here.