File indexing completed on 2024-12-22 05:36:41
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Filter 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 /** 0023 * @see Zend_Filter_Encrypt_Interface 0024 */ 0025 // require_once 'Zend/Filter/Encrypt/Interface.php'; 0026 0027 /** @see Zend_Crypt_Math */ 0028 // require_once 'Zend/Crypt/Math.php'; 0029 0030 /** 0031 * Encryption adapter for mcrypt 0032 * 0033 * @category Zend 0034 * @package Zend_Filter 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Filter_Encrypt_Mcrypt implements Zend_Filter_Encrypt_Interface 0039 { 0040 /** 0041 * Definitions for encryption 0042 * array( 0043 * 'key' => encryption key string 0044 * 'algorithm' => algorithm to use 0045 * 'algorithm_directory' => directory where to find the algorithm 0046 * 'mode' => encryption mode to use 0047 * 'modedirectory' => directory where to find the mode 0048 * ) 0049 */ 0050 protected $_encryption = array( 0051 'key' => 'ZendFramework', 0052 'algorithm' => 'blowfish', 0053 'algorithm_directory' => '', 0054 'mode' => 'cbc', 0055 'mode_directory' => '', 0056 'vector' => null, 0057 'salt' => false 0058 ); 0059 0060 /** 0061 * Internal compression 0062 * 0063 * @var array 0064 */ 0065 protected $_compression; 0066 0067 protected static $_srandCalled = false; 0068 0069 /** 0070 * Class constructor 0071 * 0072 * @param string|array|Zend_Config $options Cryption Options 0073 */ 0074 public function __construct($options) 0075 { 0076 if (!extension_loaded('mcrypt')) { 0077 // require_once 'Zend/Filter/Exception.php'; 0078 throw new Zend_Filter_Exception('This filter needs the mcrypt extension'); 0079 } 0080 0081 if ($options instanceof Zend_Config) { 0082 $options = $options->toArray(); 0083 } elseif (is_string($options)) { 0084 $options = array('key' => $options); 0085 } elseif (!is_array($options)) { 0086 // require_once 'Zend/Filter/Exception.php'; 0087 throw new Zend_Filter_Exception('Invalid options argument provided to filter'); 0088 } 0089 0090 if (array_key_exists('compression', $options)) { 0091 $this->setCompression($options['compression']); 0092 unset($options['compress']); 0093 } 0094 0095 $this->setEncryption($options); 0096 } 0097 0098 /** 0099 * Returns the set encryption options 0100 * 0101 * @return array 0102 */ 0103 public function getEncryption() 0104 { 0105 return $this->_encryption; 0106 } 0107 0108 /** 0109 * Sets new encryption options 0110 * 0111 * @param string|array $options Encryption options 0112 * @return Zend_Filter_File_Encryption 0113 */ 0114 public function setEncryption($options) 0115 { 0116 if (is_string($options)) { 0117 $options = array('key' => $options); 0118 } 0119 0120 if (!is_array($options)) { 0121 // require_once 'Zend/Filter/Exception.php'; 0122 throw new Zend_Filter_Exception('Invalid options argument provided to filter'); 0123 } 0124 0125 $options = $options + $this->getEncryption(); 0126 $algorithms = mcrypt_list_algorithms($options['algorithm_directory']); 0127 if (!in_array($options['algorithm'], $algorithms)) { 0128 // require_once 'Zend/Filter/Exception.php'; 0129 throw new Zend_Filter_Exception("The algorithm '{$options['algorithm']}' is not supported"); 0130 } 0131 0132 $modes = mcrypt_list_modes($options['mode_directory']); 0133 if (!in_array($options['mode'], $modes)) { 0134 // require_once 'Zend/Filter/Exception.php'; 0135 throw new Zend_Filter_Exception("The mode '{$options['mode']}' is not supported"); 0136 } 0137 0138 if (!mcrypt_module_self_test($options['algorithm'], $options['algorithm_directory'])) { 0139 // require_once 'Zend/Filter/Exception.php'; 0140 throw new Zend_Filter_Exception('The given algorithm can not be used due an internal mcrypt problem'); 0141 } 0142 0143 if (!isset($options['vector'])) { 0144 $options['vector'] = null; 0145 } 0146 0147 $this->_encryption = $options; 0148 $this->setVector($options['vector']); 0149 0150 return $this; 0151 } 0152 0153 /** 0154 * Returns the set vector 0155 * 0156 * @return string 0157 */ 0158 public function getVector() 0159 { 0160 return $this->_encryption['vector']; 0161 } 0162 0163 /** 0164 * Sets the initialization vector 0165 * 0166 * @param string $vector (Optional) Vector to set 0167 * @return Zend_Filter_Encrypt_Mcrypt 0168 */ 0169 public function setVector($vector = null) 0170 { 0171 $cipher = $this->_openCipher(); 0172 $size = mcrypt_enc_get_iv_size($cipher); 0173 if (empty($vector)) { 0174 $this->_srand(); 0175 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) { 0176 $method = MCRYPT_RAND; 0177 } else { 0178 if (file_exists('/dev/urandom') || (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')) { 0179 $method = MCRYPT_DEV_URANDOM; 0180 } elseif (file_exists('/dev/random')) { 0181 $method = MCRYPT_DEV_RANDOM; 0182 } else { 0183 $method = MCRYPT_RAND; 0184 } 0185 } 0186 $vector = mcrypt_create_iv($size, $method); 0187 } else if (strlen($vector) != $size) { 0188 // require_once 'Zend/Filter/Exception.php'; 0189 throw new Zend_Filter_Exception('The given vector has a wrong size for the set algorithm'); 0190 } 0191 0192 $this->_encryption['vector'] = $vector; 0193 $this->_closeCipher($cipher); 0194 0195 return $this; 0196 } 0197 0198 /** 0199 * Returns the compression 0200 * 0201 * @return array 0202 */ 0203 public function getCompression() 0204 { 0205 return $this->_compression; 0206 } 0207 0208 /** 0209 * Sets a internal compression for values to encrypt 0210 * 0211 * @param string|array $compression 0212 * @return Zend_Filter_Encrypt_Mcrypt 0213 */ 0214 public function setCompression($compression) 0215 { 0216 if (is_string($this->_compression)) { 0217 $compression = array('adapter' => $compression); 0218 } 0219 0220 $this->_compression = $compression; 0221 return $this; 0222 } 0223 0224 /** 0225 * Defined by Zend_Filter_Interface 0226 * 0227 * Encrypts $value with the defined settings 0228 * 0229 * @param string $value The content to encrypt 0230 * @return string The encrypted content 0231 */ 0232 public function encrypt($value) 0233 { 0234 // compress prior to encryption 0235 if (!empty($this->_compression)) { 0236 // require_once 'Zend/Filter/Compress.php'; 0237 $compress = new Zend_Filter_Compress($this->_compression); 0238 $value = $compress->filter($value); 0239 } 0240 0241 $cipher = $this->_openCipher(); 0242 $this->_initCipher($cipher); 0243 $encrypted = mcrypt_generic($cipher, $value); 0244 mcrypt_generic_deinit($cipher); 0245 $this->_closeCipher($cipher); 0246 0247 return $encrypted; 0248 } 0249 0250 /** 0251 * Defined by Zend_Filter_Interface 0252 * 0253 * Decrypts $value with the defined settings 0254 * 0255 * @param string $value Content to decrypt 0256 * @return string The decrypted content 0257 */ 0258 public function decrypt($value) 0259 { 0260 $cipher = $this->_openCipher(); 0261 $this->_initCipher($cipher); 0262 $decrypted = mdecrypt_generic($cipher, $value); 0263 mcrypt_generic_deinit($cipher); 0264 $this->_closeCipher($cipher); 0265 0266 // decompress after decryption 0267 if (!empty($this->_compression)) { 0268 // require_once 'Zend/Filter/Decompress.php'; 0269 $decompress = new Zend_Filter_Decompress($this->_compression); 0270 $decrypted = $decompress->filter($decrypted); 0271 } 0272 0273 return $decrypted; 0274 } 0275 0276 /** 0277 * Returns the adapter name 0278 * 0279 * @return string 0280 */ 0281 public function toString() 0282 { 0283 return 'Mcrypt'; 0284 } 0285 0286 /** 0287 * Open a cipher 0288 * 0289 * @throws Zend_Filter_Exception When the cipher can not be opened 0290 * @return resource Returns the opened cipher 0291 */ 0292 protected function _openCipher() 0293 { 0294 $cipher = mcrypt_module_open( 0295 $this->_encryption['algorithm'], 0296 $this->_encryption['algorithm_directory'], 0297 $this->_encryption['mode'], 0298 $this->_encryption['mode_directory']); 0299 0300 if ($cipher === false) { 0301 // require_once 'Zend/Filter/Exception.php'; 0302 throw new Zend_Filter_Exception('Mcrypt can not be opened with your settings'); 0303 } 0304 0305 return $cipher; 0306 } 0307 0308 /** 0309 * Close a cipher 0310 * 0311 * @param resource $cipher Cipher to close 0312 * @return Zend_Filter_Encrypt_Mcrypt 0313 */ 0314 protected function _closeCipher($cipher) 0315 { 0316 mcrypt_module_close($cipher); 0317 0318 return $this; 0319 } 0320 0321 /** 0322 * Initialises the cipher with the set key 0323 * 0324 * @param resource $cipher 0325 * @throws 0326 * @return resource 0327 */ 0328 protected function _initCipher($cipher) 0329 { 0330 $key = $this->_encryption['key']; 0331 0332 $keysizes = mcrypt_enc_get_supported_key_sizes($cipher); 0333 if (empty($keysizes) || ($this->_encryption['salt'] == true)) { 0334 $this->_srand(); 0335 $keysize = mcrypt_enc_get_key_size($cipher); 0336 $key = substr(md5($key), 0, $keysize); 0337 } else if (!in_array(strlen($key), $keysizes)) { 0338 // require_once 'Zend/Filter/Exception.php'; 0339 throw new Zend_Filter_Exception('The given key has a wrong size for the set algorithm'); 0340 } 0341 0342 $result = mcrypt_generic_init($cipher, $key, $this->_encryption['vector']); 0343 if ($result < 0) { 0344 // require_once 'Zend/Filter/Exception.php'; 0345 throw new Zend_Filter_Exception('Mcrypt could not be initialize with the given setting'); 0346 } 0347 0348 return $this; 0349 } 0350 0351 /** 0352 * _srand() interception 0353 * 0354 * @see ZF-8742 0355 */ 0356 protected function _srand() 0357 { 0358 if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 0359 return; 0360 } 0361 if (!self::$_srandCalled) { 0362 srand(Zend_Crypt_Math::randInteger(0, PHP_INT_MAX)); 0363 self::$_srandCalled = true; 0364 } 0365 } 0366 }