diff options
author | Andrey Andreev <narf@devilix.net> | 2014-02-05 12:45:31 +0100 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2014-02-05 12:45:31 +0100 |
commit | e7516b09402580c4fe0bf0ff537f367c1ba0efd2 (patch) | |
tree | 4324d21ba945340136b0e8c3d1ac230df7a087e4 /system/libraries/Encryption.php | |
parent | 86f46f4628f63ef63d28de78da0d8d73013d5a8c (diff) |
CI_Encryption: Work around MCrypt's dumb behavior in ECB mode
Diffstat (limited to 'system/libraries/Encryption.php')
-rw-r--r-- | system/libraries/Encryption.php | 114 |
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 |