944 行
		
	
	
	
		
			23 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			944 行
		
	
	
	
		
			23 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * CodeIgniter
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * An open source application development framework for PHP
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This content is released under the MIT License (MIT)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Permission is hereby granted, free of charge, to any person obtaining a copy
							 | 
						||
| 
								 | 
							
								 * of this software and associated documentation files (the "Software"), to deal
							 | 
						||
| 
								 | 
							
								 * in the Software without restriction, including without limitation the rights
							 | 
						||
| 
								 | 
							
								 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
							 | 
						||
| 
								 | 
							
								 * copies of the Software, and to permit persons to whom the Software is
							 | 
						||
| 
								 | 
							
								 * furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								 * all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
							 | 
						||
| 
								 | 
							
								 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
							 | 
						||
| 
								 | 
							
								 * THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @package	CodeIgniter
							 | 
						||
| 
								 | 
							
								 * @author	EllisLab Dev Team
							 | 
						||
| 
								 | 
							
								 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
							 | 
						||
| 
								 | 
							
								 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
							 | 
						||
| 
								 | 
							
								 * @license	http://opensource.org/licenses/MIT	MIT License
							 | 
						||
| 
								 | 
							
								 * @link	https://codeigniter.com
							 | 
						||
| 
								 | 
							
								 * @since	Version 3.0.0
							 | 
						||
| 
								 | 
							
								 * @filesource
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								defined('BASEPATH') OR exit('No direct script access allowed');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * CodeIgniter Encryption Class
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Provides two-way keyed encryption via PHP's MCrypt and/or OpenSSL extensions.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @package		CodeIgniter
							 | 
						||
| 
								 | 
							
								 * @subpackage	Libraries
							 | 
						||
| 
								 | 
							
								 * @category	Libraries
							 | 
						||
| 
								 | 
							
								 * @author		Andrey Andreev
							 | 
						||
| 
								 | 
							
								 * @link		https://codeigniter.com/user_guide/libraries/encryption.html
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class CI_Encryption {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Encryption cipher
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_cipher = 'aes-128';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Cipher mode
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_mode = 'cbc';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Cipher handle
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	mixed
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_handle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Encryption key
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * PHP extension to be used
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_driver;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * List of usable drivers (PHP extensions)
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	array
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									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' => '',
							 | 
						||
| 
								 | 
							
											'xts' => 'xts'
							 | 
						||
| 
								 | 
							
										)
							 | 
						||
| 
								 | 
							
									);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * List of supported HMAC algorithms
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * name => digest size pairs
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	array
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected $_digests = array(
							 | 
						||
| 
								 | 
							
										'sha224' => 28,
							 | 
						||
| 
								 | 
							
										'sha256' => 32,
							 | 
						||
| 
								 | 
							
										'sha384' => 48,
							 | 
						||
| 
								 | 
							
										'sha512' => 64
							 | 
						||
| 
								 | 
							
									);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * mbstring.func_overload flag
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @var	bool
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static $func_overload;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Class constructor
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Configuration parameters
							 | 
						||
| 
								 | 
							
									 * @return	void
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function __construct(array $params = array())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										$this->_drivers = array(
							 | 
						||
| 
								 | 
							
											'mcrypt'  => defined('MCRYPT_DEV_URANDOM'),
							 | 
						||
| 
								 | 
							
											'openssl' => extension_loaded('openssl')
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ! $this->_drivers['mcrypt'] && ! $this->_drivers['openssl'])
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											show_error('Encryption: Unable to find an available encryption driver.');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
							 | 
						||
| 
								 | 
							
										$this->initialize($params);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$this->_key = $key;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										log_message('info', 'Encryption Class Initialized');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Initialize
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Configuration parameters
							 | 
						||
| 
								 | 
							
									 * @return	CI_Encryption
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function initialize(array $params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! empty($params['driver']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (isset($this->_drivers[$params['driver']]))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ($this->_drivers[$params['driver']])
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													$this->_driver = $params['driver'];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													log_message('error', "Encryption: Driver '".$params['driver']."' is not available.");
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', "Encryption: Unknown driver '".$params['driver']."' cannot be configured.");
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (empty($this->_driver))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$this->_driver = ($this->_drivers['openssl'] === TRUE)
							 | 
						||
| 
								 | 
							
												? 'openssl'
							 | 
						||
| 
								 | 
							
												: 'mcrypt';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											log_message('debug', "Encryption: Auto-configured driver '".$this->_driver."'.");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										empty($params['cipher']) && $params['cipher'] = $this->_cipher;
							 | 
						||
| 
								 | 
							
										empty($params['key']) OR $this->_key = $params['key'];
							 | 
						||
| 
								 | 
							
										$this->{'_'.$this->_driver.'_initialize'}($params);
							 | 
						||
| 
								 | 
							
										return $this;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Initialize MCrypt
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Configuration parameters
							 | 
						||
| 
								 | 
							
									 * @return	void
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _mcrypt_initialize($params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! empty($params['cipher']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$params['cipher'] = strtolower($params['cipher']);
							 | 
						||
| 
								 | 
							
											$this->_cipher_alias($params['cipher']);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( ! in_array($params['cipher'], mcrypt_list_algorithms(), TRUE))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', 'Encryption: MCrypt cipher '.strtoupper($params['cipher']).' is not available.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$this->_cipher = $params['cipher'];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ! empty($params['mode']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$params['mode'] = strtolower($params['mode']);
							 | 
						||
| 
								 | 
							
											if ( ! isset($this->_modes['mcrypt'][$params['mode']]))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', 'Encryption: MCrypt mode '.strtoupper($params['mode']).' is not available.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$this->_mode = $this->_modes['mcrypt'][$params['mode']];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($this->_cipher, $this->_mode))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (is_resource($this->_handle)
							 | 
						||
| 
								 | 
							
												&& (strtolower(mcrypt_enc_get_algorithms_name($this->_handle)) !== $this->_cipher
							 | 
						||
| 
								 | 
							
													OR strtolower(mcrypt_enc_get_modes_name($this->_handle)) !== $this->_mode)
							 | 
						||
| 
								 | 
							
											)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												mcrypt_module_close($this->_handle);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ($this->_handle = mcrypt_module_open($this->_cipher, '', $this->_mode, ''))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('info', 'Encryption: MCrypt cipher '.strtoupper($this->_cipher).' initialized in '.strtoupper($this->_mode).' mode.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', 'Encryption: Unable to initialize MCrypt with cipher '.strtoupper($this->_cipher).' in '.strtoupper($this->_mode).' mode.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Initialize OpenSSL
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Configuration parameters
							 | 
						||
| 
								 | 
							
									 * @return	void
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _openssl_initialize($params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! empty($params['cipher']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$params['cipher'] = strtolower($params['cipher']);
							 | 
						||
| 
								 | 
							
											$this->_cipher_alias($params['cipher']);
							 | 
						||
| 
								 | 
							
											$this->_cipher = $params['cipher'];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ! empty($params['mode']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$params['mode'] = strtolower($params['mode']);
							 | 
						||
| 
								 | 
							
											if ( ! isset($this->_modes['openssl'][$params['mode']]))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', 'Encryption: OpenSSL mode '.strtoupper($params['mode']).' is not available.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$this->_mode = $this->_modes['openssl'][$params['mode']];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($this->_cipher, $this->_mode))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											// This is mostly for the stream mode, which doesn't get suffixed in OpenSSL
							 | 
						||
| 
								 | 
							
											$handle = empty($this->_mode)
							 | 
						||
| 
								 | 
							
												? $this->_cipher
							 | 
						||
| 
								 | 
							
												: $this->_cipher.'-'.$this->_mode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( ! in_array($handle, openssl_get_cipher_methods(), TRUE))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$this->_handle = NULL;
							 | 
						||
| 
								 | 
							
												log_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$this->_handle = $handle;
							 | 
						||
| 
								 | 
							
												log_message('info', 'Encryption: OpenSSL initialized with method '.strtoupper($handle).'.');
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Create a random key
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	int	$length	Output length
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function create_key($length)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (function_exists('random_bytes'))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											try
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												return random_bytes((int) $length);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											catch (Exception $e)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												log_message('error', $e->getMessage());
							 | 
						||
| 
								 | 
							
												return FALSE;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										elseif (defined('MCRYPT_DEV_URANDOM'))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$is_secure = NULL;
							 | 
						||
| 
								 | 
							
										$key = openssl_random_pseudo_bytes($length, $is_secure);
							 | 
						||
| 
								 | 
							
										return ($is_secure === TRUE)
							 | 
						||
| 
								 | 
							
											? $key
							 | 
						||
| 
								 | 
							
											: FALSE;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Encrypt
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Input data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function encrypt($data, array $params = NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (($params = $this->_get_params($params)) === FALSE)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$params['base64'] && $data = base64_encode($data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($params['hmac_digest']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
							 | 
						||
| 
								 | 
							
											return hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']).$data;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $data;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Encrypt via MCrypt
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Input data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _mcrypt_encrypt($data, $params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! is_resource($params['handle']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// The greater-than-1 comparison is mostly a work-around for a bug,
							 | 
						||
| 
								 | 
							
										// where 1 is returned for ARCFour instead of 0.
							 | 
						||
| 
								 | 
							
										$iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)
							 | 
						||
| 
								 | 
							
											? $this->create_key($iv_size)
							 | 
						||
| 
								 | 
							
											: NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ($params['handle'] !== $this->_handle)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												mcrypt_module_close($params['handle']);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Use PKCS#7 padding in order to ensure compatibility with OpenSSL
							 | 
						||
| 
								 | 
							
										// 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 - (self::strlen($data) % $block_size);
							 | 
						||
| 
								 | 
							
											$data .= str_repeat(chr($pad), $pad);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// 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')
							 | 
						||
| 
								 | 
							
											? $iv.mcrypt_generic($params['handle'], $data)
							 | 
						||
| 
								 | 
							
											: mcrypt_generic($params['handle'], $data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										mcrypt_generic_deinit($params['handle']);
							 | 
						||
| 
								 | 
							
										if ($params['handle'] !== $this->_handle)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											mcrypt_module_close($params['handle']);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $data;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Encrypt via OpenSSL
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Input data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _openssl_encrypt($data, $params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (empty($params['handle']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$iv = ($iv_size = openssl_cipher_iv_length($params['handle']))
							 | 
						||
| 
								 | 
							
											? $this->create_key($iv_size)
							 | 
						||
| 
								 | 
							
											: NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$data = openssl_encrypt(
							 | 
						||
| 
								 | 
							
											$data,
							 | 
						||
| 
								 | 
							
											$params['handle'],
							 | 
						||
| 
								 | 
							
											$params['key'],
							 | 
						||
| 
								 | 
							
											1, // DO NOT TOUCH!
							 | 
						||
| 
								 | 
							
											$iv
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($data === FALSE)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $iv.$data;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Decrypt
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Encrypted data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function decrypt($data, array $params = NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (($params = $this->_get_params($params)) === FALSE)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($params['hmac_digest']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											// This might look illogical, but it is done during encryption as well ...
							 | 
						||
| 
								 | 
							
											// The 'base64' value is effectively an inverted "raw data" parameter
							 | 
						||
| 
								 | 
							
											$digest_size = ($params['base64'])
							 | 
						||
| 
								 | 
							
												? $this->_digests[$params['hmac_digest']] * 2
							 | 
						||
| 
								 | 
							
												: $this->_digests[$params['hmac_digest']];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (self::strlen($data) <= $digest_size)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												return FALSE;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											$hmac_input = self::substr($data, 0, $digest_size);
							 | 
						||
| 
								 | 
							
											$data = self::substr($data, $digest_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
							 | 
						||
| 
								 | 
							
											$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Time-attack-safe comparison
							 | 
						||
| 
								 | 
							
											$diff = 0;
							 | 
						||
| 
								 | 
							
											for ($i = 0; $i < $digest_size; $i++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ($diff !== 0)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												return FALSE;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ($params['base64'])
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$data = base64_decode($data);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $this->{'_'.$this->_driver.'_decrypt'}($data, $params);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Decrypt via MCrypt
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Encrypted data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _mcrypt_decrypt($data, $params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! is_resource($params['handle']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// The greater-than-1 comparison is mostly a work-around for a bug,
							 | 
						||
| 
								 | 
							
										// where 1 is returned for ARCFour instead of 0.
							 | 
						||
| 
								 | 
							
										if (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$iv = self::substr($data, 0, $iv_size);
							 | 
						||
| 
								 | 
							
												$data = self::substr($data, $iv_size);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// MCrypt is dumb and this is ignored, only size matters
							 | 
						||
| 
								 | 
							
												$iv = str_repeat("\x0", $iv_size);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$iv = NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ($params['handle'] !== $this->_handle)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												mcrypt_module_close($params['handle']);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$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 = self::substr($data, 0, -ord($data[self::strlen($data)-1]));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										mcrypt_generic_deinit($params['handle']);
							 | 
						||
| 
								 | 
							
										if ($params['handle'] !== $this->_handle)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											mcrypt_module_close($params['handle']);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $data;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Decrypt via OpenSSL
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$data	Encrypted data
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _openssl_decrypt($data, $params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ($iv_size = openssl_cipher_iv_length($params['handle']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$iv = self::substr($data, 0, $iv_size);
							 | 
						||
| 
								 | 
							
											$data = self::substr($data, $iv_size);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$iv = NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return empty($params['handle'])
							 | 
						||
| 
								 | 
							
											? FALSE
							 | 
						||
| 
								 | 
							
											: openssl_decrypt(
							 | 
						||
| 
								 | 
							
												$data,
							 | 
						||
| 
								 | 
							
												$params['handle'],
							 | 
						||
| 
								 | 
							
												$params['key'],
							 | 
						||
| 
								 | 
							
												1, // DO NOT TOUCH!
							 | 
						||
| 
								 | 
							
												$iv
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get params
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	array	$params	Input parameters
							 | 
						||
| 
								 | 
							
									 * @return	array
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _get_params($params)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (empty($params))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return isset($this->_cipher, $this->_mode, $this->_key, $this->_handle)
							 | 
						||
| 
								 | 
							
												? array(
							 | 
						||
| 
								 | 
							
													'handle' => $this->_handle,
							 | 
						||
| 
								 | 
							
													'cipher' => $this->_cipher,
							 | 
						||
| 
								 | 
							
													'mode' => $this->_mode,
							 | 
						||
| 
								 | 
							
													'key' => NULL,
							 | 
						||
| 
								 | 
							
													'base64' => TRUE,
							 | 
						||
| 
								 | 
							
													'hmac_digest' => 'sha512',
							 | 
						||
| 
								 | 
							
													'hmac_key' => NULL
							 | 
						||
| 
								 | 
							
												)
							 | 
						||
| 
								 | 
							
												: FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										elseif ( ! isset($params['cipher'], $params['mode'], $params['key']))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										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']];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($params['hmac']) && $params['hmac'] === FALSE)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$params['hmac_digest'] = $params['hmac_key'] = NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( ! isset($params['hmac_key']))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												return FALSE;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											elseif (isset($params['hmac_digest']))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$params['hmac_digest'] = strtolower($params['hmac_digest']);
							 | 
						||
| 
								 | 
							
												if ( ! isset($this->_digests[$params['hmac_digest']]))
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													return FALSE;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												$params['hmac_digest'] = 'sha512';
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$params = array(
							 | 
						||
| 
								 | 
							
											'handle' => NULL,
							 | 
						||
| 
								 | 
							
											'cipher' => $params['cipher'],
							 | 
						||
| 
								 | 
							
											'mode' => $params['mode'],
							 | 
						||
| 
								 | 
							
											'key' => $params['key'],
							 | 
						||
| 
								 | 
							
											'base64' => isset($params['raw_data']) ? ! $params['raw_data'] : FALSE,
							 | 
						||
| 
								 | 
							
											'hmac_digest' => $params['hmac_digest'],
							 | 
						||
| 
								 | 
							
											'hmac_key' => $params['hmac_key']
							 | 
						||
| 
								 | 
							
										);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$this->_cipher_alias($params['cipher']);
							 | 
						||
| 
								 | 
							
										$params['handle'] = ($params['cipher'] !== $this->_cipher OR $params['mode'] !== $this->_mode)
							 | 
						||
| 
								 | 
							
											? $this->{'_'.$this->_driver.'_get_handle'}($params['cipher'], $params['mode'])
							 | 
						||
| 
								 | 
							
											: $this->_handle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return $params;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get MCrypt handle
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$cipher	Cipher name
							 | 
						||
| 
								 | 
							
									 * @param	string	$mode	Encryption mode
							 | 
						||
| 
								 | 
							
									 * @return	resource
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _mcrypt_get_handle($cipher, $mode)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return mcrypt_module_open($cipher, '', $mode, '');
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Get OpenSSL handle
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$cipher	Cipher name
							 | 
						||
| 
								 | 
							
									 * @param	string	$mode	Encryption mode
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _openssl_get_handle($cipher, $mode)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// OpenSSL methods aren't suffixed with '-stream' for this mode
							 | 
						||
| 
								 | 
							
										return ($mode === 'stream')
							 | 
						||
| 
								 | 
							
											? $cipher
							 | 
						||
| 
								 | 
							
											: $cipher.'-'.$mode;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Cipher alias
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * Tries to translate cipher names between MCrypt and OpenSSL's "dialects".
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$cipher	Cipher name
							 | 
						||
| 
								 | 
							
									 * @return	void
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected function _cipher_alias(&$cipher)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										static $dictionary;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (empty($dictionary))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$dictionary = array(
							 | 
						||
| 
								 | 
							
												'mcrypt' => array(
							 | 
						||
| 
								 | 
							
													'aes-128' => 'rijndael-128',
							 | 
						||
| 
								 | 
							
													'aes-192' => 'rijndael-128',
							 | 
						||
| 
								 | 
							
													'aes-256' => 'rijndael-128',
							 | 
						||
| 
								 | 
							
													'des3-ede3' => 'tripledes',
							 | 
						||
| 
								 | 
							
													'bf' => 'blowfish',
							 | 
						||
| 
								 | 
							
													'cast5' => 'cast-128',
							 | 
						||
| 
								 | 
							
													'rc4' => 'arcfour',
							 | 
						||
| 
								 | 
							
													'rc4-40' => 'arcfour'
							 | 
						||
| 
								 | 
							
												),
							 | 
						||
| 
								 | 
							
												'openssl' => array(
							 | 
						||
| 
								 | 
							
													'rijndael-128' => 'aes-128',
							 | 
						||
| 
								 | 
							
													'tripledes' => 'des-ede3',
							 | 
						||
| 
								 | 
							
													'blowfish' => 'bf',
							 | 
						||
| 
								 | 
							
													'cast-128' => 'cast5',
							 | 
						||
| 
								 | 
							
													'arcfour' => 'rc4-40',
							 | 
						||
| 
								 | 
							
													'rc4' => 'rc4-40'
							 | 
						||
| 
								 | 
							
												)
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Notes:
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - Rijndael-128 is, at the same time all three of AES-128,
							 | 
						||
| 
								 | 
							
											//   AES-192 and AES-256. The only difference between them is
							 | 
						||
| 
								 | 
							
											//   the key size. Rijndael-192, Rijndael-256 on the other hand
							 | 
						||
| 
								 | 
							
											//   also have different block sizes and are NOT AES-compatible.
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - Blowfish is said to be supporting key sizes between
							 | 
						||
| 
								 | 
							
											//   4 and 56 bytes, but it appears that between MCrypt and
							 | 
						||
| 
								 | 
							
											//   OpenSSL, only those of 16 and more bytes are compatible.
							 | 
						||
| 
								 | 
							
											//   Also, don't know what MCrypt's 'blowfish-compat' is.
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - CAST-128/CAST5 produces a longer cipher when encrypted via
							 | 
						||
| 
								 | 
							
											//   OpenSSL, but (strangely enough) can be decrypted by either
							 | 
						||
| 
								 | 
							
											//   extension anyway.
							 | 
						||
| 
								 | 
							
											//   Also, it appears that OpenSSL uses 16 rounds regardless of
							 | 
						||
| 
								 | 
							
											//   the key size, while RFC2144 says that for key sizes lower
							 | 
						||
| 
								 | 
							
											//   than 11 bytes, only 12 rounds should be used. This makes
							 | 
						||
| 
								 | 
							
											//   it portable only with keys of between 11 and 16 bytes.
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - RC4 (ARCFour) has a strange implementation under OpenSSL.
							 | 
						||
| 
								 | 
							
											//   Its 'rc4-40' cipher method seems to work flawlessly, yet
							 | 
						||
| 
								 | 
							
											//   there's another one, 'rc4' that only works with a 16-byte key.
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - DES is compatible, but doesn't need an alias.
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// Other seemingly matching ciphers between MCrypt, OpenSSL:
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// - RC2 is NOT compatible and only an obscure forum post
							 | 
						||
| 
								 | 
							
											//   confirms that it is MCrypt's fault.
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isset($dictionary[$this->_driver][$cipher]))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$cipher = $dictionary[$this->_driver][$cipher];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * HKDF
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @link	https://tools.ietf.org/rfc/rfc5869.txt
							 | 
						||
| 
								 | 
							
									 * @param	$key	Input key
							 | 
						||
| 
								 | 
							
									 * @param	$digest	A SHA-2 hashing algorithm
							 | 
						||
| 
								 | 
							
									 * @param	$salt	Optional salt
							 | 
						||
| 
								 | 
							
									 * @param	$length	Output length (defaults to the selected digest size)
							 | 
						||
| 
								 | 
							
									 * @param	$info	Optional context/application-specific info
							 | 
						||
| 
								 | 
							
									 * @return	string	A pseudo-random key
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function hkdf($key, $digest = 'sha512', $salt = NULL, $length = NULL, $info = '')
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ! isset($this->_digests[$digest]))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (empty($length) OR ! is_int($length))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$length = $this->_digests[$digest];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										elseif ($length > (255 * $this->_digests[$digest]))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return FALSE;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										self::strlen($salt) OR $salt = str_repeat("\0", $this->_digests[$digest]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										$prk = hash_hmac($digest, $key, $salt, TRUE);
							 | 
						||
| 
								 | 
							
										$key = '';
							 | 
						||
| 
								 | 
							
										for ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											$key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE);
							 | 
						||
| 
								 | 
							
											$key .= $key_block;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return self::substr($key, 0, $length);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * __get() magic
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$key	Property name
							 | 
						||
| 
								 | 
							
									 * @return	mixed
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									public function __get($key)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// Because aliases
							 | 
						||
| 
								 | 
							
										if ($key === 'mode')
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return array_search($this->_mode, $this->_modes[$this->_driver], TRUE);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										elseif (in_array($key, array('cipher', 'driver', 'drivers', 'digests'), TRUE))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return $this->{'_'.$key};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return NULL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Byte-safe strlen()
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$str
							 | 
						||
| 
								 | 
							
									 * @return	int
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static function strlen($str)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return (self::$func_overload)
							 | 
						||
| 
								 | 
							
											? mb_strlen($str, '8bit')
							 | 
						||
| 
								 | 
							
											: strlen($str);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// --------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * Byte-safe substr()
							 | 
						||
| 
								 | 
							
									 *
							 | 
						||
| 
								 | 
							
									 * @param	string	$str
							 | 
						||
| 
								 | 
							
									 * @param	int	$start
							 | 
						||
| 
								 | 
							
									 * @param	int	$length
							 | 
						||
| 
								 | 
							
									 * @return	string
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									protected static function substr($str, $start, $length = NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (self::$func_overload)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											// mb_substr($str, $start, null, '8bit') returns an empty
							 | 
						||
| 
								 | 
							
											// string on PHP 5.3
							 | 
						||
| 
								 | 
							
											isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
							 | 
						||
| 
								 | 
							
											return mb_substr($str, $start, $length, '8bit');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return isset($length)
							 | 
						||
| 
								 | 
							
											? substr($str, $start, $length)
							 | 
						||
| 
								 | 
							
											: substr($str, $start);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |