blob: 6a3ca17b049c02be06b8b8ed4757679435364713 [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
admine79dc712006-09-26 03:52:45 +000016// INITIALIZE THE CLASS ---------------------------------------------------
17
18$obj =& get_instance();
admin7981a9a2006-09-26 07:52:09 +000019$obj->init_class('CI_Encrypt');
admine79dc712006-09-26 03:52:45 +000020
adminb0dd10f2006-08-25 17:25:49 +000021// ------------------------------------------------------------------------
22
23/**
24 * Code Igniter Encryption Class
25 *
26 * Provides two-way keyed encoding using XOR Hashing and Mcrypt
27 *
28 * @package CodeIgniter
29 * @subpackage Libraries
30 * @category Libraries
31 * @author Rick Ellis
32 * @link http://www.codeigniter.com/user_guide/libraries/encryption.html
33 */
34class CI_Encrypt {
35 var $_hash_type = 'sha1';
36 var $_mcrypt_exists = FALSE;
37 var $_mcrypt_cipher;
38 var $_mcrypt_mode;
39
40 /**
41 * Constructor
42 *
43 * Simply determines whether the mcrypt library exists.
44 *
45 */
46 function CI_Encrypt()
47 {
48 $this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
49 log_message('debug', "Encrypt Class Initialized");
50 }
51 // END CI_Encrypt()
52
53 // --------------------------------------------------------------------
54
55 /**
56 * Fetch the encryption key
57 *
58 * Returns it as MD5 in order to have an exact-length 128 bit key.
59 * Mcrypt is sensitive to keys that are not the correct length
60 *
61 * @access public
62 * @param string
63 * @return string
64 */
65 function get_key($key = '')
66 {
67 if ($key == '')
68 {
69 $obj =& get_instance();
70 $key = $obj->config->item('encryption_key');
71
72 if ($key === FALSE)
73 {
74 show_error('In order to use the encryption class requires that you set an encryption key in your config file.');
75 }
76 }
77
78 return md5($key);
79 }
80 // END get_key()
81
82 // --------------------------------------------------------------------
83
84 /**
85 * Encode
86 *
87 * Encodes the message string using bitwise XOR encoding.
88 * The key is combined with a random hash, and then it
89 * too gets converted using XOR. The whole thing is then run
90 * through mcrypt (if supported) using the randomized key.
91 * The end result is a double-encrypted message string
92 * that is randomized with each call to this function,
93 * even if the supplied message and key are the same.
94 *
95 * @access public
96 * @param string the string to encode
97 * @param string the key
98 * @return string
99 */
100 function encode($string, $key = '')
101 {
102 $key = $this->get_key($key);
103 $enc = $this->_xor_encode($string, $key);
104
105 if ($this->_mcrypt_exists === TRUE)
106 {
107 $enc = $this->mcrypt_encode($enc, $key);
108 }
109 return base64_encode($enc);
110 }
111 // END encode()
112
113 // --------------------------------------------------------------------
114
115 /**
116 * Decode
117 *
118 * Reverses the above process
119 *
120 * @access public
121 * @param string
122 * @param string
123 * @return string
124 */
125 function decode($string, $key = '')
126 {
127 $key = $this->get_key($key);
128 $dec = base64_decode($string);
129
130 if ($dec === FALSE)
131 {
132 return FALSE;
133 }
134
135 if ($this->_mcrypt_exists === TRUE)
136 {
137 $dec = $this->mcrypt_decode($dec, $key);
138 }
139
140 return $this->_xor_decode($dec, $key);
141 }
142 // END decode()
143
144 // --------------------------------------------------------------------
145
146 /**
147 * XOR Encode
148 *
149 * Takes a plain-text string and key as input and generates an
150 * encoded bit-string using XOR
151 *
152 * @access private
153 * @param string
154 * @param string
155 * @return string
156 */
157 function _xor_encode($string, $key)
158 {
159 $rand = '';
160 while (strlen($rand) < 32)
161 {
162 $rand .= mt_rand(0, mt_getrandmax());
163 }
164
165 $rand = $this->hash($rand);
166
167 $enc = '';
168 for ($i = 0; $i < strlen($string); $i++)
169 {
170 $enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
171 }
172
173 return $this->_xor_merge($enc, $key);
174 }
175 // END _xor_encode()
176
177 // --------------------------------------------------------------------
178
179 /**
180 * XOR Decode
181 *
182 * Takes an encoded string and key as input and generates the
183 * plain-text original message
184 *
185 * @access private
186 * @param string
187 * @param string
188 * @return string
189 */
190 function _xor_decode($string, $key)
191 {
192 $string = $this->_xor_merge($string, $key);
193
194 $dec = '';
195 for ($i = 0; $i < strlen($string); $i++)
196 {
197 $dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
198 }
199
200 return $dec;
201 }
202 // END _xor_decode()
203
204 // --------------------------------------------------------------------
205
206 /**
207 * XOR key + string Combiner
208 *
209 * Takes a string and key as input and computes the difference using XOR
210 *
211 * @access private
212 * @param string
213 * @param string
214 * @return string
215 */
216 function _xor_merge($string, $key)
217 {
218 $hash = $this->hash($key);
219 $str = '';
220 for ($i = 0; $i < strlen($string); $i++)
221 {
222 $str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
223 }
224
225 return $str;
226 }
227 // END _xor_merge()
228
229 // --------------------------------------------------------------------
230
231 /**
232 * Encrypt using Mcrypt
233 *
234 * @access public
235 * @param string
236 * @param string
237 * @return string
238 */
239 function mcrypt_encode($data, $key)
240 {
241 $this->_get_mcrypt();
242 $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
243 $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
244 return mcrypt_encrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect);
245 }
246 // END mcrypt_encode()
247
248 // --------------------------------------------------------------------
249
250 /**
251 * Decrypt using Mcrypt
252 *
253 * @access public
254 * @param string
255 * @param string
256 * @return string
257 */
258 function mcrypt_decode($data, $key)
259 {
260 $this->_get_mcrypt();
261 $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
262 $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
263 return rtrim(mcrypt_decrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect), "\0");
264 }
265 // END mcrypt_decode()
266
267 // --------------------------------------------------------------------
268
269 /**
270 * Set the Mcrypt Cypher
271 *
272 * @access public
273 * @param constant
274 * @return string
275 */
276 function set_cypher($cypher)
277 {
278 $this->_mcrypt_cipher = $cypher;
279 }
280 // END set_cypher()
281
282 // --------------------------------------------------------------------
283
284 /**
285 * Set the Mcrypt Mode
286 *
287 * @access public
288 * @param constant
289 * @return string
290 */
291 function set_mode($mode)
292 {
293 $this->_mcrypt_mode = $mode;
294 }
295 // END set_mode()
296
297 // --------------------------------------------------------------------
298
299 /**
300 * Get Mcrypt value
301 *
302 * @access private
303 * @param string
304 * @return string
305 */
306 function _get_mcrypt()
307 {
308 if ($this->_mcrypt_cipher == '')
309 {
310 $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
311 }
312 if ($this->_mcrypt_mode == '')
313 {
314 $this->_mcrypt_mode = MCRYPT_MODE_ECB;
315 }
316 }
317 // END _get_mcrypt()
318
319 // --------------------------------------------------------------------
320
321 /**
322 * Set the Hash type
323 *
324 * @access public
325 * @param string
326 * @return string
327 */
328 function set_hash($type = 'sha1')
329 {
admin141808a2006-08-27 01:52:51 +0000330 $this->_hash_type = ($type != 'sha1' AND $type != 'md5') ? 'sha1' : $type;
adminb0dd10f2006-08-25 17:25:49 +0000331 }
332 // END set_hash()
333
334 // --------------------------------------------------------------------
335
336 /**
337 * Hash encode a string
338 *
339 * @access public
340 * @param string
341 * @return string
342 */
343 function hash($str)
344 {
345 return ($this->_hash_type == 'sha1') ? $this->sha1($str) : md5($str);
346 }
347 // END hash()
348
349 // --------------------------------------------------------------------
350
351 /**
352 * Generate an SHA1 Hash
353 *
354 * @access public
355 * @param string
356 * @return string
357 */
358 function sha1($str)
359 {
360 if ( ! function_exists('sha1'))
361 {
362 if ( ! function_exists('mhash'))
363 {
364 require_once(BASEPATH.'libraries/Sha1'.EXT);
365 $SH = new CI_SHA;
366 return $SH->generate($str);
367 }
368 else
369 {
370 return bin2hex(mhash(MHASH_SHA1, $str));
371 }
372 }
373 else
374 {
375 return sha1($str);
376 }
377 }
378 // END sha1()
379
380}
381
382// END CI_Encrypt class
383?>