summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--system/libraries/Encryption.php86
-rw-r--r--tests/codeigniter/libraries/Encryption_test.php59
2 files changed, 115 insertions, 30 deletions
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index d1aed7399..51e390c91 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -82,6 +82,35 @@ class CI_Encryption {
protected $_drivers = array();
/**
+ * List of available modes
+ *
+ * @var array
+ */
+ protected $_modes = array(
+ 'mcrypt' => array(
+ 'cbc' => 'cbc',
+ 'ecb' => 'ecb',
+ 'ofb' => 'nofb',
+ 'ofb8' => 'ofb',
+ 'cfb' => 'ncfb',
+ 'cfb8' => 'cfb',
+ 'ctr' => 'ctr',
+ 'stream' => 'stream'
+ ),
+ 'openssl' => array(
+ 'cbc' => 'cbc',
+ 'ecb' => 'ecb',
+ 'ofb' => 'ofb',
+ 'cfb' => 'cfb',
+ 'cfb8' => 'cfb8',
+ 'ctr' => 'ctr',
+ 'stream' => '',
+ 'gcm' => 'gcm',
+ 'xts' => 'xts'
+ )
+ );
+
+ /**
* List of supported HMAC algorightms
*
* name => digest size pairs
@@ -116,12 +145,6 @@ class CI_Encryption {
{
return show_error('Encryption: Unable to find an available encryption driver.');
}
- // Our configuration validates against the existence of MCRYPT_MODE_* constants,
- // but MCrypt supports CTR mode without actually having a constant for it, so ...
- elseif ($this->_drivers['mcrypt'] && ! defined('MCRYPT_MODE_CTR'))
- {
- define('MCRYPT_MODE_CTR', 'ctr');
- }
$this->initialize($params);
@@ -204,13 +227,14 @@ class CI_Encryption {
if ( ! empty($params['mode']))
{
- if ( ! defined('MCRYPT_MODE_'.$params['mode']))
+ $params['mode'] = strtolower($params['mode']);
+ if ( ! isset($this->_modes['mcrypt'][$params['mode']]))
{
log_message('error', 'Encryption: MCrypt mode '.strtotupper($params['mode']).' is not available.');
}
else
{
- $this->_mode = constant('MCRYPT_MODE_'.$params['mode']);
+ $this->_mode = $this->_modes['mcrypt'][$params['mode']];
}
}
@@ -254,13 +278,21 @@ class CI_Encryption {
if ( ! empty($params['mode']))
{
- $this->_mode = strtolower($params['mode']);
+ $params['mode'] = strtolower($params['mode']);
+ if ( ! isset($this->_modes['openssl'][$params['mode']]))
+ {
+ log_message('error', 'Encryption: OpenSSL mode '.strtotupper($params['mode']).' is not available.');
+ }
+ else
+ {
+ $this->_mode = $this->_modes['openssl'][$params['mode']];
+ }
}
if (isset($this->_cipher, $this->_mode))
{
- // OpenSSL methods aren't suffixed with '-stream' for this mode
- $handle = ($this->_mode === 'stream')
+ // This is mostly for the stream mode, which doesn't get suffixed in OpenSSL
+ $handle = empty($this->_mode)
? $this->_cipher
: $this->_cipher.'-'.$this->_mode;
@@ -356,10 +388,13 @@ class CI_Encryption {
}
// Use PKCS#7 padding in order to ensure compatibility with OpenSSL
- // and other implementations outside of PHP
- $block_size = mcrypt_enc_get_block_size($params['handle']);
- $pad = $block_size - (strlen($data) % $block_size);
- $data .= str_repeat(chr($pad), $pad);
+ // and other implementations outside of PHP.
+ if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
+ {
+ $block_size = mcrypt_enc_get_block_size($params['handle']);
+ $pad = $block_size - (strlen($data) % $block_size);
+ $data .= str_repeat(chr($pad), $pad);
+ }
// Work-around for yet another strange behavior in MCrypt.
//
@@ -526,6 +561,11 @@ class CI_Encryption {
}
$data = mdecrypt_generic($params['handle'], $data);
+ // Remove PKCS#7 padding, if necessary
+ if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
+ {
+ $data = substr($data, 0, -ord($data[strlen($data)-1]));
+ }
mcrypt_generic_deinit($params['handle']);
if ($params['handle'] !== $this->_handle)
@@ -533,8 +573,7 @@ class CI_Encryption {
mcrypt_module_close($params['handle']);
}
- // Remove PKCS#7 padding
- return substr($data, 0, -ord($data[strlen($data)-1]));
+ return $data;
}
// --------------------------------------------------------------------
@@ -664,6 +703,19 @@ class CI_Encryption {
);
}
+ if (isset($params['mode']))
+ {
+ $params['mode'] = strtolower($params['mode']);
+ if ( ! isset($this->_modes[$this->_driver][$params['mode']]))
+ {
+ return FALSE;
+ }
+ else
+ {
+ $params['mode'] = $this->_modes[$this->_driver][$params['mode']];
+ }
+ }
+
$params = array(
'handle' => NULL,
'cipher' => isset($params['cipher']) ? $params['cipher'] : $this->_cipher,
diff --git a/tests/codeigniter/libraries/Encryption_test.php b/tests/codeigniter/libraries/Encryption_test.php
index b13cb3140..ca1a4cd60 100644
--- a/tests/codeigniter/libraries/Encryption_test.php
+++ b/tests/codeigniter/libraries/Encryption_test.php
@@ -21,17 +21,51 @@ class Encryption_test extends CI_TestCase {
$message = 'This is a message encrypted via MCrypt and decrypted via OpenSSL, or vice-versa.';
- // Format is: <MCrypt cipher name>, <OpenSSL cipher name>, <key size>
+ // Format is: <Cipher name>, <Cipher mode>, <Key size>
$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),
- array('blowfish', 'bf', 16),
- array('blowfish', 'bf', 56)
+ array('aes-128', 'cbc', 16),
+ array('aes-128', 'cfb', 16),
+ array('aes-128', 'cfb8', 16),
+ array('aes-128', 'ofb', 16),
+ array('aes-128', 'ecb', 16),
+ array('aes-128', 'ctr', 16),
+ array('aes-192', 'cbc', 24),
+ array('aes-192', 'cfb', 24),
+ array('aes-192', 'cfb8', 24),
+ array('aes-192', 'ofb', 24),
+ array('aes-192', 'ecb', 24),
+ array('aes-192', 'ctr', 24),
+ array('aes-256', 'cbc', 32),
+ array('aes-256', 'cfb', 32),
+ array('aes-256', 'cfb8', 32),
+ array('aes-256', 'ofb', 32),
+ array('aes-256', 'ecb', 32),
+ array('aes-256', 'ctr', 32),
+ array('des', 'cbc', 7),
+ array('des', 'cfb', 7),
+ array('des', 'cfb8', 7),
+ array('des', 'ofb', 7),
+ array('des', 'ecb', 7),
+ array('tripledes', 'cbc', 7),
+ array('tripledes', 'cfb', 7),
+ array('tripledes', 'cfb8', 7),
+ array('tripledes', 'ofb', 7),
+ array('tripledes', 'cbc', 14),
+ array('tripledes', 'cfb', 14),
+ array('tripledes', 'cfb8', 14),
+ array('tripledes', 'ofb', 14),
+ array('tripledes', 'cbc', 21),
+ array('tripledes', 'cfb', 21),
+ array('tripledes', 'cfb8', 21),
+ array('tripledes', 'ofb', 21),
+ array('blowfish', 'cbc', 16),
+ array('blowfish', 'cfb', 16),
+ array('blowfish', 'ofb', 16),
+ array('blowfish', 'ecb', 16),
+ array('blowfish', 'cbc', 56),
+ array('blowfish', 'cfb', 56),
+ array('blowfish', 'ofb', 56),
+ array('blowfish', 'ecb', 56),
);
$driver_index = array('mcrypt', 'openssl');
@@ -40,8 +74,8 @@ class Encryption_test extends CI_TestCase {
// Add some randomness to the selected driver
$driver = mt_rand(0,1);
$params = array(
- 'cipher' => $test[$driver],
- 'mode' => 'cbc',
+ 'cipher' => $test[0],
+ 'mode' => $test[1],
'key' => openssl_random_pseudo_bytes($test[2])
);
@@ -49,7 +83,6 @@ class Encryption_test extends CI_TestCase {
$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));