Ruby on Rails

Ruby on Rails Password Hashing Module

Sunday, October 14th, 2007

This is a very simple password module that is also easy to use. Simpy place it in /lib inside your Ruby on Rails application and start protecting your passwords today. This code uses a long hash, and creates individual salts for each password stored. It should be very computationally expensive for someone to crack every password in your database, were they to fall into the wrong hands. Of course, if your database is in the wrong hands, you probably have bigger problems. But even some large sites have been caught storing passwords in plain text.

Ruby Password Hashing Code

require digest/sha2

# This module contains functions for hashing and storing passwords
module Password

  # Generates a new salt and rehashes the password
  def Password.update(password)
    salt = self.salt
    hash = self.hash(password,salt)
    self.store(hash, salt)
  end

  # Checks the password against the stored password
  def Password.check(password, store)
    hash = self.get_hash(store)
    salt = self.get_salt(store)
    if self.hash(password,salt) == hash
      true

    else
      false
    end
  end

  protected

  # Generates a psuedo-random 64 character string

  def Password.salt
    salt = ..
    64.times { salt << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
    salt
  end

  # Generates a 128 character hash
  def Password.hash(password,salt)
    Digest::SHA512.hexdigest("#{password}:#{salt}")
  end

  # Mixes the hash and salt together for storage
  def Password.store(hash, salt)
    hash + salt
  end

  # Gets the hash from a stored password
  def Password.get_hash(store)
    store[0..127]
  end

  # Gets the salt from a stored password
  def Password.get_salt(store)
    store[128..192]
  end
end

HTML code generated by vim-color-improved v.0.3.2.Download this code: password.rb

Usage

Using the the password module is simple. All you need to do is save the file above as “password.rb” in the lib directory of your rails project. Then require_dependency “password” in your application.rb. Once that is done you are free to use the functions in any controller.

 

Example

application.rb

# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
require_dependency password

class ApplicationController < ActionController::Base
end

HTML code generated by vim-color-improved v.0.3.2.

account_controller.rb

This is an example account controller.

class AccountController < ApplicationController
  layout standard
  before_filter :login_required, :except => [:login]

  def login
    case request.method
      when :post
      if session[:user] = User.authenticate(params[:user_login], params[:user_password])
        flash[:notice]  = Login successful

      else
        session[:user] = nil
        flash.now[:notice]  = Login unsuccessful
        @login = params[:user_login]
      end

    end
  end

  def logout
    session[:user] = nil

  end

  def welcome
  end

end

HTML code generated by vim-color-improved v.0.3.2.

user.rb

This is the model for the user class. As you can see, password checking against a hashed password is very simple here. Authenicating the user returns a User object, which is stored in the session[:user] variable in the controller above.

class User < ActiveRecord::Base

  # Checks login information
  def self.authenticate(nick, pass)
    user = find(:first, :conditions => ['nick = ?',nick])

    if Password::check(pass,user.password)
      user
    else
      return false
    end
  end

  protected

  # Hash the password before saving the record
  def before_create
    self.password = Password::update(self.password)
  end

end

HTML code generated by vim-color-improved v.0.3.2.