Revision #10 has been created by samdark on Mar 29, 2013, 10:20:24 AM with the memo:
trying to fix github link
« previous (#3) next (#11) »
Changes
Title
unchanged
Use crypt() for password storage
Category
unchanged
Tutorials
Yii version
unchanged
Tags
unchanged
Authentication, security, password, hash, hashing
Content
changed
Storing passwords in web apps
----
> There is now a `CPasswordHelper` class in `system.utils` <a href="https://github.com/yiisoft/yii/blob/master/framework/utils/CPasswordHelper.php">at GitHub</a>
> that provides an API to simplify the use of `crypt()` for password storage.
> While this wiki article remains valid, it will in due course be rewritten
> to refer to the new class as well as explain how it works.
There are many tutorials and examples that show storage of passwords in a table.
Often the methods used are substandard and very easy to crack. There are many web pages and tutorials that show how to do it wrong.[...]
```php
crypt('EgzamplPassword', '$2a$10$1qAz2wSx3eDc4rFv5tGb5t')
>> '$2a$10$1qAz2wSx3eDc4rFv5tGb5e4jVuld5/KF2Kpy.B8D2XoC031sReFGi'
```[...]
```php
crypt('EgzamplPassword', '$2a$10$1qAz2wSx3eDc4rFv5tGb5t12345678901234567890')
>> '$2a$10$1qAz2wSx3eDc4rFv5tGb5e4jVuld5/KF2Kpy.B8D2XoC031sReFGi'
crypt('EgzamplPassword', '$2a$10$1qAz2wSx3eDc4rFv5tGb5t$2a$10$1qAz2wSx3eDc4rFv5tGb5t')
>> '$2a$10$1qAz2wSx3eDc4rFv5tGb5e4jVuld5/KF2Kpy.B8D2XoC031sReFGi'
```[...]
```php
crypt('EgzamplPassword', '$2a$10$1qAz2wSx3eDc4rFv5tGb5e4jVuld5/KF2Kpy.B8D2XoC031sReFGi')
>> '$2a$10$1qAz2wSx3eDc4rFv5tGb5e4jVuld5/KF2Kpy.B8D2XoC031sReFGi'
```[...]
**Validate password against a stored hash**
```php
$hash === crypt($password, $hash)
```Compare the strings `$hash` and `crypt($password, $hash)`.
**NOTE:** We should use a constant-time string comparison algorithm to defeat
the possibility of
[timing attacks](http://blog.astrumfutura.com/2010/10/nanosecond-scale-remote-timing-attacks-on-php-applications-time-to-take-them-seriously/)
learning the result of validation. See below for an example.[...]
}
$rand = array();
for ($i = 0; $i < 8; ++$i
+= 1) {
$rand[] = pack('S', mt_rand(0, 0xffff));
}[...]
[sql]
create table user (
id int not null auto_increment primary key,
username varchar(255) not null,
password_hash char(64) not null,
unique key (email)
)
~~~[...]
```php
if ($password_hash === crypt($form->password, $record->passwordHash))
// password is correct
else
// password is wrong
```[...]
```
## Constant-time string comparison.
This function is based on
[this](http://codereview.stackexchange.com/questions/13512/constant-time-string-comparision-in-php-to-prevent-timing-attacks)
and
[this](https://github.com/ircmaxell/password_compat/blob/master/lib/password.php).
```php
function same($a, $b) {
/**
* @see http://codereview.stackexchange.com/questions/13512
*/
if (!is_string($a) || !is_string($b)) {
return false;
}
$mb = function_exists('mb_strlen');
$length = $mb ? mb_strlen($a, '8bit') : strlen($a);
if ($length !== ($mb ? mb_strlen($b, '8bit') : strlen($b))) {
return false;
}
$check = 0;
for ($i = 0; $i < $length; $i += 1) {
$check |= (ord($a[$i]) ^ ord($b[$i]));
}
return $check === 0;
}
```
## Availability of `crypt()`'s Blowfish option
The `crypt()` function has ben part of PHP for a long time but not all PHP installations[...]
move to a host with an up-to-date PHP.
Be careful of slow hash function implementations in PHP. The important thing is that the hash takes a lot of compute time *on the attackers equipment* and takes the minimum possible on yours. A hash implemented in PHP puts you at a disadvantage relative to the attacker. For example, imagine you iterate SHA-1 in in PHP for one second on a Micro instance on Amazon EC2 while the attacker has the same algorithm optimized to run on $5k's worth of modern GPUs. I don't know how many orders of magnitude faster the attacker's algorithm is than yours but I think its enough so that you should feel unsafe with such an implementation.