From 9c0d287a4ebfc214a9394343c9f50b39835190fd Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Thu, 24 Jan 2013 14:43:56 +0100 Subject: [PATCH 1/6] Fix for the issue 3541 --- library/Zend/Crypt/BlockCipher.php | 2 +- library/Zend/Crypt/Symmetric/Mcrypt.php | 13 +++----- tests/ZendTest/Crypt/BlockCipherTest.php | 8 +++++ tests/ZendTest/Crypt/Symmetric/McryptTest.php | 31 +++++-------------- tests/ZendTest/Filter/DecryptTest.php | 14 +++++++++ tests/ZendTest/Filter/EncryptTest.php | 14 +++++++++ 6 files changed, 49 insertions(+), 33 deletions(-) diff --git a/library/Zend/Crypt/BlockCipher.php b/library/Zend/Crypt/BlockCipher.php index 33811a87488..2633dea3197 100644 --- a/library/Zend/Crypt/BlockCipher.php +++ b/library/Zend/Crypt/BlockCipher.php @@ -360,7 +360,7 @@ public function encrypt($data) // generate the encryption key and the HMAC key for the authentication $hash = Pbkdf2::calc(self::KEY_DERIV_HMAC, $this->getKey(), - $this->cipher->getSalt(), + substr($this->cipher->getSalt(), 0, $this->cipher->getSaltSize()), $this->keyIteration, $keySize * 2); // set the encryption key diff --git a/library/Zend/Crypt/Symmetric/Mcrypt.php b/library/Zend/Crypt/Symmetric/Mcrypt.php index 97c9ae64978..3eb27d23490 100644 --- a/library/Zend/Crypt/Symmetric/Mcrypt.php +++ b/library/Zend/Crypt/Symmetric/Mcrypt.php @@ -161,9 +161,6 @@ public function __construct($options = array()) */ protected function setDefaultOptions($options = array()) { - if (empty($options)) { - return; - } if (!isset($options['padding'])) { $plugins = static::getPaddingPluginManager(); $padding = $plugins->get(self::DEFAULT_PADDING); @@ -321,11 +318,6 @@ public function encrypt($data) if (null === $this->getSalt()) { throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty'); } - if (strlen($this->getSalt()) < $this->getSaltSize()) { - throw new Exception\InvalidArgumentException( - 'The size of the salt (IV) is not enough. You need ' . $this->getSaltSize() . ' bytes' - ); - } if (null === $this->getPadding()) { throw new Exception\InvalidArgumentException('You have to specify a padding method'); } @@ -408,6 +400,11 @@ public function setSalt($salt) if (empty($salt)) { throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty'); } + if (strlen($salt) < $this->getSaltSize()) { + throw new Exception\InvalidArgumentException( + 'The size of the salt (IV) must be at least ' . $this->getSaltSize() . ' bytes' + ); + } $this->iv = $salt; return $this; } diff --git a/tests/ZendTest/Crypt/BlockCipherTest.php b/tests/ZendTest/Crypt/BlockCipherTest.php index 7aec6a1cee9..f133745bfee 100644 --- a/tests/ZendTest/Crypt/BlockCipherTest.php +++ b/tests/ZendTest/Crypt/BlockCipherTest.php @@ -71,6 +71,14 @@ public function testSetKey() $this->assertEquals('test', $this->blockCipher->getKey()); } + public function testSetSalt() + { + $salt = str_repeat('a', $this->blockCipher->getCipher()->getSaltSize()); + $result = $this->blockCipher->setSalt($salt); + $this->assertEquals($result, $this->blockCipher); + $this->assertEquals($salt, $this->blockCipher->getSalt()); + } + public function testSetAlgorithm() { $result = $this->blockCipher->setCipherAlgorithm('blowfish'); diff --git a/tests/ZendTest/Crypt/Symmetric/McryptTest.php b/tests/ZendTest/Crypt/Symmetric/McryptTest.php index 3c147a3e07a..bdbe792ef93 100644 --- a/tests/ZendTest/Crypt/Symmetric/McryptTest.php +++ b/tests/ZendTest/Crypt/Symmetric/McryptTest.php @@ -125,17 +125,17 @@ public function testSetShortKey() public function testSetSalt() { - $this->mcrypt->setSalt($this->salt); - $this->assertEquals($this->salt, $this->mcrypt->getSalt()); + $salt = substr($this->salt, 0, $this->mcrypt->getSaltSize()); + $this->mcrypt->setSalt($salt); + $this->assertEquals($salt, $this->mcrypt->getSalt()); } + /** + * @expectedException Zend\Crypt\Symmetric\Exception\InvalidArgumentException + */ public function testShortSalt() { $this->mcrypt->setSalt('short'); - $this->mcrypt->setKey($this->key); - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'The size of the salt (IV) is not enough. You need 16 bytes'); - $output = $this->mcrypt->encrypt('test'); } public function testSetMode() @@ -153,13 +153,13 @@ public function testSetWrongMode() public function testEncryptDecrypt() { - $this->mcrypt->setSalt($this->salt); $this->mcrypt->setKey($this->key); $this->mcrypt->setPadding(new PKCS7()); foreach ($this->mcrypt->getSupportedAlgorithms() as $algo) { foreach ($this->mcrypt->getSupportedModes() as $mode) { $this->mcrypt->setAlgorithm($algo); $this->mcrypt->setMode($mode); + $this->mcrypt->setSalt($this->salt); $encrypted = $this->mcrypt->encrypt($this->plaintext); $this->assertTrue(!empty($encrypted)); $decrypted = $this->mcrypt->decrypt($encrypted); @@ -191,15 +191,6 @@ public function testEncryptWihoutSalt() $ciphertext = $this->mcrypt->encrypt($this->plaintext); } - public function testEncryptWithoutPadding() - { - $this->mcrypt->setKey($this->key); - $this->mcrypt->setSalt($this->salt); - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'You have to specify a padding method'); - $ciphertext = $this->mcrypt->encrypt($this->plaintext); - } - public function testDecryptEmptyData() { $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', @@ -213,12 +204,4 @@ public function testDecryptWithoutKey() 'No key specified for the decryption'); $this->mcrypt->decrypt($this->plaintext); } - - public function testDecryptWihoutPadding() - { - $this->mcrypt->setKey($this->key); - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'You have to specify a padding method'); - $this->mcrypt->decrypt($this->plaintext); - } } diff --git a/tests/ZendTest/Filter/DecryptTest.php b/tests/ZendTest/Filter/DecryptTest.php index 04b9ac272a6..00be3d865f3 100644 --- a/tests/ZendTest/Filter/DecryptTest.php +++ b/tests/ZendTest/Filter/DecryptTest.php @@ -53,6 +53,20 @@ public function testBasicMcrypt() } } + /** + * Ensures that the encryption works fine + */ + public function testDecryptBlockCipher() + { + if (!extension_loaded('mcrypt')) { + $this->markTestSkipped('Mcrypt extension not installed'); + } + $decrypt = new DecryptFilter(array('adapter' => 'BlockCipher', 'key' => 'testkey')); + $decrypt->setVector('1234567890123456890'); + $decrypted = $decrypt->filter('ec133eb7460682b0020b736ad6d2ef14c35de0f1e5976330ae1dd096ef3b4cb7MTIzNDU2Nzg5MDEyMzQ1NoZvxY1JkeL6TnQP3ug5F0k='); + $this->assertEquals($decrypted, 'test'); + } + /** * Ensures that the filter follows expected behavior * diff --git a/tests/ZendTest/Filter/EncryptTest.php b/tests/ZendTest/Filter/EncryptTest.php index 86b7fedd9e6..5ec4b65cec0 100644 --- a/tests/ZendTest/Filter/EncryptTest.php +++ b/tests/ZendTest/Filter/EncryptTest.php @@ -53,6 +53,20 @@ public function testBasicBlockCipher() } } + /** + * Ensures that the encryption works fine + */ + public function testEncryptBlockCipher() + { + if (!extension_loaded('mcrypt')) { + $this->markTestSkipped('Mcrypt extension not installed'); + } + $encrypt = new EncryptFilter(array('adapter' => 'BlockCipher', 'key' => 'testkey')); + $encrypt->setVector('1234567890123456890'); + $encrypted = $encrypt->filter('test'); + $this->assertEquals($encrypted, 'ec133eb7460682b0020b736ad6d2ef14c35de0f1e5976330ae1dd096ef3b4cb7MTIzNDU2Nzg5MDEyMzQ1NoZvxY1JkeL6TnQP3ug5F0k='); + } + /** * Ensures that the filter follows expected behavior * From 713c51c14d76a7f89b1ca6bc48824c59860f41ab Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 25 Jan 2013 14:51:38 +0100 Subject: [PATCH 2/6] Changed the get/setSalt in Mcrypt and BlockCipher + added the setKey in Filter\Encrypt and Filter\Decrypt --- library/Zend/Crypt/BlockCipher.php | 75 +++++++++++-------- library/Zend/Crypt/Symmetric/Mcrypt.php | 60 ++++++++++----- library/Zend/Filter/Encrypt/BlockCipher.php | 32 +++++++- tests/ZendTest/Crypt/Symmetric/McryptTest.php | 17 ++--- tests/ZendTest/Filter/DecryptTest.php | 7 +- .../Filter/Encrypt/BlockCipherTest.php | 32 ++++---- tests/ZendTest/Filter/File/DecryptTest.php | 8 +- tests/ZendTest/Filter/File/EncryptTest.php | 10 +-- 8 files changed, 150 insertions(+), 91 deletions(-) diff --git a/library/Zend/Crypt/BlockCipher.php b/library/Zend/Crypt/BlockCipher.php index 2633dea3197..1e29364507a 100644 --- a/library/Zend/Crypt/BlockCipher.php +++ b/library/Zend/Crypt/BlockCipher.php @@ -48,11 +48,11 @@ class BlockCipher protected $hash = 'sha256'; /** - * Salt (IV) + * Check if the salt has been set * - * @var string + * @var boolean */ - protected $salt; + protected $saltSetted = false; /** * The output is binary? @@ -62,18 +62,18 @@ class BlockCipher protected $binaryOutput = false; /** - * User's key + * Number of iterations for Pbkdf2 * * @var string */ - protected $key; + protected $keyIteration = 5000; /** - * Number of iterations for Pbkdf2 + * Key * * @var string */ - protected $keyIteration = 5000; + protected $key; /** * Constructor @@ -88,14 +88,15 @@ public function __construct(SymmetricInterface $cipher) /** * Factory. * - * @param string $adapter - * @param array $options + * @param string $adapter + * @param array $options * @return BlockCipher */ public static function factory($adapter, $options = array()) { $plugins = static::getSymmetricPluginManager(); $adapter = $plugins->get($adapter, (array) $options); + return new static($adapter); } @@ -116,7 +117,7 @@ public static function getSymmetricPluginManager() /** * Set the symmetric cipher plugin manager * - * @param string|SymmetricPluginManager $plugins + * @param string|SymmetricPluginManager $plugins * @throws Exception\InvalidArgumentException */ public static function setSymmetricPluginManager($plugins) @@ -165,12 +166,13 @@ public function getCipher() /** * Set the number of iterations for Pbkdf2 * - * @param integer $num + * @param integer $num * @return BlockCipher */ public function setKeyIteration($num) { - $this->keyIteration = (integer)$num; + $this->keyIteration = (integer) $num; + return $this; } @@ -187,16 +189,19 @@ public function getKeyIteration() /** * Set the salt (IV) * - * @param string $salt + * @param string $salt * @return BlockCipher * @throws Exception\InvalidArgumentException */ public function setSalt($salt) { - if (empty($salt)) { - throw new Exception\InvalidArgumentException("The salt (IV) cannot be empty"); + try { + $this->cipher->setSalt($salt); + } catch (Symmetric\Exception\InvalidArgumentException $e) { + throw new Exception\InvalidArgumentException("The salt is not valid: " . $e->getMessage()); } - $this->salt = $salt; + $this->saltSetted = true; + return $this; } @@ -207,18 +212,19 @@ public function setSalt($salt) */ public function getSalt() { - return $this->salt; + return $this->cipher->getSalt(); } /** * Enable/disable the binary output * - * @param bool $value + * @param bool $value * @return BlockCipher */ public function setBinaryOutput($value) { $this->binaryOutput = (bool) $value; + return $this; } @@ -235,7 +241,7 @@ public function getBinaryOutput() /** * Set the encryption/decryption key * - * @param string $key + * @param string $key * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -245,6 +251,7 @@ public function setKey($key) throw new Exception\InvalidArgumentException('The key cannot be empty'); } $this->key = $key; + return $this; } @@ -261,7 +268,7 @@ public function getKey() /** * Set algorithm of the symmetric cipher * - * @param string $algo + * @param string $algo * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -275,6 +282,7 @@ public function setCipherAlgorithm($algo) } catch (Symmetric\Exception\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException($e->getMessage()); } + return $this; } @@ -288,6 +296,7 @@ public function getCipherAlgorithm() if (!empty($this->cipher)) { return $this->cipher->getAlgorithm(); } + return false; } @@ -301,13 +310,14 @@ public function getCipherSupportedAlgorithms() if (!empty($this->cipher)) { return $this->cipher->getSupportedAlgorithms(); } + return array(); } /** * Set the hash algorithm for HMAC authentication * - * @param string $hash + * @param string $hash * @return BlockCipher * @throws Exception\InvalidArgumentException */ @@ -319,6 +329,7 @@ public function setHashAlgorithm($hash) ); } $this->hash = $hash; + return $this; } @@ -335,7 +346,7 @@ public function getHashAlgorithm() /** * Encrypt then authenticate using HMAC * - * @param string $data + * @param string $data * @return string * @throws Exception\InvalidArgumentException */ @@ -344,23 +355,21 @@ public function encrypt($data) if (empty($data)) { throw new Exception\InvalidArgumentException('The data to encrypt cannot be empty'); } - if (empty($this->key)) { - throw new Exception\InvalidArgumentException('No key specified for the encryption'); - } if (empty($this->cipher)) { throw new Exception\InvalidArgumentException('No symmetric cipher specified'); } + if (empty($this->key)) { + throw new Exception\InvalidArgumentException('No key specified for the encryption'); + } $keySize = $this->cipher->getKeySize(); - $salt = $this->getSalt(); - // generate a random salt (IV) if empty - if (empty($salt)) { - $salt = Rand::getBytes($this->cipher->getSaltSize(), true); + // generate a random salt (IV) if the salt has not been set + if (!$this->saltSetted) { + $this->cipher->setSalt(Rand::getBytes($this->cipher->getSaltSize(), true)); } - $this->cipher->setSalt($salt); // generate the encryption key and the HMAC key for the authentication $hash = Pbkdf2::calc(self::KEY_DERIV_HMAC, $this->getKey(), - substr($this->cipher->getSalt(), 0, $this->cipher->getSaltSize()), + $this->getSalt(), $this->keyIteration, $keySize * 2); // set the encryption key @@ -376,13 +385,14 @@ public function encrypt($data) if (!$this->binaryOutput) { $ciphertext = base64_encode($ciphertext); } + return $hmac . $ciphertext; } /** * Decrypt * - * @param string $data + * @param string $data * @return string|bool * @throws Exception\InvalidArgumentException */ @@ -424,6 +434,7 @@ public function decrypt($data) if (!Utils::compareStrings($hmacNew, $hmac)) { return false; } + return $this->cipher->decrypt($ciphertext); } } diff --git a/library/Zend/Crypt/Symmetric/Mcrypt.php b/library/Zend/Crypt/Symmetric/Mcrypt.php index 3eb27d23490..6e0239a7168 100644 --- a/library/Zend/Crypt/Symmetric/Mcrypt.php +++ b/library/Zend/Crypt/Symmetric/Mcrypt.php @@ -107,7 +107,7 @@ class Mcrypt implements SymmetricInterface /** * Constructor * - * @param array|Traversable $options + * @param array|Traversable $options * @throws Exception\RuntimeException * @throws Exception\InvalidArgumentException */ @@ -185,7 +185,7 @@ public static function getPaddingPluginManager() /** * Set the padding plugin manager * - * @param string|PaddingPluginManager $plugins + * @param string|PaddingPluginManager $plugins * @throws Exception\InvalidArgumentException * @return void */ @@ -224,7 +224,7 @@ public function getKeySize() /** * Set the encryption key * - * @param string $key + * @param string $key * @throws Exception\InvalidArgumentException * @return Mcrypt */ @@ -233,7 +233,13 @@ public function setKey($key) if (empty($key)) { throw new Exception\InvalidArgumentException('The key cannot be empty'); } + if (strlen($key) < $this->getKeySize()) { + throw new Exception\InvalidArgumentException( + 'The size of the key must be at least of ' . $this->getKeySize() . ' bytes' + ); + } $this->key = $key; + return $this; } @@ -244,13 +250,19 @@ public function setKey($key) */ public function getKey() { - return $this->key; + if (strlen($this->key) < $this->getKeySize()) { + throw new Exception\InvalidArgumentException( + 'The size of the key must be at least of ' . $this->getKeySize() . ' bytes' + ); + } + + return substr($this->key, 0, $this->getKeySize()); } /** * Set the encryption algorithm (cipher) * - * @param string $algo + * @param string $algo * @throws Exception\InvalidArgumentException * @return Mcrypt */ @@ -262,6 +274,7 @@ public function setAlgorithm($algo) ); } $this->algo = $algo; + return $this; } @@ -284,6 +297,7 @@ public function getAlgorithm() public function setPadding(Padding\PaddingInterface $padding) { $this->padding = $padding; + return $this; } @@ -300,7 +314,7 @@ public function getPadding() /** * Encrypt * - * @param string $data + * @param string $data * @throws Exception\InvalidArgumentException * @return string */ @@ -312,9 +326,6 @@ public function encrypt($data) if (null === $this->getKey()) { throw new Exception\InvalidArgumentException('No key specified for the encryption'); } - if (strlen($this->getKey()) < $this->getKeySize()) { - throw new Exception\InvalidArgumentException('The key is not long enough for the cipher'); - } if (null === $this->getSalt()) { throw new Exception\InvalidArgumentException('The salt (IV) cannot be empty'); } @@ -323,23 +334,23 @@ public function encrypt($data) } // padding $data = $this->padding->pad($data, $this->getBlockSize()); - // get the correct iv size - $iv = substr($this->iv, 0, $this->getSaltSize()); + $iv = $this->getSalt(); // encryption $result = mcrypt_encrypt( $this->supportedAlgos[$this->algo], - substr($this->key, 0, $this->getKeySize()), + $this->getKey(), $data, $this->supportedModes[$this->mode], $iv ); + return $iv . $result; } /** * Decrypt * - * @param string $data + * @param string $data * @throws Exception\InvalidArgumentException * @return string */ @@ -358,7 +369,7 @@ public function decrypt($data) $ciphertext = substr($data, $this->getSaltSize()); $result = mcrypt_decrypt( $this->supportedAlgos[$this->algo], - substr($this->key, 0, $this->getKeySize()), + $this->getKey(), $ciphertext, $this->supportedModes[$this->mode], $iv @@ -391,7 +402,7 @@ public function getSupportedAlgorithms() /** * Set the salt (IV) * - * @param string $salt + * @param string $salt * @throws Exception\InvalidArgumentException * @return Mcrypt */ @@ -404,25 +415,35 @@ public function setSalt($salt) throw new Exception\InvalidArgumentException( 'The size of the salt (IV) must be at least ' . $this->getSaltSize() . ' bytes' ); - } + } $this->iv = $salt; + return $this; } /** - * Get the salt (IV) + * Get the salt (IV) according to the size requested by the algorithm * * @return string */ public function getSalt() { - return $this->iv; + if (empty($this->iv)) { + return null; + } + if (strlen($this->iv) < $this->getSaltSize()) { + throw new Exception\RuntimeException( + 'The size of the salt (IV) must be at least ' . $this->getSaltSize() . ' bytes' + ); + } + + return substr($this->iv, 0, $this->getSaltSize()); } /** * Set the cipher mode * - * @param string $mode + * @param string $mode * @throws Exception\InvalidArgumentException * @return Mcrypt */ @@ -437,6 +458,7 @@ public function setMode($mode) } $this->mode = $mode; } + return $this; } diff --git a/library/Zend/Filter/Encrypt/BlockCipher.php b/library/Zend/Filter/Encrypt/BlockCipher.php index a247f042b3c..740480e3ac3 100644 --- a/library/Zend/Filter/Encrypt/BlockCipher.php +++ b/library/Zend/Filter/Encrypt/BlockCipher.php @@ -34,15 +34,13 @@ class BlockCipher implements EncryptionAlgorithmInterface * 'key_iteration' => the number of iterations for the PBKDF2 key generation * 'algorithm => cipher algorithm to use * 'hash' => algorithm to use for the authentication - * 'iv' => initialization vector + * 'vector => initialization vector * ) */ protected $encryption = array( - 'key' => 'ZendFramework', 'key_iteration' => 5000, 'algorithm' => 'aes', 'hash' => 'sha256', - 'vector' => null, ); /** @@ -182,6 +180,34 @@ public function setVector($vector) return $this; } + /** + * Set the encryption key + * + * @param string $key + * @return BlockCipher + * @throws Exception\InvalidArgumentException + */ + public function setKey($key) + { + try { + $this->blockCipher->setKey($key); + } catch (CryptException\InvalidArgumentException $e) { + throw new Exception\InvalidArgumentException($e->getMessage()); + } + $this->encryption['key'] = $key; + return $this; + } + + /** + * Get the encryption key + * + * @return string + */ + public function getKey() + { + return $this->encryption['key']; + } + /** * Returns the compression * diff --git a/tests/ZendTest/Crypt/Symmetric/McryptTest.php b/tests/ZendTest/Crypt/Symmetric/McryptTest.php index bdbe792ef93..78a39393cd7 100644 --- a/tests/ZendTest/Crypt/Symmetric/McryptTest.php +++ b/tests/ZendTest/Crypt/Symmetric/McryptTest.php @@ -56,8 +56,8 @@ public function testConstructByParams() $this->assertTrue($mcrypt instanceof Mcrypt); $this->assertEquals($mcrypt->getAlgorithm(), MCRYPT_BLOWFISH); $this->assertEquals($mcrypt->getMode(), MCRYPT_MODE_CFB); - $this->assertEquals($mcrypt->getKey(), $this->key); - $this->assertEquals($mcrypt->getSalt(), $this->salt); + $this->assertEquals($mcrypt->getKey(), substr($this->key, 0, $mcrypt->getKeySize())); + $this->assertEquals($mcrypt->getSalt(), substr($this->salt, 0, $mcrypt->getSaltSize())); $this->assertTrue($mcrypt->getPadding() instanceof PKCS7); } @@ -75,8 +75,8 @@ public function testConstructByConfig() $this->assertTrue($mcrypt instanceof Mcrypt); $this->assertEquals($mcrypt->getAlgorithm(), MCRYPT_BLOWFISH); $this->assertEquals($mcrypt->getMode(), MCRYPT_MODE_CFB); - $this->assertEquals($mcrypt->getKey(), $this->key); - $this->assertEquals($mcrypt->getSalt(), $this->salt); + $this->assertEquals($mcrypt->getKey(), substr($this->key, 0, $mcrypt->getKeySize())); + $this->assertEquals($mcrypt->getSalt(), substr($this->salt, 0, $mcrypt->getSaltSize())); $this->assertTrue($mcrypt->getPadding() instanceof PKCS7); } @@ -117,8 +117,7 @@ public function testSetEmptyKey() public function testSetShortKey() { - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'The key is not long enough for the cipher'); + $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException'); $result = $this->mcrypt->setKey('short'); $output = $this->mcrypt->encrypt('test'); } @@ -171,8 +170,7 @@ public function testEncryptDecrypt() public function testEncryptWithoutKey() { - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'No key specified for the encryption'); + $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException'); $ciphertext = $this->mcrypt->encrypt('test'); } @@ -200,8 +198,7 @@ public function testDecryptEmptyData() public function testDecryptWithoutKey() { - $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException', - 'No key specified for the decryption'); + $this->setExpectedException('Zend\Crypt\Symmetric\Exception\InvalidArgumentException'); $this->mcrypt->decrypt($this->plaintext); } } diff --git a/tests/ZendTest/Filter/DecryptTest.php b/tests/ZendTest/Filter/DecryptTest.php index 00be3d865f3..3cd557e0a7d 100644 --- a/tests/ZendTest/Filter/DecryptTest.php +++ b/tests/ZendTest/Filter/DecryptTest.php @@ -46,15 +46,14 @@ public function testBasicMcrypt() ); $enc = $filter->getEncryption(); - $filter->setVector('1234567890123456'); - $this->assertEquals('ZendFramework', $enc['key']); + $filter->setKey('1234567890123456'); foreach ($valuesExpected as $input => $output) { $this->assertNotEquals($output, $filter($input)); } } /** - * Ensures that the encryption works fine + * Ensures that the encryption works fine */ public function testDecryptBlockCipher() { @@ -66,7 +65,7 @@ public function testDecryptBlockCipher() $decrypted = $decrypt->filter('ec133eb7460682b0020b736ad6d2ef14c35de0f1e5976330ae1dd096ef3b4cb7MTIzNDU2Nzg5MDEyMzQ1NoZvxY1JkeL6TnQP3ug5F0k='); $this->assertEquals($decrypted, 'test'); } - + /** * Ensures that the filter follows expected behavior * diff --git a/tests/ZendTest/Filter/Encrypt/BlockCipherTest.php b/tests/ZendTest/Filter/Encrypt/BlockCipherTest.php index 7bfb5b6cc60..924889c4308 100644 --- a/tests/ZendTest/Filter/Encrypt/BlockCipherTest.php +++ b/tests/ZendTest/Filter/Encrypt/BlockCipherTest.php @@ -58,14 +58,18 @@ public function testBasicBlockCipher() */ public function testGetSetVector() { + $filter = new BlockCipherEncryption(array('key' => 'testkey')); - $filter->setVector('testvect'); - $this->assertEquals('testvect', $filter->getVector()); + $filter->setVector('1234567890123456'); + $this->assertEquals('1234567890123456', $filter->getVector()); + } + public function testWrongSizeVector() + { $this->setExpectedException('\Zend\Filter\Exception\InvalidArgumentException'); - $output = $filter->encrypt('test'); + $filter = new BlockCipherEncryption(array('key' => 'testkey')); + $filter->setVector('testvect'); } - /** * Ensures that the filter allows default encryption * @@ -74,13 +78,13 @@ public function testGetSetVector() public function testDefaultEncryption() { $filter = new BlockCipherEncryption(array('key' => 'testkey')); - $filter->setVector('testvect'); + $filter->setVector('1234567890123456'); $this->assertEquals( - array('key' => 'testkey', - 'algorithm' => 'aes', - 'vector' => 'testvect', + array('key' => 'testkey', + 'algorithm' => 'aes', + 'vector' => '1234567890123456', 'key_iteration' => 5000, - 'hash' => 'sha256'), + 'hash' => 'sha256'), $filter->getEncryption() ); } @@ -93,16 +97,16 @@ public function testDefaultEncryption() public function testGetSetEncryption() { $filter = new BlockCipherEncryption(array('key' => 'testkey')); - $filter->setVector('testvect'); + $filter->setVector('1234567890123456'); $filter->setEncryption( array('algorithm' => '3des') ); $this->assertEquals( - array('key' => 'testkey', - 'algorithm' => '3des', - 'vector' => 'testvect', + array('key' => 'testkey', + 'algorithm' => '3des', + 'vector' => '1234567890123456', 'key_iteration' => 5000, - 'hash' => 'sha256'), + 'hash' => 'sha256'), $filter->getEncryption() ); } diff --git a/tests/ZendTest/Filter/File/DecryptTest.php b/tests/ZendTest/Filter/File/DecryptTest.php index 19eeef156c1..728d28cd18e 100644 --- a/tests/ZendTest/Filter/File/DecryptTest.php +++ b/tests/ZendTest/Filter/File/DecryptTest.php @@ -61,7 +61,7 @@ public function testBasic() dirname(__DIR__).'/_files/newencryption.txt', $filter->getFilename()); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $filter->filter(dirname(__DIR__).'/_files/encryption.txt'); $filter = new FileDecrypt(); @@ -70,7 +70,7 @@ public function testBasic() 'Encryption', file_get_contents(dirname(__DIR__).'/_files/newencryption.txt')); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $this->assertEquals( dirname(__DIR__).'/_files/newencryption.txt', $filter->filter(dirname(__DIR__).'/_files/newencryption.txt')); @@ -84,7 +84,7 @@ public function testEncryptionWithDecryption() { $filter = new FileEncrypt(); $filter->setFilename(dirname(__DIR__).'/_files/newencryption.txt'); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $this->assertEquals(dirname(__DIR__).'/_files/newencryption.txt', $filter->filter(dirname(__DIR__).'/_files/encryption.txt')); @@ -99,7 +99,7 @@ public function testEncryptionWithDecryption() dirname(__DIR__).'/_files/newencryption2.txt', $filter->getFilename()); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $input = $filter->filter(dirname(__DIR__).'/_files/newencryption.txt'); $this->assertEquals(dirname(__DIR__).'/_files/newencryption2.txt', $input); diff --git a/tests/ZendTest/Filter/File/EncryptTest.php b/tests/ZendTest/Filter/File/EncryptTest.php index 6a6954905c9..32ce03e343a 100644 --- a/tests/ZendTest/Filter/File/EncryptTest.php +++ b/tests/ZendTest/Filter/File/EncryptTest.php @@ -53,7 +53,7 @@ public function testBasic() dirname(__DIR__).'/_files/newencryption.txt', $filter->getFilename()); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $this->assertEquals(dirname(__DIR__).'/_files/newencryption.txt', $filter->filter(dirname(__DIR__).'/_files/encryption.txt')); @@ -70,7 +70,7 @@ public function testEncryptionWithDecryption() { $filter = new FileEncrypt(); $filter->setFilename(dirname(__DIR__).'/_files/newencryption.txt'); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $this->assertEquals(dirname(__DIR__).'/_files/newencryption.txt', $filter->filter(dirname(__DIR__).'/_files/encryption.txt')); @@ -79,7 +79,7 @@ public function testEncryptionWithDecryption() file_get_contents(dirname(__DIR__).'/_files/newencryption.txt')); $filter = new FileDecrypt(); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $input = $filter->filter(dirname(__DIR__).'/_files/newencryption.txt'); $this->assertEquals(dirname(__DIR__).'/_files/newencryption.txt', $input); @@ -94,7 +94,7 @@ public function testEncryptionWithDecryption() public function testNonExistingFile() { $filter = new FileEncrypt(); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); $this->setExpectedException('\Zend\Filter\Exception\InvalidArgumentException', 'not found'); echo $filter->filter(dirname(__DIR__).'/_files/nofile.txt'); @@ -106,7 +106,7 @@ public function testNonExistingFile() public function testEncryptionInSameFile() { $filter = new FileEncrypt(); - $filter->setVector('1234567890123456'); + $filter->setKey('1234567890123456'); copy(dirname(__DIR__).'/_files/encryption.txt', dirname(__DIR__).'/_files/newencryption.txt'); $filter->filter(dirname(__DIR__).'/_files/newencryption.txt'); From 79d9977bf3c69adcb8a45f6749e4234cc6085a6f Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 25 Jan 2013 14:55:15 +0100 Subject: [PATCH 3/6] Moved the setSalt outside the loop in testEncryptDecrypt --- tests/ZendTest/Crypt/Symmetric/McryptTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ZendTest/Crypt/Symmetric/McryptTest.php b/tests/ZendTest/Crypt/Symmetric/McryptTest.php index 78a39393cd7..18a483914c4 100644 --- a/tests/ZendTest/Crypt/Symmetric/McryptTest.php +++ b/tests/ZendTest/Crypt/Symmetric/McryptTest.php @@ -154,11 +154,11 @@ public function testEncryptDecrypt() { $this->mcrypt->setKey($this->key); $this->mcrypt->setPadding(new PKCS7()); + $this->mcrypt->setSalt($this->salt); foreach ($this->mcrypt->getSupportedAlgorithms() as $algo) { foreach ($this->mcrypt->getSupportedModes() as $mode) { $this->mcrypt->setAlgorithm($algo); $this->mcrypt->setMode($mode); - $this->mcrypt->setSalt($this->salt); $encrypted = $this->mcrypt->encrypt($this->plaintext); $this->assertTrue(!empty($encrypted)); $decrypted = $this->mcrypt->decrypt($encrypted); From bc8dc1dd3a18d73957f701b2151da21c48e033c2 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 25 Jan 2013 15:05:06 +0100 Subject: [PATCH 4/6] Added the getOriginalSalt() in Mcrypt and BlockCipher --- library/Zend/Crypt/BlockCipher.php | 12 +++++++++++- library/Zend/Crypt/Symmetric/Mcrypt.php | 10 ++++++++++ tests/ZendTest/Crypt/BlockCipherTest.php | 8 +++++--- tests/ZendTest/Crypt/Symmetric/McryptTest.php | 7 ++++--- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/library/Zend/Crypt/BlockCipher.php b/library/Zend/Crypt/BlockCipher.php index 1e29364507a..cf20c5ff4c6 100644 --- a/library/Zend/Crypt/BlockCipher.php +++ b/library/Zend/Crypt/BlockCipher.php @@ -206,7 +206,7 @@ public function setSalt($salt) } /** - * Get the salt (IV) + * Get the salt (IV) according to the size requested by the algorithm * * @return string */ @@ -215,6 +215,16 @@ public function getSalt() return $this->cipher->getSalt(); } + /** + * Get the original salt value + * + * @return type + */ + public function getOriginalSalt() + { + return $this->cipher->getOriginalSalt(); + } + /** * Enable/disable the binary output * diff --git a/library/Zend/Crypt/Symmetric/Mcrypt.php b/library/Zend/Crypt/Symmetric/Mcrypt.php index 6e0239a7168..10ba32f8cf8 100644 --- a/library/Zend/Crypt/Symmetric/Mcrypt.php +++ b/library/Zend/Crypt/Symmetric/Mcrypt.php @@ -440,6 +440,16 @@ public function getSalt() return substr($this->iv, 0, $this->getSaltSize()); } + /** + * Get the original salt value + * + * @return string + */ + public function getOriginalSalt() + { + return $this->iv; + } + /** * Set the cipher mode * diff --git a/tests/ZendTest/Crypt/BlockCipherTest.php b/tests/ZendTest/Crypt/BlockCipherTest.php index f133745bfee..900283b2f46 100644 --- a/tests/ZendTest/Crypt/BlockCipherTest.php +++ b/tests/ZendTest/Crypt/BlockCipherTest.php @@ -73,12 +73,14 @@ public function testSetKey() public function testSetSalt() { - $salt = str_repeat('a', $this->blockCipher->getCipher()->getSaltSize()); + $salt = str_repeat('a', $this->blockCipher->getCipher()->getSaltSize() + 2); $result = $this->blockCipher->setSalt($salt); $this->assertEquals($result, $this->blockCipher); - $this->assertEquals($salt, $this->blockCipher->getSalt()); + $this->assertEquals(substr($salt, 0, $this->blockCipher->getCipher()->getSaltSize()), + $this->blockCipher->getSalt()); + $this->assertEquals($salt, $this->blockCipher->getOriginalSalt()); } - + public function testSetAlgorithm() { $result = $this->blockCipher->setCipherAlgorithm('blowfish'); diff --git a/tests/ZendTest/Crypt/Symmetric/McryptTest.php b/tests/ZendTest/Crypt/Symmetric/McryptTest.php index 18a483914c4..727bf9aa9fc 100644 --- a/tests/ZendTest/Crypt/Symmetric/McryptTest.php +++ b/tests/ZendTest/Crypt/Symmetric/McryptTest.php @@ -124,9 +124,10 @@ public function testSetShortKey() public function testSetSalt() { - $salt = substr($this->salt, 0, $this->mcrypt->getSaltSize()); - $this->mcrypt->setSalt($salt); - $this->assertEquals($salt, $this->mcrypt->getSalt()); + $this->mcrypt->setSalt($this->salt); + $this->assertEquals(substr($this->salt, 0, $this->mcrypt->getSaltSize()), + $this->mcrypt->getSalt()); + $this->assertEquals($this->salt, $this->mcrypt->getOriginalSalt()); } /** From 65938e80b3fe31c35c3218275d527c9fe0bc8ec9 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 25 Jan 2013 15:36:25 +0100 Subject: [PATCH 5/6] Fixed CS issue --- tests/ZendTest/Filter/EncryptTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ZendTest/Filter/EncryptTest.php b/tests/ZendTest/Filter/EncryptTest.php index 5ec4b65cec0..9c8846511d4 100644 --- a/tests/ZendTest/Filter/EncryptTest.php +++ b/tests/ZendTest/Filter/EncryptTest.php @@ -54,7 +54,7 @@ public function testBasicBlockCipher() } /** - * Ensures that the encryption works fine + * Ensures that the encryption works fine */ public function testEncryptBlockCipher() { @@ -66,7 +66,7 @@ public function testEncryptBlockCipher() $encrypted = $encrypt->filter('test'); $this->assertEquals($encrypted, 'ec133eb7460682b0020b736ad6d2ef14c35de0f1e5976330ae1dd096ef3b4cb7MTIzNDU2Nzg5MDEyMzQ1NoZvxY1JkeL6TnQP3ug5F0k='); } - + /** * Ensures that the filter follows expected behavior * From b5ebe8ba5f7da0add89cd2eaa5b0ed033dee884f Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 25 Jan 2013 17:18:58 +0100 Subject: [PATCH 6/6] Removed check in getKey of Zend\Cryp\Symmetric\Mcrypt --- library/Zend/Crypt/Symmetric/Mcrypt.php | 7 ++----- library/Zend/Filter/Encrypt/BlockCipher.php | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/library/Zend/Crypt/Symmetric/Mcrypt.php b/library/Zend/Crypt/Symmetric/Mcrypt.php index 10ba32f8cf8..0420dfd552d 100644 --- a/library/Zend/Crypt/Symmetric/Mcrypt.php +++ b/library/Zend/Crypt/Symmetric/Mcrypt.php @@ -250,12 +250,9 @@ public function setKey($key) */ public function getKey() { - if (strlen($this->key) < $this->getKeySize()) { - throw new Exception\InvalidArgumentException( - 'The size of the key must be at least of ' . $this->getKeySize() . ' bytes' - ); + if (empty($this->key)) { + return null; } - return substr($this->key, 0, $this->getKeySize()); } diff --git a/library/Zend/Filter/Encrypt/BlockCipher.php b/library/Zend/Filter/Encrypt/BlockCipher.php index 740480e3ac3..f035e50df8c 100644 --- a/library/Zend/Filter/Encrypt/BlockCipher.php +++ b/library/Zend/Filter/Encrypt/BlockCipher.php @@ -34,7 +34,7 @@ class BlockCipher implements EncryptionAlgorithmInterface * 'key_iteration' => the number of iterations for the PBKDF2 key generation * 'algorithm => cipher algorithm to use * 'hash' => algorithm to use for the authentication - * 'vector => initialization vector + * 'vector' => initialization vector * ) */ protected $encryption = array(