4 act as encrypts password

act_as_encrypts_password is a ActiveRecord::Base mixin that allows automatic encryption of passwords.

4.1 Motivation

When implementing a user model then a mandatory requirement is to encrypt the user’s password. This functionality is orthogonal to all other parts of the application: There is no interdependency between the encryption functionality of your user model and any other part of your system.

ActiveRBAC provides the mixin act_as_encrypts_password for ActiveRecord::Base. This mixin implements automatic and transparent password encryption: Whenever you set the password and store the record, the generated methods salt the password and encrypt the salted password with a cryptographic hash function. The salt is randomly generated to provide protection against Rainbow Table attacks.

4.2 First Glance

Let’s have a really quick glance over how to use act_as_encrypts_password. Create a new database table users and a User model and drop in the mixin:

class User < ActiveRecord::Base
  acts_as_encrypts_password
end

And you have password encryption on the fly.

4.3 Requirements

The encrypted password mixin can only be used with ActiveRecord::Base classes. The database table of the ActiveRecord must have the following columns:

Note that in a later release you will be able to replace “password” by any other string like “passwd” by passing a parameter to act_as_encrypts_password.

4.4 Reference

When you mark an ActiveRecord::Base class with this mixin then nifty meta programming Ruby magic will modify the class in class in the following way:

Additionally, the following validations will be added to the ActiveRecord:

4.5 Example

File db/migrations/001create_users.rb:

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      # a user needs a login, right?
      t.column :login               :string, :limit => 20,
        :null => false  

      # columns for acts_as_encrypts_password
      t.column :password,           :string, :limit => 128, # sha-512 ready
        :null => false
      t.column :password_salt,      :string, :limit => 100, 
        :null => false
      t.column :password_hash_type, :string, :limit =>  10, 
        :null => false
    end

    # ...
  end

File app/model/user.rb:

class User < ActiveRecord::Base
  acts_as_encrypts_password

  validates_presence_of :login
end

Now we could use this User class in the following way:

$> cd rbac_using_project
$> ./script/console
Loading development environment.
>> user = User.new
=> <#User...
>> user.password_new?
=> true
>> user.login = 'me'
=> "me"
>> user.password = 'password'
=> "password"
>> user.password_confirmation = 'password'
=> "password"
>> user.save!
=> true
>> user.password_new?
=> false
>> user.password_salt
=> "rzTK3WRlPK"
>> user.password
=> "b5f8673fb23319c365e5f0968c55bc17db263e55"
>> require 'digest/sha1'
=> true
>> Digest::SHA1.hexdigst('password' + 'rzTK3WRlPK')
=> "b5f8673fb23319c365e5f0968c55bc17db263e55"
>> user.password_equals?('password')
=> true
>> user.password_equals?('passwd')
=> false

4.6 TODO