Subversion-Projekte lars-tiefland.ci

Revision

Revision 68 | Revision 2107 | Zur aktuellen Revision | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
2049 lars 9
 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
68 lars 10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
2049 lars 32
 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
68 lars 33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * CodeIgniter Encryption Class
42
 *
43
 * Provides two-way keyed encoding using Mcrypt
44
 *
45
 * @package		CodeIgniter
46
 * @subpackage	Libraries
47
 * @category	Libraries
48
 * @author		EllisLab Dev Team
49
 * @link		https://codeigniter.com/user_guide/libraries/encryption.html
50
 */
51
class CI_Encrypt {
52
 
53
	/**
54
	 * Reference to the user's encryption key
55
	 *
56
	 * @var string
57
	 */
58
	public $encryption_key		= '';
59
 
60
	/**
61
	 * Type of hash operation
62
	 *
63
	 * @var string
64
	 */
65
	protected $_hash_type		= 'sha1';
66
 
67
	/**
68
	 * Flag for the existence of mcrypt
69
	 *
70
	 * @var bool
71
	 */
72
	protected $_mcrypt_exists	= FALSE;
73
 
74
	/**
75
	 * Current cipher to be used with mcrypt
76
	 *
77
	 * @var string
78
	 */
79
	protected $_mcrypt_cipher;
80
 
81
	/**
82
	 * Method for encrypting/decrypting data
83
	 *
84
	 * @var int
85
	 */
86
	protected $_mcrypt_mode;
87
 
88
	/**
89
	 * Initialize Encryption class
90
	 *
91
	 * @return	void
92
	 */
93
	public function __construct()
94
	{
95
		if (($this->_mcrypt_exists = function_exists('mcrypt_encrypt')) === FALSE)
96
		{
97
			show_error('The Encrypt library requires the Mcrypt extension.');
98
		}
99
 
100
		log_message('info', 'Encrypt Class Initialized');
101
	}
102
 
103
	// --------------------------------------------------------------------
104
 
105
	/**
106
	 * Fetch the encryption key
107
	 *
108
	 * Returns it as MD5 in order to have an exact-length 128 bit key.
109
	 * Mcrypt is sensitive to keys that are not the correct length
110
	 *
111
	 * @param	string
112
	 * @return	string
113
	 */
114
	public function get_key($key = '')
115
	{
116
		if ($key === '')
117
		{
118
			if ($this->encryption_key !== '')
119
			{
120
				return $this->encryption_key;
121
			}
122
 
123
			$key = config_item('encryption_key');
124
 
125
			if ( ! strlen($key))
126
			{
127
				show_error('In order to use the encryption class requires that you set an encryption key in your config file.');
128
			}
129
		}
130
 
131
		return md5($key);
132
	}
133
 
134
	// --------------------------------------------------------------------
135
 
136
	/**
137
	 * Set the encryption key
138
	 *
139
	 * @param	string
140
	 * @return	CI_Encrypt
141
	 */
142
	public function set_key($key = '')
143
	{
144
		$this->encryption_key = $key;
145
		return $this;
146
	}
147
 
148
	// --------------------------------------------------------------------
149
 
150
	/**
151
	 * Encode
152
	 *
153
	 * Encodes the message string using bitwise XOR encoding.
154
	 * The key is combined with a random hash, and then it
155
	 * too gets converted using XOR. The whole thing is then run
156
	 * through mcrypt using the randomized key. The end result
157
	 * is a double-encrypted message string that is randomized
158
	 * with each call to this function, even if the supplied
159
	 * message and key are the same.
160
	 *
161
	 * @param	string	the string to encode
162
	 * @param	string	the key
163
	 * @return	string
164
	 */
165
	public function encode($string, $key = '')
166
	{
167
		return base64_encode($this->mcrypt_encode($string, $this->get_key($key)));
168
	}
169
 
170
	// --------------------------------------------------------------------
171
 
172
	/**
173
	 * Decode
174
	 *
175
	 * Reverses the above process
176
	 *
177
	 * @param	string
178
	 * @param	string
179
	 * @return	string
180
	 */
181
	public function decode($string, $key = '')
182
	{
183
		if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string)
184
		{
185
			return FALSE;
186
		}
187
 
188
		return $this->mcrypt_decode(base64_decode($string), $this->get_key($key));
189
	}
190
 
191
	// --------------------------------------------------------------------
192
 
193
	/**
194
	 * Encode from Legacy
195
	 *
196
	 * Takes an encoded string from the original Encryption class algorithms and
197
	 * returns a newly encoded string using the improved method added in 2.0.0
198
	 * This allows for backwards compatibility and a method to transition to the
199
	 * new encryption algorithms.
200
	 *
201
	 * For more details, see https://codeigniter.com/user_guide/installation/upgrade_200.html#encryption
202
	 *
203
	 * @param	string
204
	 * @param	int		(mcrypt mode constant)
205
	 * @param	string
206
	 * @return	string
207
	 */
208
	public function encode_from_legacy($string, $legacy_mode = MCRYPT_MODE_ECB, $key = '')
209
	{
210
		if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string))
211
		{
212
			return FALSE;
213
		}
214
 
215
		// decode it first
216
		// set mode temporarily to what it was when string was encoded with the legacy
217
		// algorithm - typically MCRYPT_MODE_ECB
218
		$current_mode = $this->_get_mode();
219
		$this->set_mode($legacy_mode);
220
 
221
		$key = $this->get_key($key);
222
		$dec = base64_decode($string);
223
		if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)
224
		{
225
			$this->set_mode($current_mode);
226
			return FALSE;
227
		}
228
 
229
		$dec = $this->_xor_decode($dec, $key);
230
 
231
		// set the mcrypt mode back to what it should be, typically MCRYPT_MODE_CBC
232
		$this->set_mode($current_mode);
233
 
234
		// and re-encode
235
		return base64_encode($this->mcrypt_encode($dec, $key));
236
	}
237
 
238
	// --------------------------------------------------------------------
239
 
240
	/**
241
	 * XOR Decode
242
	 *
243
	 * Takes an encoded string and key as input and generates the
244
	 * plain-text original message
245
	 *
246
	 * @param	string
247
	 * @param	string
248
	 * @return	string
249
	 */
250
	protected function _xor_decode($string, $key)
251
	{
252
		$string = $this->_xor_merge($string, $key);
253
 
254
		$dec = '';
255
		for ($i = 0, $l = strlen($string); $i < $l; $i++)
256
		{
257
			$dec .= ($string[$i++] ^ $string[$i]);
258
		}
259
 
260
		return $dec;
261
	}
262
 
263
	// --------------------------------------------------------------------
264
 
265
	/**
266
	 * XOR key + string Combiner
267
	 *
268
	 * Takes a string and key as input and computes the difference using XOR
269
	 *
270
	 * @param	string
271
	 * @param	string
272
	 * @return	string
273
	 */
274
	protected function _xor_merge($string, $key)
275
	{
276
		$hash = $this->hash($key);
277
		$str = '';
278
		for ($i = 0, $ls = strlen($string), $lh = strlen($hash); $i < $ls; $i++)
279
		{
280
			$str .= $string[$i] ^ $hash[($i % $lh)];
281
		}
282
 
283
		return $str;
284
	}
285
 
286
	// --------------------------------------------------------------------
287
 
288
	/**
289
	 * Encrypt using Mcrypt
290
	 *
291
	 * @param	string
292
	 * @param	string
293
	 * @return	string
294
	 */
295
	public function mcrypt_encode($data, $key)
296
	{
297
		$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
298
		$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
299
		return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);
300
	}
301
 
302
	// --------------------------------------------------------------------
303
 
304
	/**
305
	 * Decrypt using Mcrypt
306
	 *
307
	 * @param	string
308
	 * @param	string
309
	 * @return	string
310
	 */
311
	public function mcrypt_decode($data, $key)
312
	{
313
		$data = $this->_remove_cipher_noise($data, $key);
314
		$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
315
 
316
		if ($init_size > strlen($data))
317
		{
318
			return FALSE;
319
		}
320
 
321
		$init_vect = substr($data, 0, $init_size);
322
		$data = substr($data, $init_size);
323
		return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0");
324
	}
325
 
326
	// --------------------------------------------------------------------
327
 
328
	/**
329
	 * Adds permuted noise to the IV + encrypted data to protect
330
	 * against Man-in-the-middle attacks on CBC mode ciphers
331
	 * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV
332
	 *
333
	 * @param	string
334
	 * @param	string
335
	 * @return	string
336
	 */
337
	protected function _add_cipher_noise($data, $key)
338
	{
339
		$key = $this->hash($key);
340
		$str = '';
341
 
342
		for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)
343
		{
344
			if ($j >= $lk)
345
			{
346
				$j = 0;
347
			}
348
 
349
			$str .= chr((ord($data[$i]) + ord($key[$j])) % 256);
350
		}
351
 
352
		return $str;
353
	}
354
 
355
	// --------------------------------------------------------------------
356
 
357
	/**
358
	 * Removes permuted noise from the IV + encrypted data, reversing
359
	 * _add_cipher_noise()
360
	 *
361
	 * Function description
362
	 *
363
	 * @param	string	$data
364
	 * @param	string	$key
365
	 * @return	string
366
	 */
367
	protected function _remove_cipher_noise($data, $key)
368
	{
369
		$key = $this->hash($key);
370
		$str = '';
371
 
372
		for ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)
373
		{
374
			if ($j >= $lk)
375
			{
376
				$j = 0;
377
			}
378
 
379
			$temp = ord($data[$i]) - ord($key[$j]);
380
 
381
			if ($temp < 0)
382
			{
383
				$temp += 256;
384
			}
385
 
386
			$str .= chr($temp);
387
		}
388
 
389
		return $str;
390
	}
391
 
392
	// --------------------------------------------------------------------
393
 
394
	/**
395
	 * Set the Mcrypt Cipher
396
	 *
397
	 * @param	int
398
	 * @return	CI_Encrypt
399
	 */
400
	public function set_cipher($cipher)
401
	{
402
		$this->_mcrypt_cipher = $cipher;
403
		return $this;
404
	}
405
 
406
	// --------------------------------------------------------------------
407
 
408
	/**
409
	 * Set the Mcrypt Mode
410
	 *
411
	 * @param	int
412
	 * @return	CI_Encrypt
413
	 */
414
	public function set_mode($mode)
415
	{
416
		$this->_mcrypt_mode = $mode;
417
		return $this;
418
	}
419
 
420
	// --------------------------------------------------------------------
421
 
422
	/**
423
	 * Get Mcrypt cipher Value
424
	 *
425
	 * @return	int
426
	 */
427
	protected function _get_cipher()
428
	{
429
		if ($this->_mcrypt_cipher === NULL)
430
		{
431
			return $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
432
		}
433
 
434
		return $this->_mcrypt_cipher;
435
	}
436
 
437
	// --------------------------------------------------------------------
438
 
439
	/**
440
	 * Get Mcrypt Mode Value
441
	 *
442
	 * @return	int
443
	 */
444
	protected function _get_mode()
445
	{
446
		if ($this->_mcrypt_mode === NULL)
447
		{
448
			return $this->_mcrypt_mode = MCRYPT_MODE_CBC;
449
		}
450
 
451
		return $this->_mcrypt_mode;
452
	}
453
 
454
	// --------------------------------------------------------------------
455
 
456
	/**
457
	 * Set the Hash type
458
	 *
459
	 * @param	string
460
	 * @return	void
461
	 */
462
	public function set_hash($type = 'sha1')
463
	{
464
		$this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1';
465
	}
466
 
467
	// --------------------------------------------------------------------
468
 
469
	/**
470
	 * Hash encode a string
471
	 *
472
	 * @param	string
473
	 * @return	string
474
	 */
475
	public function hash($str)
476
	{
477
		return hash($this->_hash_type, $str);
478
	}
479
 
480
}