Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

genki-bcrypt-ruby

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

genki-bcrypt-ruby

  • 2.0.3
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

= bcrypt-ruby

An easy way to keep your users' passwords secure.

== Why you should use bcrypt

If you store user passwords in the clear, then an attacker who steals a copy of your database has a giant list of emails and passwords. Some of your users will only have one password -- for their email account, for their banking account, for your application. A simple hack could escalate into massive identity theft.

It's your responsibility as a web developer to make your web application secure -- blaming your users for not being security experts is not a professional response to risk.

bcrypt allows you to easily harden your application against these kinds of attacks.

== How to install bcrypt

sudo gem install bcrypt-ruby

You'll need a working compiler. (Win32 folks should use Cygwin or um, something else.)

== How to use bcrypt in your Rails application

=== The +User+ model

require 'bcrypt'

class User < ActiveRecord::Base # users.password_hash in the database is a :string include BCrypt

def password
  @password ||= Password.new(password_hash)
end

def password=(new_password)
  @password = Password.create(new_password)
  self.password_hash = @password
end

end

=== Creating an account

def create @user = User.new(params[:user]) @user.password = params[:password] @user.save! end

=== Authenticating a user

def login @user = User.find_by_email(params[:email]) if @user.password == params[:password] give_token else redirect_to home_url end end

=== If a user forgets their password?

assign them a random one and mail it to them, asking them to change it

def forgot_password @user = User.find_by_email(params[:email]) random_password = Array.new(10).map { (65 + rand(58)).chr }.join @user.password = random_password @user.save! Mailer.create_and_deliver_password_change(@user, random_password) end

== How to use bcrypt-ruby in general

require 'bcrypt'

my_password = BCrypt::Password.create("my password") #=> "$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa"

my_password.version #=> "2a" my_password.cost #=> 10 my_password == "my password" #=> true my_password == "not my password" #=> false

my_password = BCrypt::Password.new("$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa") my_password == "my password" #=> true my_password == "not my password" #=> false

Check the rdocs for more details -- BCrypt, BCrypt::Password.

== How bcrypt() works

bcrypt() is a hashing algorithm designed by Niels Provos and David Mazières of the OpenBSD Project.

=== Background

Hash algorithms take a chunk of data (e.g., your user's password) and create a "digital fingerprint," or hash, of it. Because this process is not reversible, there's no way to go from the hash back to the password.

In other words:

hash(p) #=>

You can store the hash and check it against a hash made of a potentially valid password:

=? hash(just_entered_password)

=== Rainbow Tables

But even this has weaknesses -- attackers can just run lists of possible passwords through the same algorithm, store the results in a big database, and then look up the passwords by their hash:

PrecomputedPassword.find_by_hash().password #=> "secret1"

=== Salts

The solution to this is to add a small chunk of random data -- called a salt -- to the password before it's hashed:

hash(salt + p) #=>

The salt is then stored along with the hash in the database, and used to check potentially valid passwords:

=? hash(salt + just_entered_password)

bcrypt-ruby automatically handles the storage and generation of these salts for you.

Adding a salt means that an attacker has to have a gigantic database for each unique salt -- for a salt made of 4 letters, that's 456,976 different databases. Pretty much no one has that much storage space, so attackers try a different, slower method -- throw a list of potential passwords at each individual password:

hash(salt + "aadvark") =? hash(salt + "abacus") =? etc.

This is much slower than the big database approach, but most hash algorithms are pretty quick -- and therein lies the problem. Hash algorithms aren't usually designed to be slow, they're designed to turn gigabytes of data into secure fingerprints as quickly as possible. bcrypt(), though, is designed to be computationally expensive:

Ten thousand iterations: user system total real md5 0.070000 0.000000 0.070000 ( 0.070415) bcrypt 22.230000 0.080000 22.310000 ( 22.493822)

If an attacker was using Ruby to check each password, they could check ~140,000 passwords a second with MD5 but only ~450 passwords a second with bcrypt().

=== Cost Factors

In addition, bcrypt() allows you to increase the amount of work required to hash a password as computers get faster. Old passwords will still work fine, but new passwords can keep up with the times.

The default cost factor used by bcrypt-ruby is 10, which is fine for session-based authentication. If you are using a stateless authentication architecture (e.g., HTTP Basic Auth), you will want to lower the cost factor to reduce your server load and keep your request times down. This will lower the security provided you, but there are few alternatives.

== More Information

bcrypt() is currently used as the default password storage hash in OpenBSD, widely regarded as the most secure operating system available.

For a more technical explanation of the algorithm and its design criteria, please read Niels Provos and David Mazières' Usenix99 paper: http://www.usenix.org/events/usenix99/provos.html

If you'd like more down-to-earth advice regarding cryptography, I suggest reading Practical Cryptography by Niels Ferguson and Bruce Schneier: http://www.schneier.com/book-practical.html

= Etc

Author :: Coda Hale coda.hale@gmail.com Website :: http://blog.codahale.com

FAQs

Package last updated on 11 Aug 2014

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc