Merge pull request #813 from bantu/hash-rewrite

[master] More work on Hash.php

* bantu/hash-rewrite:
  Hash: Cover remaining uncovered line.
  Hash: Update incorrect documentation, use max line length 80.
  Hash: Remove constructor return value documentation.
  Hash: Do not assign false to length property. It's documented as an int.
  Hash: Rename properly l to length.
  Slightly rework of HashTest.php.
This commit is contained in:
Andreas Fischer 2015-09-14 22:47:37 +02:00
commit 3b33941d3d
2 changed files with 103 additions and 51 deletions

View File

@ -1,23 +1,20 @@
<?php
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
* Wrapper around hash() and hash_hmac() functions supporting truncated hashes
* such as sha256-96. Any hash algorithm returned by hash_algos() (and
* truncated versions thereof) are supported.
*
* Basically a wrapper for hash(). Currently supports the following:
*
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
*
* If {@link \phpseclib\Crypt\Hash::setKey() setKey()} is called, {@link \phpseclib\Crypt\Hash::hash() hash()} will return the HMAC as opposed to
* the hash. If no valid algorithm is provided, sha1 will be used.
*
* PHP version 5
* If {@link \phpseclib\Crypt\Hash::setKey() setKey()} is called,
* {@link \phpseclib\Crypt\Hash::hash() hash()} will return the HMAC as opposed
* to the hash.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include 'vendor/autoload.php';
*
* $hash = new \phpseclib\Crypt\Hash('sha1');
* $hash = new \phpseclib\Crypt\Hash('sha512');
*
* $hash->setKey('abcdefg');
*
@ -28,7 +25,9 @@
* @category Crypt
* @package Hash
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2007 Jim Wigginton
* @copyright 2015 Jim Wigginton
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright 2015 Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
@ -38,10 +37,9 @@ namespace phpseclib\Crypt;
use phpseclib\Exception\UnsupportedAlgorithmException;
/**
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
*
* @package Hash
* @author Jim Wigginton <terrafrost@php.net>
* @author Andreas Fischer <bantu@phpbb.com>
* @access public
*/
class Hash
@ -62,7 +60,7 @@ class Hash
* @var int
* @access private
*/
var $l = false;
var $length;
/**
* Hash Algorithm
@ -86,7 +84,6 @@ class Hash
* Default Constructor.
*
* @param string $hash
* @return \phpseclib\Crypt\Hash
* @access public
*/
function __construct($hash = 'sha256')
@ -135,36 +132,44 @@ class Hash
case 'sha256-96':
case 'sha512-96':
$hash = substr($hash, 0, -3);
$this->l = 12; // 96 / 8 = 12
$this->length = 12; // 96 / 8 = 12
break;
case 'md2':
case 'md5':
$this->l = 16;
$this->length = 16;
break;
case 'sha1':
$this->l = 20;
$this->length = 20;
break;
case 'sha256':
$this->l = 32;
$this->length = 32;
break;
case 'sha384':
$this->l = 48;
$this->length = 48;
break;
case 'sha512':
$this->l = 64;
$this->length = 64;
break;
default:
// see if the hash isn't "officially" supported see if it can be "unofficially" supported and calculate the length accordingly
// see if the hash isn't "officially" supported see if it can
// be "unofficially" supported and calculate the length
// accordingly.
if (in_array($hash, hash_algos())) {
$this->l = strlen(hash($hash, '', true));
$this->length = strlen(hash($hash, '', true));
break;
}
// if the hash algorithm doens't exist maybe it's a truncated hash. eg. md5-96 or some such
if (preg_match('#(-\d+)$#', $hash, $matches) && in_array($hash = substr($hash, 0, -strlen($matches[1])), hash_algos())) {
$this->l = abs($matches[1]) >> 3;
break;
// if the hash algorithm doens't exist maybe it's a truncated
// hash, e.g. whirlpool-12 or some such.
if (preg_match('#(-\d+)$#', $hash, $matches)) {
$hash = substr($hash, 0, -strlen($matches[1]));
if (in_array($hash, hash_algos())) {
$this->length = abs($matches[1]) >> 3;
break;
}
}
throw new UnsupportedAlgorithmException("$hash is not a supported algorithm");
throw new UnsupportedAlgorithmException(
"$hash is not a supported algorithm"
);
}
$this->hash = $hash;
@ -183,7 +188,9 @@ class Hash
hash_hmac($this->hash, $text, $this->key, true) :
hash($this->hash, $text, true);
return strlen($output) > $this->l ? substr($output, 0, $this->l) : $output;
return strlen($output) > $this->length
? substr($output, 0, $this->length)
: $output;
}
/**
@ -194,6 +201,6 @@ class Hash
*/
function getLength()
{
return $this->l;
return $this->length;
}
}

View File

@ -13,7 +13,7 @@ class Unit_Crypt_HashTest extends PhpseclibTestCase
{
$hash = new Hash($hash);
$this->assertEquals(
$this->assertSame(
strtolower($expected),
bin2hex($hash->hash($message)),
sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected)
@ -25,7 +25,7 @@ class Unit_Crypt_HashTest extends PhpseclibTestCase
$hash = new Hash($hash);
$hash->setKey($key);
$this->assertEquals(
$this->assertSame(
strtolower($expected),
bin2hex($hash->hash($message)),
sprintf(
@ -43,6 +43,8 @@ class Unit_Crypt_HashTest extends PhpseclibTestCase
array('md5', '', 'd41d8cd98f00b204e9800998ecf8427e'),
array('md5', 'The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'),
array('md5', 'The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'),
array('sha1', 'The quick brown fox jumps over the lazy dog', '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'),
array('sha1', 'The quick brown fox jumps over the lazy dog.', '408d94384216f890ff7a0c3528e8bed1e0b01621'),
array(
'sha256',
'',
@ -58,6 +60,16 @@ class Unit_Crypt_HashTest extends PhpseclibTestCase
'The quick brown fox jumps over the lazy dog.',
'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c',
),
array(
'sha384',
'',
'38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b'
),
array(
'sha384',
'The quick brown fox jumps over the lazy dog',
'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1',
),
array(
'sha512',
'',
@ -190,31 +202,64 @@ class Unit_Crypt_HashTest extends PhpseclibTestCase
$this->assertHashesTo($hash . '-96', $message, substr($result, 0, 24));
}
public function testGetHash()
public function testConstructorDefault()
{
$hash = new Hash();
$this->assertEquals($hash->getHash(), 'sha256');
$hash = new Hash('whirlpool');
$this->assertEquals($hash->getHash(), 'whirlpool');
$hash = new Hash('md5');
$this->assertEquals($hash->getHash(), 'md5');
$hash->setHash('whirlpool');
$this->assertEquals($hash->getHash(), 'whirlpool');
$hash->setHash('md5');
$this->assertEquals($hash->getHash(), 'md5');
$this->assertSame($hash->getHash(), 'sha256');
}
public function testGetLength()
/**
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
*/
public function testConstructorArgumentInvalid()
{
new Hash('abcdefghijklmnopqrst');
}
public function testConstructorArgumentValid()
{
$hash = new Hash();
$this->assertEquals($hash->getLength(), 32);
$hash = new Hash('whirlpool');
$this->assertEquals($hash->getLength(), 64);
$this->assertSame($hash->getHash(), 'whirlpool');
}
/**
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
*/
public function testSetHashInvalid()
{
$hash = new Hash('md5');
$this->assertEquals($hash->getLength(), 16);
$hash->setHash('whirlpool');
$this->assertEquals($hash->getLength(), 64);
$hash->setHash('md5');
$this->assertEquals($hash->getLength(), 16);
$hash->setHash('abcdefghijklmnopqrst-96');
}
public function testSetHashValid()
{
$hash = new Hash('md5');
$this->assertSame($hash->getHash(), 'md5');
$hash->setHash('sha1');
$this->assertSame($hash->getHash(), 'sha1');
}
/**
* @dataProvider lengths
*/
public function testGetLengthKnown($algorithm, $length)
{
$hash = new Hash($algorithm);
$this->assertSame($hash->getLength(), $length);
}
public function lengths()
{
return array(
// known
array('md5-96', 12),
array('md5', 16),
array('sha1', 20),
array('sha256', 32),
array('sha384', 48),
array('sha512', 64),
// unknown
array('whirlpool', 64),
);
}
}