2012-08-09

When authenticating users, you should never store their password value directly. The proper way is to salt and hash before storing.

Most hashing algorithms are designed to take a large amount of data such as documents and quickly return a hash. For storing passwords, you want the opposite: small data, and slow (strong) hashing.

Recognizing this different need, BCrypt takes a different approach. BCrypt uses the very strong but slow Blowfish cipher to do the hashing. BCrypt generates a random salt value to be added to the password, changing on each usage. Furthermore, and most importantly, BCrypt is adaptive. That is, as computing technology speed increases, you can increase the the strength of BCrypt by passing an increasing number. Though oversimplifying, you can think of the number as indicating the number of iterations of hashing and re-hashing. As computers get faster in the future, you can increase the strength of your hashing by passing a higher numbers.

Postgres 9 has a crypto module that includes a "crypt" command that seems to implement BCrypt. Here's a example of calling that command, where 'bf' means Blowfish: SELECT crypt('YourPasswordGoesHere', gen_salt('bf', 10));

Increasing that number slightly dramatically increases the burden on a comupter. Here's some results of calling that in Postgres 9.0.4 on Mac OS X 10.6.7 on a MacBook with a 2.4 GHz Core 2 Duo.

6 ≈ 40 milliseconds

8 ≈ 130 ms

10 ≈ 500 ms

12 ≈ 1,600 ms

14 ≈ 7,000 ms

16 ≈ 28,000 ms (half a minute)

21 ≈ 1 million ms (17 minutes)

During this time, the calculation took about 80-100% utilization of a CPU core.

BCrypt has been implemented in many languages, including C, Java, Python, Ruby, and more.

An implementation is bundled with Postgres, at least when using the installer for Mac OS X provided by EnterpriseDB. At least it seems to me that you are getting BCrypt if you specify the 'bf' argument, but the docs are not explicit -- Please correct me if I'm wrong.

To use this in Postgres, you must enable the "pgcrypto" functions, by copying and executing the SQL found in the "pgcrypto.sql" file found someplace such as this: /Library/PostgreSQL/9.0/share/postgresql/contrib/pgcrypto.sql
Open that file, copy and paste to an interactive SQL window in the pgAdmin app. Actually, you only need the first third of that file's SQL, down to but not including the "pgp_" functions.