PageRenderTime 483ms CodeModel.GetById 260ms app.highlight 113ms RepoModel.GetById 106ms app.codeStats 0ms

/halogy/libraries/Encrypt.php

https://bitbucket.org/haloweb/halogy-1.0/
PHP | 484 lines | 203 code | 69 blank | 212 comment | 29 complexity | d0f356a8bda8b618b6ebca86cfb359f9 MD5 | raw file
  1<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2/**
  3 * CodeIgniter
  4 *
  5 * An open source application development framework for PHP 4.3.2 or newer
  6 *
  7 * @package		CodeIgniter
  8 * @author		ExpressionEngine Dev Team
  9 * @copyright	Copyright (c) 2008 - 2009, EllisLab, Inc.
 10 * @license		http://codeigniter.com/user_guide/license.html
 11 * @link		http://codeigniter.com
 12 * @since		Version 1.0
 13 * @filesource
 14 */
 15
 16// ------------------------------------------------------------------------
 17
 18/**
 19 * CodeIgniter Encryption Class
 20 *
 21 * Provides two-way keyed encoding using XOR Hashing and Mcrypt
 22 *
 23 * @package		CodeIgniter
 24 * @subpackage	Libraries
 25 * @category	Libraries
 26 * @author		ExpressionEngine Dev Team
 27 * @link		http://codeigniter.com/user_guide/libraries/encryption.html
 28 */
 29class CI_Encrypt {
 30
 31	var $CI;
 32	var $encryption_key	= '';
 33	var $_hash_type	= 'sha1';
 34	var $_mcrypt_exists = FALSE;
 35	var $_mcrypt_cipher;
 36	var $_mcrypt_mode;
 37
 38	/**
 39	 * Constructor
 40	 *
 41	 * Simply determines whether the mcrypt library exists.
 42	 *
 43	 */
 44	function CI_Encrypt()
 45	{
 46		$this->CI =& get_instance();
 47		$this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
 48		log_message('debug', "Encrypt Class Initialized");
 49	}
 50
 51	// --------------------------------------------------------------------
 52
 53	/**
 54	 * Fetch the encryption key
 55	 *
 56	 * Returns it as MD5 in order to have an exact-length 128 bit key.
 57	 * Mcrypt is sensitive to keys that are not the correct length
 58	 *
 59	 * @access	public
 60	 * @param	string
 61	 * @return	string
 62	 */
 63	function get_key($key = '')
 64	{
 65		if ($key == '')
 66		{
 67			if ($this->encryption_key != '')
 68			{
 69				return $this->encryption_key;
 70			}
 71
 72			$CI =& get_instance();
 73			$key = $CI->config->item('encryption_key');
 74
 75			if ($key === FALSE)
 76			{
 77				show_error('In order to use the encryption class requires that you set an encryption key in your config file.');
 78			}
 79		}
 80
 81		return md5($key);
 82	}
 83
 84	// --------------------------------------------------------------------
 85
 86	/**
 87	 * Set the encryption key
 88	 *
 89	 * @access	public
 90	 * @param	string
 91	 * @return	void
 92	 */
 93	function set_key($key = '')
 94	{
 95		$this->encryption_key = $key;
 96	}
 97
 98	// --------------------------------------------------------------------
 99
100	/**
101	 * Encode
102	 *
103	 * Encodes the message string using bitwise XOR encoding.
104	 * The key is combined with a random hash, and then it
105	 * too gets converted using XOR. The whole thing is then run
106	 * through mcrypt (if supported) using the randomized key.
107	 * The end result is a double-encrypted message string
108	 * that is randomized with each call to this function,
109	 * even if the supplied message and key are the same.
110	 *
111	 * @access	public
112	 * @param	string	the string to encode
113	 * @param	string	the key
114	 * @return	string
115	 */
116	function encode($string, $key = '')
117	{
118		$key = $this->get_key($key);
119		$enc = $this->_xor_encode($string, $key);
120		
121		if ($this->_mcrypt_exists === TRUE)
122		{
123			$enc = $this->mcrypt_encode($enc, $key);
124		}
125		return base64_encode($enc);
126	}
127
128	// --------------------------------------------------------------------
129
130	/**
131	 * Decode
132	 *
133	 * Reverses the above process
134	 *
135	 * @access	public
136	 * @param	string
137	 * @param	string
138	 * @return	string
139	 */
140	function decode($string, $key = '')
141	{
142		$key = $this->get_key($key);
143		
144		if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string))
145		{
146			return FALSE;
147		}
148
149		$dec = base64_decode($string);
150
151		if ($this->_mcrypt_exists === TRUE)
152		{
153			if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)
154			{
155				return FALSE;
156			}
157		}
158
159		return $this->_xor_decode($dec, $key);
160	}
161
162	// --------------------------------------------------------------------
163
164	/**
165	 * XOR Encode
166	 *
167	 * Takes a plain-text string and key as input and generates an
168	 * encoded bit-string using XOR
169	 *
170	 * @access	private
171	 * @param	string
172	 * @param	string
173	 * @return	string
174	 */
175	function _xor_encode($string, $key)
176	{
177		$rand = '';
178		while (strlen($rand) < 32)
179		{
180			$rand .= mt_rand(0, mt_getrandmax());
181		}
182
183		$rand = $this->hash($rand);
184
185		$enc = '';
186		for ($i = 0; $i < strlen($string); $i++)
187		{			
188			$enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
189		}
190
191		return $this->_xor_merge($enc, $key);
192	}
193
194	// --------------------------------------------------------------------
195
196	/**
197	 * XOR Decode
198	 *
199	 * Takes an encoded string and key as input and generates the
200	 * plain-text original message
201	 *
202	 * @access	private
203	 * @param	string
204	 * @param	string
205	 * @return	string
206	 */
207	function _xor_decode($string, $key)
208	{
209		$string = $this->_xor_merge($string, $key);
210
211		$dec = '';
212		for ($i = 0; $i < strlen($string); $i++)
213		{
214			$dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
215		}
216
217		return $dec;
218	}
219
220	// --------------------------------------------------------------------
221
222	/**
223	 * XOR key + string Combiner
224	 *
225	 * Takes a string and key as input and computes the difference using XOR
226	 *
227	 * @access	private
228	 * @param	string
229	 * @param	string
230	 * @return	string
231	 */
232	function _xor_merge($string, $key)
233	{
234		$hash = $this->hash($key);
235		$str = '';
236		for ($i = 0; $i < strlen($string); $i++)
237		{
238			$str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
239		}
240
241		return $str;
242	}
243
244	// --------------------------------------------------------------------
245
246	/**
247	 * Encrypt using Mcrypt
248	 *
249	 * @access	public
250	 * @param	string
251	 * @param	string
252	 * @return	string
253	 */
254	function mcrypt_encode($data, $key)
255	{
256		$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
257		$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
258		return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);
259	}
260
261	// --------------------------------------------------------------------
262
263	/**
264	 * Decrypt using Mcrypt
265	 *
266	 * @access	public
267	 * @param	string
268	 * @param	string
269	 * @return	string
270	 */
271	function mcrypt_decode($data, $key)
272	{
273		$data = $this->_remove_cipher_noise($data, $key);
274		$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
275
276		if ($init_size > strlen($data))
277		{
278			return FALSE;
279		}
280
281		$init_vect = substr($data, 0, $init_size);
282		$data = substr($data, $init_size);
283		return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0");
284	}
285
286	// --------------------------------------------------------------------
287
288	/**
289	 * Adds permuted noise to the IV + encrypted data to protect
290	 * against Man-in-the-middle attacks on CBC mode ciphers
291	 * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV
292	 *
293	 * Function description
294	 *
295	 * @access	private
296	 * @param	string
297	 * @param	string
298	 * @return	string
299	 */
300	function _add_cipher_noise($data, $key)
301	{
302		$keyhash = $this->hash($key);
303		$keylen = strlen($keyhash);
304		$str = '';
305
306		for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j)
307		{
308			if ($j >= $keylen)
309			{
310				$j = 0;
311			}
312
313			$str .= chr((ord($data[$i]) + ord($keyhash[$j])) % 256);
314		}
315
316		return $str;
317	}
318
319	// --------------------------------------------------------------------
320
321	/**
322	 * Removes permuted noise from the IV + encrypted data, reversing
323	 * _add_cipher_noise()
324	 *
325	 * Function description
326	 *
327	 * @access	public
328	 * @param	type
329	 * @return	type
330	 */
331	function _remove_cipher_noise($data, $key)
332	{
333		$keyhash = $this->hash($key);
334		$keylen = strlen($keyhash);
335		$str = '';
336
337		for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j)
338		{
339			if ($j >= $keylen)
340			{
341				$j = 0;
342			}
343
344			$temp = ord($data[$i]) - ord($keyhash[$j]);
345
346			if ($temp < 0)
347			{
348				$temp = $temp + 256;
349			}
350			
351			$str .= chr($temp);
352		}
353
354		return $str;
355	}
356
357	// --------------------------------------------------------------------
358	
359	/**
360	 * Set the Mcrypt Cipher
361	 *
362	 * @access	public
363	 * @param	constant
364	 * @return	string
365	 */
366	function set_cipher($cipher)
367	{
368		$this->_mcrypt_cipher = $cipher;
369	}
370
371	// --------------------------------------------------------------------
372
373	/**
374	 * Set the Mcrypt Mode
375	 *
376	 * @access	public
377	 * @param	constant
378	 * @return	string
379	 */
380	function set_mode($mode)
381	{
382		$this->_mcrypt_mode = $mode;
383	}
384
385	// --------------------------------------------------------------------
386
387	/**
388	 * Get Mcrypt cipher Value
389	 *
390	 * @access	private
391	 * @return	string
392	 */
393	function _get_cipher()
394	{
395		if ($this->_mcrypt_cipher == '')
396		{
397			$this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
398		}
399
400		return $this->_mcrypt_cipher;
401	}
402
403	// --------------------------------------------------------------------
404
405	/**
406	 * Get Mcrypt Mode Value
407	 *
408	 * @access	private
409	 * @return	string
410	 */
411	function _get_mode()
412	{
413		if ($this->_mcrypt_mode == '')
414		{
415			$this->_mcrypt_mode = MCRYPT_MODE_ECB;
416		}
417		
418		return $this->_mcrypt_mode;
419	}
420
421	// --------------------------------------------------------------------
422
423	/**
424	 * Set the Hash type
425	 *
426	 * @access	public
427	 * @param	string
428	 * @return	string
429	 */
430	function set_hash($type = 'sha1')
431	{
432		$this->_hash_type = ($type != 'sha1' AND $type != 'md5') ? 'sha1' : $type;
433	}
434
435	// --------------------------------------------------------------------
436
437	/**
438	 * Hash encode a string
439	 *
440	 * @access	public
441	 * @param	string
442	 * @return	string
443	 */	
444	function hash($str)
445	{
446		return ($this->_hash_type == 'sha1') ? $this->sha1($str) : md5($str);
447	}
448
449	// --------------------------------------------------------------------
450
451	/**
452	 * Generate an SHA1 Hash
453	 *
454	 * @access	public
455	 * @param	string
456	 * @return	string
457	 */
458	function sha1($str)
459	{
460		if ( ! function_exists('sha1'))
461		{
462			if ( ! function_exists('mhash'))
463			{
464				require_once(BASEPATH.'libraries/Sha1'.EXT);
465				$SH = new CI_SHA;
466				return $SH->generate($str);
467			}
468			else
469			{
470				return bin2hex(mhash(MHASH_SHA1, $str));
471			}
472		}
473		else
474		{
475			return sha1($str);
476		}
477	}
478
479}
480
481// END CI_Encrypt class
482
483/* End of file Encrypt.php */
484/* Location: ./system/libraries/Encrypt.php */