Skip to content

Commit

Permalink
Merge pull request #20 from AngryBytes/feat/php80
Browse files Browse the repository at this point in the history
PHP 8.0 support
  • Loading branch information
t0mmie authored May 7, 2021
2 parents 8efb206 + 10da6f4 commit 6bff493
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 126 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/php-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
on: [push]
name: PHP checks
jobs:
composer-check:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['7.3', '7.4', '8.0']
name: PHP ${{ matrix.php-versions }} tests
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: cs2pr

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}

- name: Run Composer install
run: composer install --prefer-dist

- name: Run PHP checks
run: composer phpcheck

- name: Run PHPUnit
run: composer phpunit
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.phpunit.*
composer.lock
vendor
13 changes: 0 additions & 13 deletions .travis.yml

This file was deleted.

48 changes: 30 additions & 18 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 3.0.0

## PHP Support

The minimum supported PHP version is now 7.3.

Support was added for PHP 8.0

## 2.0.0

### New Password Hasher
Expand All @@ -19,6 +27,7 @@ $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
Expand Down Expand Up @@ -46,7 +55,7 @@ $password = '...';
$userPasswordHash = '...';

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

// Check if the hash needs to be rehashed?
if ($hasher->needsRehash($userPasswordHash)) {
Expand All @@ -62,9 +71,9 @@ if ($hasher->verify($password, $userPasswordHash)) {
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.
- `$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

Expand All @@ -74,29 +83,29 @@ to accommodate for hashers that handle their own salt, like `AngryBytes\Hash\Has
`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.
- `$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.
- `$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
- 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.

Expand All @@ -106,15 +115,18 @@ Please refer to the [upgrade notes](UPGRADING.md).

### Deprecated & Removed Components

* `AngryBytes\Hash\RandomString` has been removed. Better open-source random string generation
- `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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object oriented interface to a variety of hashing methods.

## Requirements

* PHP `5.6.0` or `PHP 7.0` (recommended)
* PHP `7.3`, `7.4` or PHP `8.0` (recommended)

## Installation

Expand Down
66 changes: 40 additions & 26 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
{
"name": "angrybytes/hash",
"description": "Object Oriented hash interface",
"authors": [
{
"name": "Angry Bytes BV",
"email": "[email protected]",
"role": "owner",
"homepage": "http://angrybytes.com/"
},
{
"name": "Maurice Fonk",
"email": "[email protected]",
"role": "developer"
}
],
"minimum-stability": "stable",
"license": "MIT",
"autoload": {
"psr-0": {
"AngryBytes\\Hash": "src"
}
},
"require": {
"php": "~5.6 || ~7.0"
"name": "angrybytes/hash",
"description": "Object Oriented hash interface",
"authors": [
{
"name": "Angry Bytes BV",
"email": "[email protected]",
"role": "owner",
"homepage": "http://angrybytes.com/"
},
"require-dev": {
"phpunit/phpunit" : "~5.4.0"
{
"name": "Maurice Fonk",
"email": "[email protected]",
"role": "developer"
}
],
"minimum-stability": "stable",
"license": "MIT",
"autoload": {
"psr-0": {
"AngryBytes\\Hash": "src"
}
},
"scripts": {
"phpcheck": [
"./vendor/bin/phpstan analyse -l max --memory-limit=1G src/",
"./vendor/bin/phpcs -p --standard=PSR2 --extensions=php src/"
],
"phpcbf": [
"./vendor/bin/phpcbf -p --standard=PSR2 --extensions=php src/"
],
"phpunit": [
"./vendor/bin/phpunit"
]
},
"require": {
"php": "7.3.* || 7.4.* || 8.0.*"
},
"require-dev": {
"phpstan/phpstan": "0.12.85",
"phpunit/phpunit": "^9.5.4",
"squizlabs/php_codesniffer": "^3.6.0"
}
}
8 changes: 8 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
parameters:
reportUnmatchedIgnoredErrors: false
ignoreErrors:
-
message: "#^Strict comparison using \\=\\=\\= between string and false will always evaluate to false\\.$#"
count: 1
path: src/AngryBytes/Hash/Hasher/Password.php

15 changes: 4 additions & 11 deletions src/AngryBytes/Hash/HMAC.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,15 @@ public static function platformSupportsAlgorithm($algorithm)
* This method accepts multiple variables as input, but is restricted to
* strings. All input will be concatenated before hashing.
*
* @param string $sharedSecret
* @param array $args
* @param string $sharedSecret
* @param string[] $args
* @return string
*/
public function hmac($sharedSecret, ...$args)
{
// Get the data concatenated
$data = '';
foreach ($args as $index => $arg) {
// Sanity check
if (!is_string($arg)) {
throw new InvalidArgumentException(sprintf(
'Received a non-string argument at "%s"',
$index
));
}

$data .= $arg;
}

Expand Down Expand Up @@ -111,7 +103,8 @@ protected function setAlgorithm($algorithm)
// Sanity check
if (!self::platformSupportsAlgorithm($algorithm)) {
throw new InvalidArgumentException(sprintf(
'"%s" is not a supported hash algorithm on this platform'
'"%s" is not a supported hash algorithm on this platform',
$algorithm
));
}

Expand Down
13 changes: 8 additions & 5 deletions src/AngryBytes/Hash/Hash.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Hash
* Constructor
*
* @param HasherInterface $hasher The hasher to be used
* @param string|bool $salt (optional) Omit if the hasher creates its own (better) salt
* @param ?string $salt (optional) Omit if the hasher creates its own (better) salt
**/
public function __construct(HasherInterface $hasher, $salt = null)
{
Expand All @@ -55,8 +55,9 @@ public function __construct(HasherInterface $hasher, $salt = null)
/**
* Dynamically pass methods to the active hasher
*
* @param string $method
* @param array $parameters
* @param string $method
* @param mixed[] $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
Expand Down Expand Up @@ -91,7 +92,8 @@ public function hash($data, array $options = [])
/**
* Verify if the data matches the hash
*
* @param mixed $data The data to verify against the hash string. This can either be a scalar value or a serializable value.
* @param mixed $data The data to verify against the hash string.
* This can either be a scalar value or a serializable value.
* @param string $hash
* @param mixed[] $options
* @return bool
Expand Down Expand Up @@ -169,7 +171,8 @@ protected function setSalt($salt)
if (is_string($salt) && (strlen($salt) < 20 || strlen($salt) > CRYPT_SALT_LENGTH)) {
// Make sure it's of sufficient length
throw new InvalidArgumentException(sprintf(
'Provided salt "%s" does not match the length requirements. A length between 20 en %d characters is required.',
'Provided salt "%s" does not match the length requirements. ' .
'A length between 20 en %d characters is required.',
$salt,
CRYPT_SALT_LENGTH
));
Expand Down
13 changes: 4 additions & 9 deletions src/AngryBytes/Hash/Hasher/Blowfish.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ class Blowfish implements HasherInterface
*/
public function __construct($workFactor = null)
{
if (!defined("CRYPT_BLOWFISH") || CRYPT_BLOWFISH !== 1) {
throw new RuntimeException(
'Blowfish hashing not available on this installation'
);
}

if (is_int($workFactor)) {
$this->setWorkFactor($workFactor);
}
Expand Down Expand Up @@ -91,7 +85,7 @@ public function setWorkFactor($workFactor)
*/
public function hash($string, array $options = [])
{
$salt = isset($options['salt']) ? $this->bcryptSalt($options['salt']) : null;
$salt = isset($options['salt']) ? $this->bcryptSalt($options['salt']) : '';

return crypt($string, $salt);
}
Expand Down Expand Up @@ -119,7 +113,7 @@ private function bcryptSalt($salt)
{
return '$2y$'
// Pad workfactor with 0's to the left, max 2 chars long
. str_pad($this->getWorkFactor(), 2, '0', STR_PAD_LEFT)
. str_pad((string) $this->getWorkFactor(), 2, '0', STR_PAD_LEFT)
// Add salt itself
. '$' .
self::getSaltSubstr($salt)
Expand All @@ -146,7 +140,8 @@ private static function getSaltSubstr($salt)
// fallback to md5() to make the salt valid
return substr(
md5($salt),
0, 22
0,
22
);
}
}
Loading

0 comments on commit 6bff493

Please sign in to comment.