Class: Sorcery::CryptoProviders::BCrypt

Inherits:
Object
  • Object
show all
Defined in:
lib/sorcery/crypto_providers/bcrypt.rb

Overview

For most apps Sha512 is plenty secure, but if you are building an app that stores nuclear launch codes you might want to consier BCrypt. This is an extremely secure hashing algorithm, mainly because it is slow. A brute force attack on a BCrypt encrypted password would take much longer than a brute force attack on a password encrypted with a Sha algorithm. Keep in mind you are sacrificing performance by using this, generating a password takes exponentially longer than any of the Sha algorithms. I did some benchmarking to save you some time with your decision:

require "bcrypt"
require "digest"
require "benchmark"

Benchmark.bm(18) do |x|
  x.report("BCrypt (cost = 10:") { 100.times { BCrypt::Password.create("mypass", :cost => 10) } }
  x.report("BCrypt (cost = 2:") { 100.times { BCrypt::Password.create("mypass", :cost => 2) } }
  x.report("Sha512:") { 100.times { Digest::SHA512.hexdigest("mypass") } }
  x.report("Sha1:") { 100.times { Digest::SHA1.hexdigest("mypass") } }
end

                        user     system      total        real
BCrypt (cost = 10): 10.780000   0.060000  10.840000 ( 11.100289)
BCrypt (cost = 2):  0.180000   0.000000   0.180000 (  0.181914)
Sha512:             0.000000   0.000000   0.000000 (  0.000829)
Sha1:               0.000000   0.000000   0.000000 (  0.000395)

You can play around with the cost to get that perfect balance between performance and security.

Decided BCrypt is for you? Just insall the bcrypt gem:

gem install bcrypt-ruby

Update your initializer to use it:

config.encryption_algorithm = :bcrypt

You are good to go!

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.costObject Also known as: stretches

This is the :cost option for the BCrpyt library. The higher the cost the more secure it is and the longer is take the generate a hash. By default this is 10. Set this to whatever you want, play around with it to get that perfect balance between security and performance.



51
52
53
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 51

def cost
  @cost ||= 10
end

.pepperObject

Setting the option :pepper allows users to append an app-specific secret token. Basically it’s equivalent to :salt_join_token option, but have a different name to ensure backward compatibility in generating/matching passwords.



46
47
48
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 46

def pepper
  @pepper
end

Class Method Details

.cost_matches?(hash) ⇒ Boolean

This method is used as a flag to tell Sorcery to “resave” the password upon a successful login, using the new cost

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 73

def cost_matches?(hash)
  hash = new_from_hash(hash)
  if hash.nil? || hash == {}
    false
  else
    hash.cost == cost
  end
end

.encrypt(*tokens) ⇒ Object

Creates a BCrypt hash for the password passed.



59
60
61
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 59

def encrypt(*tokens)
  ::BCrypt::Password.create(join_tokens(tokens), cost: cost)
end

.matches?(hash, *tokens) ⇒ Boolean

Does the hash match the tokens? Uses the same tokens that were used to encrypt.

Returns:

  • (Boolean)


64
65
66
67
68
69
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 64

def matches?(hash, *tokens)
  hash = new_from_hash(hash)
  return false if hash.nil? || hash == {}

  hash == join_tokens(tokens)
end

.reset!Object



82
83
84
85
# File 'lib/sorcery/crypto_providers/bcrypt.rb', line 82

def reset!
  @cost = 10
  @pepper = ''
end