Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2005 Aurelien 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, 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
 */
29
class 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 */