Storing nuclear launch codes in your app? Enter BCrypt for Authlogic.

Today is Saturday, which is “fun day”, and there is nothing more fun that talking about encryption algorithms. So let’s get started…

Part of Authlogic’s responsibility to is to keep you on the cutting edge when it comes to security. Afterall, that is part of the reason you use Authlogic, so you don”t have to deal with it. Your app can use the latest and great security techniques just by updating the Authlogic gem.

That being said, today I released Authlogic 1.3.2. With this came a new optional crypto provider: BCrypt. According the to BCrypt website:

“There are two kinds of cryptography in this world: cryptography that will stop your kid sister from reading your files, and cryptography that will stop major governments from reading your files.”

My personal opinion is that the default Sha512 encryption that Authlogic uses is plenty secure, emphasis on plenty. Authlogic uses salted Sha512 with multiple stretches. Hell, the majority of apps use Sha1, because that’s what restful_authentication uses, and Sha1 is much less secure. I don’t want to link to these resources directly, but there are a number of resources available to perform reverse lookups on Sha1. I don’t want to paint the wrong picture here by saying Sha1 is insecure. It’s all in how you use it. As long as you are salting it and doing a number of stretches, which restful_authenticaton is doing, you are fine. But if you are storing extremely sensitive information in your app, such as nuclear launch codes, then you might consider something a little more secure.

What makes BCrypt more secure?

For one, BCrypt provides it’s own salting, then Authlogic provides salting as well. Double salting!

Secondly, when it comes to hashing algorithms, security mostly deals with the amount of time it takes to generate the hash. Take a dictionary attack on a Sha1 algorithm. A decent computer could fly through a list of every dictionary word in a relatively fast amount of time compared to BCrypt. Let me show you wish some benchmarks: do |x|"BCrypt (cost = 10:") { 100.times { BCrypt::Password.create("mypass", :cost => 10) } }"BCrypt (cost = 2:") { 100.times { BCrypt::Password.create("mypass", :cost => 2) } }"Sha512:") { 100.times { Digest::SHA512.hexdigest("mypass") } }"Sha1:") { 100.times { Digest::SHA1.hexdigest("mypass") } }

#                         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)

That my friend is a huge difference. There is a trade off between security and performance. If you are willing to take the performance hit then go for it. Play with the :cost option to get that perfect balance between performance and security. By default the BCrypt library uses a cost of 10.

Easily upgrade encryption and transition your users

As I mentioned above, the cost can be adjusted. So let’s say 5 years from now a cost of 10 isn’t as effective as it used to be, because computers are now faster, things have advanced, etc. No problem, just bump the cost up to whatever is now suitable. Your old passwords will continue to work, while the new passwords will be much stronger.

Here’s why using a library like Authlogic is so nice. As your users start to log in, Authlogic will handle upgrading their passwords to the new and improved cost.

Now your app can move with the times and constantly stay on the cutting edge of security, and you don’t have to worry about breaking all of your users passwords.

This is a cool feature, but nothing to go crazy about. The average app will probably never need to upgrade their encryption algorithm. If your app is around long enough, maybe you will upgrade it once. Even then, it’s probably not necessary because of the salting and stretches. Regardless, Authlogic will assist you in your upgrade if you choose to do so.

Lastly, you can get this feature with any encryption algorithm, including Sha. Checkout the “Upgrading encryption methods” in the Authlogic README. It’s very simple.

How do I use this?

It’s simple:

$ sudo gem install bcrypt-ruby

Starting a new app?

# app/models/user.rb
class User < ActiveRecord::Base
  acts_as_authentic do |c|
    crypto_provider = Authlogic::CryptoProviders::BCrypt

Looking to switch to BCrypt?:

class User < ActiveRecord::Base
  acts_as_authentic do |c|
    c.crypto_provider = Authlogic::CryptoProviders::BCrypt
    c.transition_from_crypto_provider = Authlogic::CryptoProviders::Sha512

The transition_from_crypto_provider is whatever crypto provider you are currently using. Check out my blog posts about transitioning to another crypto provider:

What about [insert encryption method here]?

Check out the Authlogic::CryptoProviders module and the subclasses within. You can add you own method just by creating a simple class and letting acts_as_authentic know about. Authlogic bundles some common methods as a convenience to you, there is nothing wrong with adding your own if you feel its necessary.

Why isn’t this the default encryption method for Authlogic?

I have heard of people having issues with the BCrypt library on windows. I have not used windows in years, so don’t take my word for it, but approach it with some caution. I decided to go with Sha512 since that is part of the ruby core and works wherever ruby can be installed.

Then again, using a library like bcrypt on windows is somewhat ironic. If you are very concerned with security I doubt you will be putting your app on windows. To me using BCrypt on Windows is like putting a state of the art lock on a cardboard box.

Final thoughts

The level of security your app provides is really up to you. Unless you are writing apps for the pentagon, the default Sha512 is fine. Regardless, Authlogic shouldn’t get in your way or make decisions for you, so if you feel BCrypt is necessary then go for it.

  • Share/Save/Bookmark

7 Responses to “Storing nuclear launch codes in your app? Enter BCrypt for Authlogic.”

  1. Dan Kubb says:

    Glad to see BCrypt getting more attention. I use it for storing passwords in my app. IMHO one of the biggest benefits of using BCrypt is that you can alter the cost on the fly and passwords stored earlier with the lower cost will continue to work, while all new passwords are stored with the stronger one. Sure, you can do this with SHA but it’ll require more code, when this is all factored into the design of BCrypt. Computers are only going to get faster over time so I think it was smart of them to build in something to the algorithm that allows you to easily increase the strength to compensate.

    I do have one suggestion though: When someone successfully authenticates with a password that was encryped using a lower cost than what’s currently being used, you should re-save the password using the higher cost. That way regular users of an app will always have their passwords stored with the highest possible level of encryption.

  2. Ben Johnson says:

    Dan, you make some excellent points. I updated this post and added a feature in Authlogic to update the passwords when users log in.

  3. coxy says:

    wow – I stumbled upon this just in time. I was busy writing a web admin panel for my nuclear warhead and I somewhat naively assumed that sha1 was enough

  4. Ben Johnson says:

    Coxy, you wouldn’t believe how many people use sha1 for their nuclear warhead admin panels. I’m glad you didn’t make that mistake like all of the others.

  5. Paul says:

    I think the "major governments" quote comes originally from Applied Cryptography, by Bruce Schneier. Gotta love that guy.

  6. sabat says:

    For all those people who are frustrated because BCrypt keeps throwing errors when you try to put it in environment.rb as a config.gem: you have to list it this way: config.gem "bcrypt-ruby", :lib => "bcrypt"

    Also missing here: if you want to change the cost of the BCrypt algorithm, you do it by putting an authlogic.rb file in config/initializers with a line like this: Authlogic::CryptoProviders::BCrypt.cost = 15

  7. Brian says:

    sabat thanks for that post. I’m sure it saved me some time, I had just put it in my environment.rb with the lib.