Ruby on Rails Password Hashing Module
Sunday, October 14th, 2007This 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.