Popular Posts

Tuesday, 4 March 2014

Please Stop Hashing Passwords Yourself

The problem in two code samples

For those developers who understand they can’t simply store the password in plain text, they typically employ one of two mechanisms. Both are insecure.
The first mechanism is using some type of insecure hashing algorithm, like MD5 or SHA1. These “fingerprint hashes” produce the same hash for a given string of characters, making them ideal for identifying files and other items, but are not cryptographically strong enough for hashing passwords. Even if you add a salt, your passwords will be inherently insecure especially since these algorithms require that the salt be stored alongside the password for two reasons: first, you are likely to screw up the randomness of the salt (weakening the encryption). Second, MD5 and SHA1 are meant to be fast hash algorithms, meaning that a determined attacker can brute force their way through your passwords with ease.
1
2
3
<?php
 
$hashed = insecure_hashing_function($salt . $password); # This is BAD
Another potential failure of security for developers is somehow encrypting passwords with a key, so they can be decrypted for various purposes. I came across the following code sample in a project I was auditing:

md5_decrypt

The ONLY surefire way to hash passwords in PHP

So, if “traditional” methods aren’t enough, what can a developer who cares about security do? The answer lies in a feature introduced as of PHP 5.5: a native password hashing API for PHP.
This library contains two functions that will make it easier for you to hash passwords: password_hash() and password_verify(). These functions essentially wrap built-in PHP behaviors for cryptography, but build in sane defaults that will serve even the most inexperienced developer well.







<?php
 
$password = 'SuperS3cr3+P@ssw0rd';
$hash = password_hash($password,  PASSWORD_DEFAULT);
# $2y$10$PwbhVaqzuUSl5wSdi.iCK.RBz5pQp/a.6lRdSRttY8s2qs7dn5hTq
 
$verified = password_verify($password, $hash);
# true
Astute developers who run the above code will recognize that the hash I give isn’t repeated by their own password_hash function. That’s by design: each password hash should be unique, even for the same password between different users! Also, the second argument lets developers pick the encryption algorithm they want to use; PHP 5.5 defaults to bcrypt, which is usually sufficient.

But I don’t have access to PHP 5.5!

Ah, that is a problem, isn’t it? PHP 5.5′s adoption rate is fairly low right now. But you’re in luck: Anthony Ferrara has backported the native password library for earlier versions of PHP. You can check out his work on GitHub. The library requires PHP 5.3.7 and later, which is well-distributed.

Bottom line

The bottom line is that there’s no reason for you to be hashing passwords yourself. You should be relying on a well-established methodology that will help keep your users secure in the event of a data breach.

No comments:

Post a Comment

Magento: How to get last order id

There are many ways to get last order id:   1. From checkout session: $lastOrderId = Mage::getSingleton('checkout/session'...