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