Using bcrypt to store passwords

Posted on

The linkedin password breach highlighted once again the risks associated with storing user passwords. I hope you are not still storing passwords in the clear and are using a one-way salted hash before storing them. But, the algorithm you choose to use is also important. If you don't know why, go read You're Probably Storing Passwords Incorrectly. The choice, at the moment, seems to come down to SHA512 versus Bcrypt encryption. There's a StackOverflow Q&A discussing the merits of each. Bcrypt gets the nod since its goal is to be slow enough that brute force attacks would take too much time to be feasible, but not so slow that honest users would really notice and be inconvenienced [1]. I wanted to switch one of my personal apps to use bcrypt, which on php means using Blowfish encryption via the crypt() function. There's no shortage of classes and examples for using bcrypts to hash a string. But I didn't find anything that outlined how to setup a database table to store usernames and passwords, salt and store passwords, and then verify a login request.

Storing passwords in Mysql

To store passwords in a MySQL database, all we need is a CHAR field of length 60. And you don't need a separate column for the salt, as it will be stored as part of the password. The SQL for a minimal Users table is shown below.

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` char(60) NOT NULL,
  PRIMARY KEY (`id`),
);

When a user registers providing a username and password, you have to generate a salt and hash the password, before saving it. This gist helped me figure out how to salt and hash them.

function save_user($username, $password, PDO $db)
{
    // create a random salt
    $salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);

    // hash incoming password - this works on PHP 5.3 and up
    $hash = crypt($password, '$2a$12$' . $salt);

    // store username and hashed password
    $insert = $db->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
    $insert->execute($username, $hash)
}

Authenticating Users

When a user comes back to your site and tries to login, you retrieve their credentials and then compare the expected password to the supplied password. Remember we were clever and stored the salt as part of our hash in the password field? Now, we can reuse our stored password as the salt for hashing the incoming password. If its the right password, we'll have two identical hashes. Magic!

function validate_user($username, $password, PDO $db)
{
    // attempt to lookup user's information
    $query= $db->prepare('SELECT * FROM users WHERE username=?';
    $query->execute(array($username));

    if (0 == $query->rowCount()) {
        // user not found
        return false;
    }

    $user = $query->fetch();
    // compare the password to the expected hash
    if (crypt($password, $user['password']) == $user['password']) {
        // let them in
        return $user;
    }

    // wrong password
    return false;
}

Those are the basics for using bcrypt to store passwords with PHP and MySQL. The main difference I found, was that the hashing and comparison of hashes now happens in PHP. With MD5 and SHA algorithms, you could invoke them using the database functions provided by MySQL. As far as I could find, it doesn't have a native Blowfish/bcrypt function. If your system provides a crypt() call, you maybe be able to use Blowfish encryption, but it won't be an option on Windows systems.

Tags: Mysql, PHP, Windows

─── ✧ ─── ✦ ─── ✧ ───

Back to SQL it is

Posted on

An honest write up with first hand details of the shortcomings of couchdb in production. There's a reason to stick with proven technologies and not simply chasing the latest shiny. Not saying sauce labs did that, just sayin'.

This post describes our experience using CouchDB, and where we ran into trouble. I'll also talk about how this experience has affected our outlook on NoSQL overall, and how we designed our MySQL setup based on our familiarity with the positive tradeoffs that came with using a NoSQL database.

From: Goodbye, CouchDB | Selenium Testing? Do Cross Browser Testing with Sauce Labs

Tags: Programming

─── ✧ ─── ✦ ─── ✧ ───

Are social referrals killing SEO?

Posted on

I think this is an improvement to how we write for the web. Instead of optimizing for a machine algorithm that can bring traffic to an article, writers must concentrate on making the article interesting so that readers will share it with their friends. Curation is the key, which is also why I hated the "social reader" apps that want to post for me to see everything my friends read. I want to know what they recommend I read.

"Sixteen months ago we received the same number of monthly referrals from search as social. Now 40% of traffic comes from social media," Scott Havens, senior vice president of finance and digital operations at The Atlantic Media Company, said in a phone conversation ahead of his on-stage interview at our Mashable Connect conference in Orlando, Fla. last weekend. "Truly [our writers] are not really thinking about SEO anymore. Now it's about how we can spin a story so that it goes viral."

From: Why 'The Atlantic' No Longer Cares About SEO

Tags: Digital Media

─── ✧ ─── ✦ ─── ✧ ───