From 50ccc38a8c07b412aad0c26afb0775a0d9be18ee Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 4 Feb 2014 23:30:06 +0200 Subject: CI_Encryption: Fix more errors and add a 'portability' test case --- system/libraries/Encryption.php | 34 ++++++++--------- tests/codeigniter/libraries/Encryption_test.php | 51 ++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index 3c1347523..2d3f82dc8 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -148,7 +148,7 @@ class CI_Encryption { { if (isset($this->_drivers[$params['driver']])) { - if ($this->_driver[$params['driver']]) + if ($this->_drivers[$params['driver']]) { $this->_driver = $params['driver']; } @@ -264,7 +264,7 @@ class CI_Encryption { ? $this->_cipher : $this->_cipher.'-'.$this->_mode; - if ( ! in_array($handle, openssl_get_cipher_methods, TRUE)) + if ( ! in_array($handle, openssl_get_cipher_methods(), TRUE)) { $this->_handle = NULL; log_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.'); @@ -364,7 +364,7 @@ class CI_Encryption { mcrypt_generic_deinit($params['handle']); if ($params['handle'] !== $this->_handle) { - mcrypt_module_close($handle); + mcrypt_module_close($params['handle']); } return $data; @@ -452,7 +452,8 @@ class CI_Encryption { if ( ! isset($params['iv'])) { - if ($iv_size) + $iv_size = $this->{'_'.$this->_driver.'_get_iv_size'}($params['handle']); + if ($iv_size = $this->{'_'.$this->_driver.'_get_iv_size'}($params['handle'])) { $params['iv'] = substr($data, 0, $iv_size); $data = substr($data, $iv_size); @@ -500,7 +501,7 @@ class CI_Encryption { mcrypt_generic_deinit($params['handle']); if ($params['handle'] !== $this->_handle) { - mcrypt_module_close($handle); + mcrypt_module_close($params['handle']); } // Remove PKCS#7 padding @@ -607,7 +608,7 @@ class CI_Encryption { { if (empty($params)) { - return isset($this->_cipher, $this->_mode, $params->_key, $this->_handle) + return isset($this->_cipher, $this->_mode, $this->_key, $this->_handle) ? array( 'handle' => $this->_handle, 'cipher' => $this->_cipher, @@ -714,14 +715,16 @@ class CI_Encryption { { $dictionary = array( 'mcrypt' => array( - 'rijndael-128', - 'tripledes', - 'arcfour' + 'aes-128' => 'rijndael-128', + 'aes-192' => 'rijndael-128', + 'aes-256' => 'rijndael-128', + 'des3-ede3' => 'tripledes', + 'rc4-40' => 'arcfour' ), 'openssl' => array( - 'aes-128', - 'des-ede3', - 'rc4-40' + 'rijndael-128' => 'aes-128', + 'tripledes' => 'des-ede3', + 'arcfour' => 'rc4-40' ) ); @@ -746,12 +749,9 @@ class CI_Encryption { // All compatibility tests were done in CBC mode. } - $dialect = ($this->_driver === 'mcrypt') - ? 'openssl' - : 'mcrypt'; - if (($index = array_search($cipher, $dictionary[$dialect], TRUE)) !== FALSE) + if (isset($dictionary[$this->_driver][$cipher])) { - $cipher = $dictionary[$this->_driver][$index]; + $cipher = $dictionary[$this->_driver][$cipher]; } } diff --git a/tests/codeigniter/libraries/Encryption_test.php b/tests/codeigniter/libraries/Encryption_test.php index 94a952677..3d091e8d8 100644 --- a/tests/codeigniter/libraries/Encryption_test.php +++ b/tests/codeigniter/libraries/Encryption_test.php @@ -4,13 +4,62 @@ class Encryption_test extends CI_TestCase { public function set_up() { - $this->ci_set_config('encryption_key', "Encryptin'glike@boss!"); + $this->ci_set_config('encryption_key', "\xd0\xc9\x08\xc4\xde\x52\x12\x6e\xf8\xcc\xdb\x03\xea\xa0\x3a\x5c"); $this->encryption = new CI_Encryption(); $this->ci_instance_var('encryption', $this->encryption); } // -------------------------------------------------------------------- + public function test_portability() + { + if ( ! $this->encryption->drivers['mcrypt'] OR ! $this->encryption->drivers['openssl']) + { + $this->markTestAsSkipped('Both MCrypt and OpenSSL support are required for portability tests.'); + return; + } + + $message = 'This is a message encrypted via MCrypt and decrypted via OpenSSL, or vice-versa.'; + + // As it turns out, only ciphers that happened to be a US standard have a + // somewhat consistent implementation between MCrypt and OpenSSL, so + // we can only test AES, DES and TripleDES. + // + // Format is: , , + $portable = array( + array('rijndael-128', 'aes-128', 16), + array('rijndael-128', 'aes-192', 24), + array('rijndael-128', 'aes-256', 32), + array('des', 'des', 7), + array('tripledes', 'des-ede3', 7), + array('tripledes', 'des-ede3', 14), + array('tripledes', 'des-ede3', 21) + ); + $driver_index = array('mcrypt', 'openssl'); + + foreach ($portable as &$test) + { + // Add some randomness to the selected driver + $driver = mt_rand(0,1); + $params = array( + 'cipher' => $test[$driver], + 'mode' => 'cbc', + 'key' => openssl_random_pseudo_bytes($test[2]) + ); + + $this->encryption->initialize(array('driver' => $driver_index[$driver])); + $ciphertext = $this->encryption->encrypt($message, $params); + + $driver = (int) ! $driver; + $params['cipher'] = $test[$driver]; + + $this->encryption->initialize(array('driver' => $driver_index[$driver])); + $this->assertEquals($message, $this->encryption->decrypt($ciphertext, $params)); + } + } + + // -------------------------------------------------------------------- + public function test_hkdf() { // Test vectors are described in RFC5869, Appendix A(1-3). -- cgit v1.2.3-24-g4f1b