DEV Community

rwparrish
rwparrish

Posted on • Updated on

Using Bcrypt with Ruby

In this blog, I will cover how to create a 'bcrypt" module for use in a Ruby on Rails project.

Bcrypt uses the MD5 algorithm and adds in a salt to it in order to hash passwords. This is important because as developers we do not want passwords to be stored as regular old strings. Believe it or not, this used to be the case. However, this is no longer safe and NOT considered to be best practice.

The code below is a module. I have called this module "Crud". The methods in this module can be easily called on from other classes or files:

module Crud
  require 'bcrypt'
  puts "Module CRUD activated"

  def self.create_hash_digest(password)
    BCrypt::Password.create(password)
  end

  def self.verify_hash_digest(password)
    BCrypt::Password.new(password)
  end

  def self.create_secure_users(list_of_users)
    list_of_users.each do |user_record|
      user_record[:password] = create_hash_digest(user_record[:password])
    end
    list_of_users
  end

  def self.authenticate_user(username, password, list_of_users)
    list_of_users.each do |user_record|
      if user_record[:username] == username && verify_hash_digest(user_record[:password]) == password
        return user_record
      end
    end
    "Credentials were not correct"
  end
end
Enter fullscreen mode Exit fullscreen mode

Notice the "self" keyword on the methods creating class methods to be called on in another file. Class methods do not require an instance of an object to work. They can be called on the class itself, or a module in this case...

In the file I want to use the Crud module containing the bcrypt methods:

require_relative 'crud'

users = [
          { username: "ryan", password: "password1" },
          { username: "jack", password: "password2" },
          { username: "maria", password: "password3" },
          { username: "michael", password: "password4" },
          { username: "phill", password: "password5" }
        ]

hashed_users = Crud.create_secure_users(users)
puts hashed_users
Enter fullscreen mode Exit fullscreen mode

There are two things to notice here. First, take a look at require_relative 'crud'. This allows me to use the methods from the Crud module in this file. Second, notice the methods I wish to use from the Crud module must be appended with the Crud class.

require_relative 'crud'

class Student
  include Crud
  attr_accessor :first_name, :last_name, :email, :username, :password

  def initialize(firstname, lastname, username, email, password)
    @first_name = firstname
    @last_name = lastname
    @username = username
    @email = email
    @password = password
  end

  def to_s
    "First name: #{@first_name}, Last name: #{@last_name}, Username: #{@username},
                  email address: #{@email}"
  end

end

ryan = Student.new("Ryan", "Parrish", "ryan1", "ryan@example.com",
                      "password1")
john = Student.new("John", "Doe", "john1", "john1@example.com",
                      "password2")

hashed_password = ryan.create_hash_digest(ryan.password)

puts hashed_password
Enter fullscreen mode Exit fullscreen mode

If I include or "mixin" the module I want - include Crud, then the methods in the module needn't be class methods so the "self" keyword can be removed from the methods in the module and the methods can then be called on instances of objects in the class I want.

Happy coding!

Top comments (0)