summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-02-05 12:45:31 +0100
committerAndrey Andreev <narf@devilix.net>2014-02-05 12:45:31 +0100
commite7516b09402580c4fe0bf0ff537f367c1ba0efd2 (patch)
tree4324d21ba945340136b0e8c3d1ac230df7a087e4
parent86f46f4628f63ef63d28de78da0d8d73013d5a8c (diff)
CI_Encryption: Work around MCrypt's dumb behavior in ECB mode
-rw-r--r--system/libraries/Encryption.php114
1 files changed, 65 insertions, 49 deletions
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index 503fb64e3..2228ca3a6 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -292,12 +292,6 @@ class CI_Encryption {
{
return FALSE;
}
- elseif ( ! isset($params['iv']))
- {
- $params['iv'] = ($iv_size = $this->{'_'.$this->_driver.'_get_iv_size'}($params['handle']))
- ? $this->{'_'.$this->_driver.'_get_iv'}($iv_size)
- : NULL;
- }
if (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)
{
@@ -343,7 +337,15 @@ class CI_Encryption {
{
return FALSE;
}
- elseif (mcrypt_generic_init($params['handle'], $params['key'], $params['iv']) < 0)
+ elseif ( ! isset($params['iv']))
+ {
+ $params['iv'] = ($iv_size = mcrypt_enc_get_iv_size($params['handle']))
+ ? $this->_mcrypt_get_iv($iv_size)
+ : NULL;
+ }
+
+
+ if (mcrypt_generic_init($params['handle'], $params['key'], $params['iv']) < 0)
{
if ($params['handle'] !== $this->_handle)
{
@@ -359,7 +361,20 @@ class CI_Encryption {
$pad = $block_size - (strlen($data) % $block_size);
$data .= str_repeat(chr($pad), $pad);
- $data = $params['iv'].mcrypt_generic($params['handle'], $data);
+ // Work-around for yet another strange behavior in MCrypt.
+ //
+ // When encrypting in ECB mode, the IV is ignored. Yet
+ // mcrypt_enc_get_iv_size() returns a value larger than 0
+ // even if ECB is used AND mcrypt_generic_init() complains
+ // if you don't pass an IV with length equal to the said
+ // return value.
+ //
+ // This probably would've been fine (even though still wasteful),
+ // but OpenSSL isn't that dumb and we need to make the process
+ // portable, so ...
+ $data = (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
+ ? $params['iv'].mcrypt_generic($params['handle'], $data)
+ : mcrypt_generic($params['handle'], $data);
mcrypt_generic_deinit($params['handle']);
if ($params['handle'] !== $this->_handle)
@@ -385,6 +400,12 @@ class CI_Encryption {
{
return FALSE;
}
+ elseif ( ! isset($params['iv']))
+ {
+ $params['iv'] = ($iv_size = openssl_cipher_iv_length($params['handle']))
+ ? $this->_openssl_get_iv($iv_size)
+ : NULL;
+ }
$data = openssl_encrypt(
$data,
@@ -450,20 +471,7 @@ class CI_Encryption {
$data = base64_decode($data);
}
- if ( ! isset($params['iv']))
- {
- $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);
- }
- else
- {
- $params['iv'] = NULL;
- }
- }
- elseif (strncmp($params['iv'], $data, $iv_size = strlen($params['iv'])) === 0)
+ if (isset($params['iv']) && strncmp($params['iv'], $data, $iv_size = strlen($params['iv'])) === 0)
{
$data = substr($data, $iv_size);
}
@@ -486,7 +494,28 @@ class CI_Encryption {
{
return FALSE;
}
- elseif (mcrypt_generic_init($params['handle'], $params['key'], $params['iv']) < 0)
+ elseif ( ! isset($params['iv']))
+ {
+ if ($iv_size = mcrypt_enc_get_iv_size($params['handle']))
+ {
+ if (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
+ {
+ $params['iv'] = substr($data, 0, $iv_size);
+ $data = substr($data, $iv_size);
+ }
+ else
+ {
+ // MCrypt is dumb and this is ignored, only size matters
+ $params['iv'] = str_repeat("\x0", $iv_size);
+ }
+ }
+ else
+ {
+ $params['iv'] = NULL;
+ }
+ }
+
+ if (mcrypt_generic_init($params['handle'], $params['key'], $params['iv']) < 0)
{
if ($params['handle'] !== $this->_handle)
{
@@ -519,6 +548,19 @@ class CI_Encryption {
*/
protected function _openssl_decrypt($data, $params)
{
+ if ( ! isset($params['iv']))
+ {
+ if ($iv_size = openssl_cipher_iv_length($params['handle']))
+ {
+ $params['iv'] = substr($data, 0, $iv_size);
+ $data = substr($data, $iv_size);
+ }
+ else
+ {
+ $params['iv'] = NULL;
+ }
+ }
+
return empty($params['handle'])
? FALSE
: openssl_decrypt(
@@ -533,32 +575,6 @@ class CI_Encryption {
// --------------------------------------------------------------------
/**
- * Get IV size via MCrypt
- *
- * @param resource $handle MCrypt module resource
- * @return int
- */
- protected function _mcrypt_get_iv_size($handle)
- {
- return mcrypt_enc_get_iv_size($handle);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get IV size via OpenSSL
- *
- * @param string $handle OpenSSL cipher method
- * @return int
- */
- protected function _openssl_get_iv_size($handle)
- {
- return openssl_cipher_iv_length($handle);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Get IV via MCrypt
*
* @param int $size