# RFC: password_hash function behavior

- Status: Inactive
- Authors: Yasuo Ohgaki yohgaki@ohgaki.net
- Version: 0.9
- Original: https://wiki.php.net/rfc/password_hash_spec
- Page: https://externals.io/rfc/password_hash_spec
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Discussions on the mailing list

No thread found.

---

## Introduction

[password\_hash()](http://jp2.php.net/password_hash) is introduced from PHP 5.5 as crypt() wrapper and has Blowfish(PASSWORD\_BCRYPT) hash algorithm as the only hash function available.

Unlike other hash functions, Blowfish is designed to take limited length as its parameter. Bytes longer than 72 bytes are truncated to compute hash value. Current implementation does not have check against too long parameter. Therefore, too long parameter is silently ignored. Average users expect “hash” functions compute hash value based on parameter, not part of it.

Before PHP 5.3, crypt() could not be used reliably because it didn't have required hash function internally. Therefore, code like below is used commonly. Note: According to this [survey](http://w3techs.com/technologies/details/pl-php/5/all) 20% of PHP users are still using PHP4 and 25% of PHP5 users are using pre PHP5.3.

```php
<?php
$password_hash = sha1(SOME_STATIC_SECRET_SALT . $_POST['password']);
if ($password_hash === get_password_hash_from_db($_POST['username'])) {
  // authenticated
} else {
  // not authenticated
?>
```

If user writes code like below, password\_hash() does not work for authentication when SOME\_STATIC\_SECRET\_SALT is long enough. (e.g. const = SOME\_STATIC\_SECRET\_SLAT = hash('sha512', 'some secret string'); hash('sha512', 'str') returns 128 bytes which is longer than 72.)

```php
<?php
// $password_hash = password_hash(SOME_STATIC_SECRET_SALT . $_POST['password']) is saved in password DB
if (password_verify(SOME_STATIC_SECRET_SALT . $_POST['password'], get_password_hash_from_db($_POST['username']))) {
  // authenticated
} else {
  // not authenticated
}
?>
```

In general, users are recommended to use crypt related functions as is and this is documented currently. However, SOME\_STATIC\_SECRET\_SALT is still useful as mitigation when password database is stolen while SOME\_STATIC\_SECRET\_SALT is \_not\_ stolen. (e.g. Stolen password DB via SQL injection, stolen password db backup, etc) Therefore, some organizations require to add secret salt for an additional mitigation. 72 bytes limits is real problem in this case.

This RFC is for

- Changing password\_hash() behavior.
- How to document password hash related functions.

## Proposal

password\_hash() behavior:

1. Add E\_NOTICE error to password\_hash() with PASSWORD\_BCRYPT and password longer than 72 bytes. (password\_hash() return result with truncated password)
2. Add PASSWORD\_SHA512 hashing to password\_hash() that is compatible with crypt-sha512

Password hashing related documentation:

Recommend plain use of password\_hash() with less than 72 bytes.

In case we decided not to have PASSWORD\_SHA512,

1. Suggest PBKDF2 SHA512 functions ([hash](http://jp2.php.net/manual/en/function.hash-pbkdf2.php) or [openssl](http://jp2.php.net/manual/en/function.openssl-pbkdf2.php)) as an alternative. (rounds larger than 10,000)
2. Suggest workaround (not recommend) by prehash with raw SHA512. (e.g. password\_hash(hash('sha512', SOME\_STATIC\_SCRET\_SALT . $password), PASSWORD\_DEFAULT);)

## Backward Incompatible Changes

password\_hash() E\_NOTICE may break apps.

## Proposed PHP Version(s)

PHP 5.5.x

## RFC Impact

### To Existing Extensions

- [Password Hashing](http://jp2.php.net/manual/en/book.password.php)

### New Constants

- PASSWORD\_SHA512 for crypt-sha512

### php.ini Defaults

If there are any php.ini settings then list:

- hardcoded default values
- php.ini-development values
- php.ini-production values

None

## Open Issues

More edit

## Unaffected PHP Functionality

return value of password\_hash() function will not be changed.

## Future Scope

When better crypt is available, password\_hash()/crypt() and documentations should be updated.

## Proposed Voting Choices

Include these so readers know where you are heading and can discuss the proposed voting options.

State whether this project requires a 2/3 or 50%+1 majority (see [voting](https://externals.io/rfc/voting))

## Patches and Tests

TDB

## Implementation

After the project is implemented, this section should contain

1. the version(s) it was merged to
2. a link to the git commit(s)
3. a link to the PHP manual entry for the feature

## References

Links to external references, discussions or RFCs

## Rejected Features

Keep this updated with features that were discussed on the mail lists.
