diff --git a/composer.json b/composer.json index a0922c1..30f805a 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.23", "zendframework/zend-math": "self.version", "zendframework/zend-stdlib": "self.version", "zendframework/zend-servicemanager": "self.version" diff --git a/src/BlockCipher.php b/src/BlockCipher.php index 03cc12d..d2c7517 100644 --- a/src/BlockCipher.php +++ b/src/BlockCipher.php @@ -18,7 +18,12 @@ */ class BlockCipher { - const KEY_DERIV_HMAC = 'sha256'; + /** + * Hash algorithm for Pbkdf2 + * + * @var string + */ + protected $pbkdf2Hash = 'sha256'; /** * Symmetric cipher @@ -35,7 +40,7 @@ class BlockCipher protected static $symmetricPlugins = null; /** - * Hash algorithm fot HMAC + * Hash algorithm for HMAC * * @var string */ @@ -72,7 +77,7 @@ class BlockCipher /** * Constructor * - * @param SymmetricInterface $cipher + * @param SymmetricInterface $cipher */ public function __construct(SymmetricInterface $cipher) { @@ -160,7 +165,7 @@ public function getCipher() /** * Set the number of iterations for Pbkdf2 * - * @param int $num + * @param int $num * @return BlockCipher */ public function setKeyIteration($num) @@ -183,7 +188,7 @@ public function getKeyIteration() /** * Set the salt (IV) * - * @param string $salt + * @param string $salt * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -222,7 +227,7 @@ public function getOriginalSalt() /** * Enable/disable the binary output * - * @param bool $value + * @param bool $value * @return BlockCipher */ public function setBinaryOutput($value) @@ -272,7 +277,7 @@ public function getKey() /** * Set algorithm of the symmetric cipher * - * @param string $algo + * @param string $algo * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -321,7 +326,7 @@ public function getCipherSupportedAlgorithms() /** * Set the hash algorithm for HMAC authentication * - * @param string $hash + * @param string $hash * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -347,19 +352,58 @@ public function getHashAlgorithm() return $this->hash; } + /** + * Set the hash algorithm for the Pbkdf2 + * + * @param string $hash + * @return BlockCipher + * @throws Exception\InvalidArgumentException + */ + public function setPbkdf2HashAlgorithm($hash) + { + if (!Hash::isSupported($hash)) { + throw new Exception\InvalidArgumentException( + "The specified hash algorithm '{$hash}' is not supported by Zend\Crypt\Hash" + ); + } + $this->pbkdf2Hash = $hash; + + return $this; + } + + /** + * Get the Pbkdf2 hash algorithm + * + * @return string + */ + public function getPbkdf2HashAlgorithm() + { + return $this->pbkdf2Hash; + } + /** * Encrypt then authenticate using HMAC * - * @param string $data + * @param string $data * @return string * @throws Exception\InvalidArgumentException */ public function encrypt($data) { // 0 (as integer), 0.0 (as float) & '0' (as string) will return false, though these should be allowed - if (!is_string($data) || $data === '') { + // Must be a string, integer, or float in order to encrypt + if ((is_string($data) && $data === '') + || is_array($data) + || is_object($data) + ) { throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty'); } + + // Cast to string prior to encrypting + if (!is_string($data)) { + $data = (string) $data; + } + if (empty($this->cipher)) { throw new Exception\InvalidArgumentException('No symmetric cipher specified'); } @@ -372,7 +416,7 @@ public function encrypt($data) $this->cipher->setSalt(Rand::getBytes($this->cipher->getSaltSize(), true)); } // generate the encryption key and the HMAC key for the authentication - $hash = Pbkdf2::calc(self::KEY_DERIV_HMAC, + $hash = Pbkdf2::calc($this->getPbkdf2HashAlgorithm(), $this->getKey(), $this->getSalt(), $this->keyIteration, @@ -397,7 +441,7 @@ public function encrypt($data) /** * Decrypt * - * @param string $data + * @param string $data * @return string|bool * @throws Exception\InvalidArgumentException */ @@ -424,7 +468,7 @@ public function decrypt($data) $iv = substr($ciphertext, 0, $this->cipher->getSaltSize()); $keySize = $this->cipher->getKeySize(); // generate the encryption key and the HMAC key for the authentication - $hash = Pbkdf2::calc(self::KEY_DERIV_HMAC, + $hash = Pbkdf2::calc($this->getPbkdf2HashAlgorithm(), $this->getKey(), $iv, $this->keyIteration, diff --git a/src/Key/Derivation/Scrypt.php b/src/Key/Derivation/Scrypt.php index 6140cb8..e4e37d7 100644 --- a/src/Key/Derivation/Scrypt.php +++ b/src/Key/Derivation/Scrypt.php @@ -328,7 +328,7 @@ protected static function integerify($b) */ protected static function hex2bin($hex) { - if (version_compare(PHP_VERSION, '5.4') >= 0) { + if (PHP_VERSION_ID >= 50400) { return hex2bin($hex); } $len = strlen($hex); diff --git a/src/Password/Apache.php b/src/Password/Apache.php index 3d90761..47be2b1 100644 --- a/src/Password/Apache.php +++ b/src/Password/Apache.php @@ -116,7 +116,7 @@ public function create($password) } /** - * Verify if a password is correct against an hash value + * Verify if a password is correct against a hash value * * @param string $password * @param string $hash diff --git a/src/Password/Bcrypt.php b/src/Password/Bcrypt.php index 851f109..b489ddd 100644 --- a/src/Password/Bcrypt.php +++ b/src/Password/Bcrypt.php @@ -22,8 +22,12 @@ class Bcrypt implements PasswordInterface /** * @var string + * + * Changed from 14 to 10 to prevent possibile DOS attacks + * due to the high computational time + * @see http://timoh6.github.io/2013/11/26/Aggressive-password-stretching.html */ - protected $cost = '14'; + protected $cost = '10'; /** * @var string @@ -83,7 +87,7 @@ public function create($password) * Check for security flaw in the bcrypt implementation used by crypt() * @see http://php.net/security/crypt_blowfish.php */ - if ((version_compare(PHP_VERSION, '5.3.7') >= 0) && !$this->backwardCompatibility) { + if ((PHP_VERSION_ID >= 50307) && !$this->backwardCompatibility) { $prefix = '$2y$'; } else { $prefix = '$2a$'; @@ -104,7 +108,7 @@ public function create($password) } /** - * Verify if a password is correct against an hash value + * Verify if a password is correct against a hash value * * @param string $password * @param string $hash @@ -117,22 +121,6 @@ public function verify($password, $hash) if ($result === $hash) { return true; } - if (strlen($result) <= 13) { - /* This should only happen if the algorithm that generated hash is - * either unsupported by this version of crypt(), or is invalid. - * - * An example of when this can happen, is if you generate - * non-backwards-compatible hashes on 5.3.7+, and then try to verify - * them on < 5.3.7. - * - * This is needed, because version comparisons are not possible due - * to back-ported functionality by some distributions. - */ - throw new Exception\RuntimeException( - 'The supplied password hash could not be verified. Please check ' . - 'backwards compatibility settings.' - ); - } return false; } diff --git a/src/Symmetric/Mcrypt.php b/src/Symmetric/Mcrypt.php index 7410a8d..2c6c90d 100755 --- a/src/Symmetric/Mcrypt.php +++ b/src/Symmetric/Mcrypt.php @@ -326,7 +326,8 @@ public function getPadding() */ public function encrypt($data) { - if (empty($data)) { + // Cannot encrypt empty string + if (!is_string($data) || $data === '') { throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty'); } if (null === $this->getKey()) { diff --git a/test/BlockCipherTest.php b/test/BlockCipherTest.php index 1940ab3..14826ff 100644 --- a/test/BlockCipherTest.php +++ b/test/BlockCipherTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -99,6 +99,13 @@ public function testSetHashAlgorithm() $this->assertEquals('sha1', $this->blockCipher->getHashAlgorithm()); } + public function testSetPbkdf2HashAlgorithm() + { + $result = $this->blockCipher->setPbkdf2HashAlgorithm('sha1'); + $this->assertEquals($result, $this->blockCipher); + $this->assertEquals('sha1', $this->blockCipher->getPbkdf2HashAlgorithm()); + } + public function testSetKeyIteration() { $result = $this->blockCipher->setKeyIteration(1000); @@ -149,6 +156,32 @@ public function testEncryptDecryptUsingBinary() } } + public function zeroValuesProvider() + { + return array( + '"0"' => array(0), + '"0.0"' => array(0.0), + '"0"' => array('0'), + ); + } + + /** + * @dataProvider zeroValuesProvider + */ + public function testEncryptDecryptUsingZero($value) + { + $this->blockCipher->setKey('test'); + $this->blockCipher->setKeyIteration(1000); + foreach ($this->blockCipher->getCipherSupportedAlgorithms() as $algo) { + $this->blockCipher->setCipherAlgorithm($algo); + + $encrypted = $this->blockCipher->encrypt($value); + $this->assertTrue(!empty($encrypted)); + $decrypted = $this->blockCipher->decrypt($encrypted); + $this->assertEquals($value, $decrypted); + } + } + public function testDecryptAuthFail() { $this->blockCipher->setKey('test'); diff --git a/test/HashTest.php b/test/HashTest.php index 92617c7..b4fc831 100644 --- a/test/HashTest.php +++ b/test/HashTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/HmacTest.php b/test/HmacTest.php index d2113b6..0f36290 100644 --- a/test/HmacTest.php +++ b/test/HmacTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Key/Derivation/Pbkdf2Test.php b/test/Key/Derivation/Pbkdf2Test.php index 00c6be8..49154fc 100644 --- a/test/Key/Derivation/Pbkdf2Test.php +++ b/test/Key/Derivation/Pbkdf2Test.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Key/Derivation/SaltedS2kTest.php b/test/Key/Derivation/SaltedS2kTest.php index 27de897..4dc6abf 100644 --- a/test/Key/Derivation/SaltedS2kTest.php +++ b/test/Key/Derivation/SaltedS2kTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Key/Derivation/ScryptTest.php b/test/Key/Derivation/ScryptTest.php index 6280743..a12c276 100644 --- a/test/Key/Derivation/ScryptTest.php +++ b/test/Key/Derivation/ScryptTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -133,12 +133,12 @@ public function testVectorScryptROMix() */ public function testVectorScrypt() { - $hexOutput = '77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 - f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 - fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 - e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06'; + $hexOutput = 'd3 3c 6e c1 81 8d aa f7 28 f5 5a fa df ea a5 58 + b3 8e fa 81 30 5b 35 21 a7 f1 2f 4b e0 97 e8 4d + 18 40 92 d2 a2 e9 3b f7 1f d1 ef e0 52 71 0f 66 + b9 56 ce 45 da 43 aa 90 99 de 74 06 d3 a0 5e 2a'; - $result = Scrypt::calc('', '', 16, 1, 1, 64); + $result = Scrypt::calc('password', '', 16, 1, 1, 64); $this->assertEquals(64, strlen($result)); $this->assertEquals(str_replace(array(' ',PHP_EOL),'',$hexOutput), bin2hex($result)); } diff --git a/test/Password/ApacheTest.php b/test/Password/ApacheTest.php index 81e59fd..cb5aeb1 100644 --- a/test/Password/ApacheTest.php +++ b/test/Password/ApacheTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Password/BcryptTest.php b/test/Password/BcryptTest.php index 09572c0..d7833cc 100644 --- a/test/Password/BcryptTest.php +++ b/test/Password/BcryptTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -32,12 +32,9 @@ public function setUp() $this->bcrypt = new Bcrypt(); $this->salt = '1234567890123456'; $this->password = 'test'; - if (version_compare(PHP_VERSION, '5.3.7') >= 0) { - $this->prefix = '$2y$'; - } else { - $this->prefix = '$2a$'; - } - $this->bcryptPassword = $this->prefix . '14$MTIzNDU2Nzg5MDEyMzQ1NeWUUefVlefsTbFhsbqKFv/vPSZBrSFVm'; + $this->prefix = '$2y$'; + + $this->bcryptPassword = $this->prefix . '10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y'; } public function testConstructByOptions() @@ -118,38 +115,13 @@ public function testVerify() $this->assertFalse($this->bcrypt->verify(substr($this->password, -1), $this->bcryptPassword)); } - public function testVerifyFailureVersion() - { - $test = (substr(crypt('test', '$2y$04$012345678901234567890123456789'), 0, 3) === '$2y'); - if (!$test) { - // We don't support new style hashes, test verify failure - $hash = '$y2$14$MTIzNDU2Nzg5MDEyMzQ1NeWUUefVlefsTbFhsbqKFv/vPSZBrSFVm'; - $this->setExpectedException('Zend\Crypt\Password\Exception\RuntimeException', - 'The supplied password hash could not be verified. Please check ' . - 'backwards compatibility settings.' - ); - $this->bcrypt->verify('test', $hash); - } else { - $this->markTestSkipped('Test requires PHP which does not support $2y hashes (<5.3.7)'); - } - } - public function testPasswordWith8bitCharacter() { $password = 'test' . chr(128); $this->bcrypt->setSalt($this->salt); - if (version_compare(PHP_VERSION, '5.3.7') >= 0) { - $this->assertEquals('$2y$14$MTIzNDU2Nzg5MDEyMzQ1NexAbOIUHkG6Ra.TK9QxHOVUhDxOe4dkW', + $this->assertEquals('$2y$10$MTIzNDU2Nzg5MDEyMzQ1NemFdU/4JOrNpxMym09Mbp0m4hKTgfQo.', $this->bcrypt->create($password)); - } else { - $this->setExpectedException('Zend\Crypt\Password\Exception\RuntimeException', - 'The bcrypt implementation used by PHP can contain a security flaw ' . - 'using password with 8-bit character. ' . - 'We suggest to upgrade to PHP 5.3.7+ or use passwords with only 7-bit characters' - ); - $output = $this->bcrypt->create($password); - } } public function testSetBackwardCompatibility() diff --git a/test/PublicKey/DiffieHellmanTest.php b/test/PublicKey/DiffieHellmanTest.php index 1a5ecbf..f654157 100644 --- a/test/PublicKey/DiffieHellmanTest.php +++ b/test/PublicKey/DiffieHellmanTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/PublicKey/RsaTest.php b/test/PublicKey/RsaTest.php index 5e2766e..e60fe4a 100644 --- a/test/PublicKey/RsaTest.php +++ b/test/PublicKey/RsaTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Symmetric/McryptTest.php b/test/Symmetric/McryptTest.php index 57a8ecc..369cd12 100644 --- a/test/Symmetric/McryptTest.php +++ b/test/Symmetric/McryptTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/Symmetric/Padding/Pkcs7Test.php b/test/Symmetric/Padding/Pkcs7Test.php index 4bb743b..0758f01 100644 --- a/test/Symmetric/Padding/Pkcs7Test.php +++ b/test/Symmetric/Padding/Pkcs7Test.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/test/UtilsTest.php b/test/UtilsTest.php index 04b0eb0..534cd57 100644 --- a/test/UtilsTest.php +++ b/test/UtilsTest.php @@ -3,7 +3,7 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */