Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/update hashing - Add password hasher #18

Merged
merged 36 commits into from
Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3a24f2f
Refactor hashing and add a new password hasher
t0mmie Sep 29, 2016
d98fcb0
Fix HMAC namespace issue
t0mmie Sep 29, 2016
0ce09ab
Remove random string generator
t0mmie Sep 29, 2016
f1735f9
Remove random string test
t0mmie Sep 29, 2016
588bb47
Fix unitests
t0mmie Sep 29, 2016
a71d1cc
Add HMAC unittest
t0mmie Sep 29, 2016
7093fef
Add bloffish verify tests
t0mmie Sep 29, 2016
1f0b235
Add password hasher unittest
t0mmie Sep 29, 2016
fb666db
Use default cost factor for password hasher
t0mmie Sep 30, 2016
d67d4dc
Update password unit test for new cost
t0mmie Sep 30, 2016
c6ac261
Skip cost check if cost is null
t0mmie Sep 30, 2016
66a54a9
Fix double serialization for short hash
t0mmie Sep 30, 2016
4f0d8e4
Add changelog and upgrading files
t0mmie Oct 3, 2016
9555885
Fix code example
t0mmie Oct 3, 2016
6246962
Fix doc typo
t0mmie Oct 3, 2016
5c4653d
Set php requirement and update phpunit
t0mmie Oct 3, 2016
72d80b9
Update php version for travis
t0mmie Oct 4, 2016
25b0e1c
Update HMAC lib for a slightly improved API
Oct 5, 2016
4b2b1d9
PR feedback
t0mmie Oct 5, 2016
40d41ae
Merge pull request #1 from ivarb/feat/update-hashing
t0mmie Oct 5, 2016
b59b89b
Update hasher and Hash lib
Oct 5, 2016
2007572
Update password hasher interface and public API
Oct 5, 2016
14246b1
Check salt max length
t0mmie Oct 5, 2016
a01bea1
Resolve conflicts
t0mmie Oct 5, 2016
f3e8e73
Add hasher options, fix __call method
t0mmie Oct 5, 2016
093c434
Fix unit tests
t0mmie Oct 5, 2016
27cd096
Update changelog
t0mmie Oct 5, 2016
3fef7ee
Update method
Oct 6, 2016
da27d68
Docblock
Oct 6, 2016
53fbb87
Merge pull request #3 from ivarb/feat/update-hashing
t0mmie Oct 6, 2016
82e7826
Fix salt length test
Oct 6, 2016
2939d3f
Add salt length unit test
Oct 6, 2016
6076129
Merge pull request #4 from ivarb/feat/update-hashing
t0mmie Oct 6, 2016
ec7887c
Update docs
Oct 6, 2016
5b98eb3
Update readme
Oct 6, 2016
62353d5
Merge pull request #5 from ivarb/feat/update-hashing
t0mmie Oct 6, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: php
php:
- 5.5
- 5.4
- 5.3
- 7.1
- 7.0
- 5.6

# Notifications
notifications:
Expand Down
120 changes: 120 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Changelog

## 2.0.0

### New Password Hasher

Version `2.0.0` comes with a new password hasher component: `AngryBytes\Hash\Hasher\Password`.
This hasher is intended to be used for hashing of passwords (and other secure tokens).

The hasher utilises PHP's native cryptographically strong password hashing functions:
`password_hash()` and `password_verify()`, see [Password Hashing](http://php.net/manual/en/book.password.php).

The password hasher has been setup to use PHP's default cost and algorithm.
The default cost can however be overwritten by providing a cost to the the constructor, like so:

```php
// Create a password hasher with n cost factor of 15 instead of the default (10).
$passwordHasher = new \AngryBytes\Hash\Hasher\Password(15);
```

#### Password Rehashing
The password hasher offers a method to check if an existing hash needs to be **rehashed**.
For example, this can be the case when the cost and/or algorithm of the password
hasher has changed. If this is the case, you **should** rehash the password
and update the stored hash with the rehashed value.

**Example**

In this example, we check whether an existing password is outdated and should be rehashed.

Note: in order to rehash the password, you will need access to its original plaintext value.
Therefore, it's probably a best practice to check for and update a stale hash
during login procedure, where the plaintext password is available after a login form
submit.

```php
// Create a password hasher
$hasher = new \AngryBytes\Hash\Hash(
new \AngryBytes\Hash\Hasher\Password
);

// Plaintext password received via form submit.
$password = '...';

// Persisted password hash for the User
$userPasswordHash = '...';

// Verify the password against the hash
if ($hasher->verify($password, $userPasswordHash)) {

// Check if the hash needs to be rehashed?
if ($hasher->needsRehash($userPasswordHash)) {
// Rehash password and update the user.
$user->hash = $hasher->hash($password);
$user->save();
}
}
```

### Refactored "AngryBytes\Hash\HasherInterface"

Added new verification method `AngryBytes\Hash\HasherInterface::verify()` hash
verification. This method accepts the following three arguments:

* `$data` - The data that needs to be hashed.
* `$hash` - The hash that needs to match the hashed value of `$data`.
* `$options` (optional) - An array with addition hasher options. What these options are depends on the active hasher.

### Refactored AngryBytes\Hash\Hash

`AngryBytes\Hash\Hash::construct()` second argument (`$salt`) has become optional
to accommodate for hashers that handle their own salt, like `AngryBytes\Hash\Hasher\Password`.

`AngryBytes\Hash\Hash::hash()` and `AngryBytes\Hash\Hash::shortHash()` no longer accept any number of arguments but
only following two:

* `$data` - The data that needs to be hashed. This data can be of any type, all non-scalar types will be
serialized before hashing.
* `$options` (optional) - An array with options that will be passed to the hasher. What these options are depends
on the active hasher.

`AngryBytes\Hash\Hash::verify()` is a new method that's available to validate a hash in a time-safe manner.
The method accepts the following arguments:

* `$data` - The data that needs to be hashed. This data can be of any type, all non-scalar types will be
serialized before hashing.
* `$hash` - The hash that needs to match the hashed value of `$data`.
* `$options` (optional) - An array with options that will be passed to the hasher. What these options are depends
on the active hasher.

`AngryBytes\Hash\Hash::matchesShortHash()` is replaced by `AngryBytes\Hash\Hash::verifyShortHash()` this methods
accepts three arguments (`$data`, `$hash` and `$options`) just like `AngryBytes\Hash\Hash::verify()`.

### Minor Changes

* Scalar values passed to `hash()` and `shortHash()` are no longer serialized.
* `AngryBytes\Hash::compare()` now uses PHP native (timing attack safe) `hash_equals()` function.
* Fixed namespace issues for `AngryBytes\Hash\HMAC`.
* `AngryBytes\Hash\Hash` now implements a `__call()` method that dynamically passes
methods to the active hasher. This allows you to perform calls such as `AngryBytes\Hash::hash($string, ['cost' => 15]);`
without having to call `AngryBytes\Hash::getHasher()` first.

### Upgrading

Please refer to the [upgrade notes](UPGRADING.md).

### Deprecated & Removed Components

* `AngryBytes\Hash\RandomString` has been removed. Better open-source random string generation
libraries are available to do this.

## 1.0.2
Valid Blowfish salts (22 char long composed of ./A-Za-z0-9 characters only) are now used as the salt as-is instead
of md5-ed and substring-ed.

## 1.0.1
Adding travis build status and scrutinizer code qual. img. to readme

## 1.0.0
Initial release
40 changes: 31 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,54 @@
# AngryBytes Hash

[![Author](http://img.shields.io/badge/author-@angrybytes-blue.svg?style=flat-square)](https://twitter.com/angrybytes)
[![Software License](https://img.shields.io/badge/license-proprietary-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Build Status](https://travis-ci.org/AngryBytes/hash.svg?branch=master)](https://travis-ci.org/AngryBytes/hash)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/AngryBytes/hash/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/AngryBytes/hash/?branch=master)

A simple PHP library that simplifies cryptographical hashing. It provides an
object oriented interface to a variety of hashing methods.

## Contents
## Requirements

* PHP `5.6.0` or `PHP 7.0` (recommended)

## Installation

Installation is done via Composer: `composer require angrybytes/hash`.

## Components

### Hash

`AngryBytes\Hash\Hash` is the main hasher class. It uses one of the `Hashers` to do the work.
`AngryBytes\Hash\Hash` is the main hasher class and acts as a helper wrapper
around hashers (i.e. `AngryBytes\Hash\HasherInterface` implementations).

Some of the main features of this component:

Available hashers are:
* Hash strings and/or passwords.
* Create short hashes (e.g. used for identification).
* Compare strings/hashes using a time-safe method.
* Verify a string against a hash using the configured hasher.

### Hashers

This library comes with a set of hashers to be utilised by this hash component (or
to be used on their own):

* `AngryBytes\Hash\Hasher\BlowFish`
* `AngryBytes\Hash\Hasher\MD5`

In addition this class can compare strings/hashes using a time-safe method.
* `AngryBytes\Hash\Hasher\Password`

### HMAC

`AngryBytes\Hash\HMAC` can be used to generate
[HMAC's](http://en.wikipedia.org/wiki/Hash-based_message_authentication_code)
for string messages.

### Random Strings
## Contributing

Before contributing to this project, please read the [contributing notes](CONTRIBUTING.md).

## License

Also included is a basic random string generator in
`AngryBytes\Hash\RandomString`. It targets Unix systems with `/dev/urandom`
available for now.
Please refer to the [license file](LICENSE.md).
74 changes: 74 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Upgrade Notes

This document lists important upgrade nodes and BC breaks per version.

## 2.0.0

### Update Hashing Values

If you are hashing multiple values you will need to change the way their are passed
to the hasher. Instead of passing each variable separately you will need to pass
them as an array. Like so:

```php

// Create a new Password Hasher
$hasher = new \AngryBytes\Hash\Hash(
new \AngryBytes\Hash\Hasher\Password
);

// Old
$hash = $hasher->hash('foo', 'bar', ['foo', 'bar']);

// New
$hash = $hasher->hash([
'foo', 'bar', ['foo', 'bar']
]);
```

The same principle applies to `Hash::shortHash()`.

### Update Hash Validation

In the previous version hash validation would be done by creating a hash and comparing
it to the existing hash. Now, you can simple pass the value(s) to hash and the
existing hash to methods: `verify()` or `verfiyShortHash()`.

```php
// Create a new Password Hasher
$hasher = new \AngryBytes\Hash\Hash(
new \AngryBytes\Hash\Hasher\Password
);

// The origin and hashed values
$valueToHash = '...'
$existingHash = '...';

// Old
$isValid = \AngryBytes\Hash\Hash::compare(
$hasher->hash($valueToHash),
$existingHash
);

// New
$isValid = $hasher->verify($valueToHash, $existingHash)
```

And for short hash comparison:

```php
// Create a new Password Hasher
$hasher = new \AngryBytes\Hash\Hash(
new \AngryBytes\Hash\Hasher\Password
);

// Old
if (Hash::matchShortHash($hasher->shortHash($value), $existingShortHash)) {
// Hash is valid
}

// New
if ($hasher->verifyShortHash($value, $existingShortHash)) {
// Hash is valid
}
```
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"AngryBytes\\Hash": "src"
}
},
"require": {
"php": "~5.6 || ~7.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.x"
"phpunit/phpunit" : "~5.4.0"
}
}
Loading