blob: 537b1ab203adfa9dbd88b1f05b0203d2ec444857 [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 */
admine79dc712006-09-26 03:52:45 +000015
adminb0dd10f2006-08-25 17:25:49 +000016// ------------------------------------------------------------------------
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 {
admin3ed8c512006-09-29 23:26:28 +000030 var $encryption_key = '';
adminb0dd10f2006-08-25 17:25:49 +000031 var $_hash_type = 'sha1';
32 var $_mcrypt_exists = FALSE;
33 var $_mcrypt_cipher;
34 var $_mcrypt_mode;
35
36 /**
37 * Constructor
38 *
39 * Simply determines whether the mcrypt library exists.
40 *
41 */
42 function CI_Encrypt()
43 {
44 $this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
45 log_message('debug', "Encrypt Class Initialized");
46 }
adminb0dd10f2006-08-25 17:25:49 +000047
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 {
admin3ed8c512006-09-29 23:26:28 +000064 if ($this->encryption_key != '')
65 {
66 return $this->encryption_key;
67 }
68
adminb0dd10f2006-08-25 17:25:49 +000069 $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 }
admin3ed8c512006-09-29 23:26:28 +000080
81 // --------------------------------------------------------------------
82
83 /**
84 * Set the encryption key
85 *
86 * @access public
87 * @param string
88 * @return void
89 */
90 function set_key($key = '')
91 {
92 $this->encryption_key = $key;
93 }
adminb0dd10f2006-08-25 17:25:49 +000094
95 // --------------------------------------------------------------------
96
97 /**
98 * Encode
99 *
100 * Encodes the message string using bitwise XOR encoding.
101 * The key is combined with a random hash, and then it
102 * too gets converted using XOR. The whole thing is then run
103 * through mcrypt (if supported) using the randomized key.
104 * The end result is a double-encrypted message string
105 * that is randomized with each call to this function,
106 * even if the supplied message and key are the same.
107 *
108 * @access public
109 * @param string the string to encode
110 * @param string the key
111 * @return string
112 */
113 function encode($string, $key = '')
114 {
115 $key = $this->get_key($key);
116 $enc = $this->_xor_encode($string, $key);
117
118 if ($this->_mcrypt_exists === TRUE)
119 {
120 $enc = $this->mcrypt_encode($enc, $key);
121 }
122 return base64_encode($enc);
123 }
adminb0dd10f2006-08-25 17:25:49 +0000124
125 // --------------------------------------------------------------------
126
127 /**
128 * Decode
129 *
130 * Reverses the above process
131 *
132 * @access public
133 * @param string
134 * @param string
135 * @return string
136 */
137 function decode($string, $key = '')
138 {
139 $key = $this->get_key($key);
140 $dec = base64_decode($string);
141
142 if ($dec === FALSE)
143 {
144 return FALSE;
145 }
146
147 if ($this->_mcrypt_exists === TRUE)
148 {
149 $dec = $this->mcrypt_decode($dec, $key);
150 }
151
152 return $this->_xor_decode($dec, $key);
153 }
adminb0dd10f2006-08-25 17:25:49 +0000154
155 // --------------------------------------------------------------------
156
157 /**
158 * XOR Encode
159 *
160 * Takes a plain-text string and key as input and generates an
161 * encoded bit-string using XOR
162 *
163 * @access private
164 * @param string
165 * @param string
166 * @return string
167 */
168 function _xor_encode($string, $key)
169 {
170 $rand = '';
171 while (strlen($rand) < 32)
172 {
173 $rand .= mt_rand(0, mt_getrandmax());
174 }
175
176 $rand = $this->hash($rand);
177
178 $enc = '';
179 for ($i = 0; $i < strlen($string); $i++)
180 {
181 $enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
182 }
183
184 return $this->_xor_merge($enc, $key);
185 }
adminb0dd10f2006-08-25 17:25:49 +0000186
187 // --------------------------------------------------------------------
188
189 /**
190 * XOR Decode
191 *
192 * Takes an encoded string and key as input and generates the
193 * plain-text original message
194 *
195 * @access private
196 * @param string
197 * @param string
198 * @return string
199 */
200 function _xor_decode($string, $key)
201 {
202 $string = $this->_xor_merge($string, $key);
203
204 $dec = '';
205 for ($i = 0; $i < strlen($string); $i++)
206 {
207 $dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
208 }
209
210 return $dec;
211 }
adminb0dd10f2006-08-25 17:25:49 +0000212
213 // --------------------------------------------------------------------
214
215 /**
216 * XOR key + string Combiner
217 *
218 * Takes a string and key as input and computes the difference using XOR
219 *
220 * @access private
221 * @param string
222 * @param string
223 * @return string
224 */
225 function _xor_merge($string, $key)
226 {
227 $hash = $this->hash($key);
228 $str = '';
229 for ($i = 0; $i < strlen($string); $i++)
230 {
231 $str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
232 }
233
234 return $str;
235 }
adminb0dd10f2006-08-25 17:25:49 +0000236
237 // --------------------------------------------------------------------
238
239 /**
240 * Encrypt using Mcrypt
241 *
242 * @access public
243 * @param string
244 * @param string
245 * @return string
246 */
247 function mcrypt_encode($data, $key)
248 {
249 $this->_get_mcrypt();
250 $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
251 $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
252 return mcrypt_encrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect);
253 }
adminb0dd10f2006-08-25 17:25:49 +0000254
255 // --------------------------------------------------------------------
256
257 /**
258 * Decrypt using Mcrypt
259 *
260 * @access public
261 * @param string
262 * @param string
263 * @return string
264 */
265 function mcrypt_decode($data, $key)
266 {
267 $this->_get_mcrypt();
268 $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
269 $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
270 return rtrim(mcrypt_decrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect), "\0");
271 }
adminb0dd10f2006-08-25 17:25:49 +0000272
273 // --------------------------------------------------------------------
274
275 /**
276 * Set the Mcrypt Cypher
277 *
278 * @access public
279 * @param constant
280 * @return string
281 */
282 function set_cypher($cypher)
283 {
284 $this->_mcrypt_cipher = $cypher;
285 }
adminb0dd10f2006-08-25 17:25:49 +0000286
287 // --------------------------------------------------------------------
288
289 /**
290 * Set the Mcrypt Mode
291 *
292 * @access public
293 * @param constant
294 * @return string
295 */
296 function set_mode($mode)
297 {
298 $this->_mcrypt_mode = $mode;
299 }
adminb0dd10f2006-08-25 17:25:49 +0000300
301 // --------------------------------------------------------------------
302
303 /**
304 * Get Mcrypt value
305 *
306 * @access private
307 * @param string
308 * @return string
309 */
310 function _get_mcrypt()
311 {
312 if ($this->_mcrypt_cipher == '')
313 {
314 $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
315 }
316 if ($this->_mcrypt_mode == '')
317 {
318 $this->_mcrypt_mode = MCRYPT_MODE_ECB;
319 }
320 }
adminb0dd10f2006-08-25 17:25:49 +0000321
322 // --------------------------------------------------------------------
323
324 /**
325 * Set the Hash type
326 *
327 * @access public
328 * @param string
329 * @return string
330 */
331 function set_hash($type = 'sha1')
332 {
admin141808a2006-08-27 01:52:51 +0000333 $this->_hash_type = ($type != 'sha1' AND $type != 'md5') ? 'sha1' : $type;
adminb0dd10f2006-08-25 17:25:49 +0000334 }
adminb0dd10f2006-08-25 17:25:49 +0000335
336 // --------------------------------------------------------------------
337
338 /**
339 * Hash encode a string
340 *
341 * @access public
342 * @param string
343 * @return string
344 */
345 function hash($str)
346 {
347 return ($this->_hash_type == 'sha1') ? $this->sha1($str) : md5($str);
348 }
adminb0dd10f2006-08-25 17:25:49 +0000349
350 // --------------------------------------------------------------------
351
352 /**
353 * Generate an SHA1 Hash
354 *
355 * @access public
356 * @param string
357 * @return string
358 */
359 function sha1($str)
360 {
361 if ( ! function_exists('sha1'))
362 {
363 if ( ! function_exists('mhash'))
364 {
365 require_once(BASEPATH.'libraries/Sha1'.EXT);
366 $SH = new CI_SHA;
367 return $SH->generate($str);
368 }
369 else
370 {
371 return bin2hex(mhash(MHASH_SHA1, $str));
372 }
373 }
374 else
375 {
376 return sha1($str);
377 }
378 }
adminb0dd10f2006-08-25 17:25:49 +0000379
380}
381
382// END CI_Encrypt class
383?>