Skip to content

Commit

Permalink
Added blowfish password encryption strategy.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sproinks committed Feb 27, 2012
1 parent 3430e88 commit 40362e9
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 1 deletion.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,22 @@ By default, Clearance uses SHA1 encryption of the user's password. You can provi
def encrypt_password
end

See [lib/clearance/password_strategies/sha1.rb](https://github.com/thoughtbot/clearance/blob/master/lib/clearance/password_strategies/sha1.rb) for the default behavior.
See [lib/clearance/password_strategies/sha1.rb](https://github.com/thoughtbot/clearance/blob/master/lib/clearance/password_strategies/sha1.rb) for the default behavior. Also see [lib/clearance/password_strategies/blowfish.rb](https://github.com/thoughtbot/clearance/blob/master/lib/clearance/password_strategies/blowfish.rb) for another password strategy. Switching password strategies will cause your existing users' passwords to not work.

Once you have an API-compliant module, load it with:

Clearance.configure do |config|
config.password_strategy = MyPasswordStrategy
end

For example:

# default
config.password_strategy = Clearance::PasswordStrategies::SHA1
# ... or another example
config.password_strategy = Clearance::PasswordStrategies::Blowfish


Optional Cucumber features
--------------------------

Expand Down
1 change: 1 addition & 0 deletions lib/clearance/password_strategies.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Clearance
module PasswordStrategies
autoload :SHA1, 'clearance/password_strategies/sha1'
autoload :Blowfish, 'clearance/password_strategies/blowfish'
end
end
45 changes: 45 additions & 0 deletions lib/clearance/password_strategies/blowfish.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'openssl'

module Clearance
module PasswordStrategies
module Blowfish
extend ActiveSupport::Concern

# Am I authenticated with given password?
#
# @param [String] plain-text password
# @return [true, false]
# @example
# user.authenticated?('password')
def authenticated?(password)
encrypted_password == encrypt(password)
end

protected

def encrypt_password
initialize_salt_if_necessary
if password.present?
self.encrypted_password = encrypt(password)
end
end

def generate_hash(string)
# TODO: 1.9 vs 1.8 testing
cipher = OpenSSL::Cipher::Cipher.new('bf-cbc').encrypt
cipher.key = Digest::SHA256.digest(salt)
cipher.update(string) << cipher.final
end

def encrypt(string)
generate_hash("--#{salt}--#{string}--")
end

def initialize_salt_if_necessary
if salt.blank?
self.salt = generate_random_code
end
end
end
end
end
45 changes: 45 additions & 0 deletions spec/models/blowfish_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'spec_helper'

describe Clearance::PasswordStrategies::Blowfish do
subject do
Class.new do
attr_accessor :salt, :password, :encrypted_password
include Clearance::PasswordStrategies::Blowfish

def generate_random_code; "code"; end
end.new
end

describe "#encrypt_password" do
context "when the password is set" do
let(:salt) { "salt" }
let(:password) { "password" }

before do
subject.salt = salt
subject.password = password
subject.send(:encrypt_password)
end

it "should encrypt the password using Blowfish into encrypted_password" do
cipher = OpenSSL::Cipher::Cipher.new('bf-cbc').encrypt
cipher.key = Digest::SHA256.digest(salt)
expected = cipher.update("--#{salt}--#{password}--") << cipher.final

subject.encrypted_password.should == expected
end
end

context "when the salt is not set" do
before do
subject.salt = nil

subject.send(:encrypt_password)
end

it "should initialize the salt" do
subject.salt.should_not be_nil
end
end
end
end

0 comments on commit 40362e9

Please sign in to comment.