diff --git a/phpseclib/Crypt/Hash.php b/phpseclib/Crypt/Hash.php index 6baa7664..41afd6d9 100644 --- a/phpseclib/Crypt/Hash.php +++ b/phpseclib/Crypt/Hash.php @@ -1,23 +1,20 @@ * setKey('abcdefg'); * @@ -28,7 +25,9 @@ * @category Crypt * @package Hash * @author Jim Wigginton - * @copyright 2007 Jim Wigginton + * @copyright 2015 Jim Wigginton + * @author Andreas Fischer + * @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 + * @author Andreas Fischer * @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; } } diff --git a/tests/Unit/Crypt/HashTest.php b/tests/Unit/Crypt/HashTest.php index 05681dff..72779ea1 100644 --- a/tests/Unit/Crypt/HashTest.php +++ b/tests/Unit/Crypt/HashTest.php @@ -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), + ); } }