1
<?php
2
/**
3
* Encryption Class
4
*
5
* Provides two-way keyed encoding using XOR Hashing and Mcrypt
6
*/
7
class Encrypt_Library {
8
9
private $_encryption_key = '';
10
private $_hash_type = 'sha1';
11
private $_mcrypt_exists = FALSE;
12
private $_mcrypt_cipher;
13
private $_mcrypt_mode;
14
15
/**
16
* Constructor
17
*
18
* Simply determines whether the mcrypt library exists.
19
*/
20
public function __construct(array $config = NULL) {
21
$this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
22
// Set the encryption key
23
if (isset($config['encryption_key'])) {
24
$this->_encryption_key = $config['encryption_key'];
25
}
26
}
27
28
29
/**
30
* Fetch the encryption key
31
*
32
* Returns it as MD5 in order to have an exact-length 128 bit key.
33
* Mcrypt is sensitive to keys that are not the correct length
34
*
35
* @param string
36
* @return string
37
*/
38
public function get_key($key = '') {
39
if ($key == '') {
40
if ($this->_encryption_key != '') {
41
return $this->_encryption_key;
42
}
43
}
44
45
return md5($key);
46
}
47
48
49
/**
50
* Encode
51
*
52
* Encodes the message string using bitwise XOR encoding.
53
* The key is combined with a random hash, and then it
54
* too gets converted using XOR. The whole thing is then run
55
* through mcrypt (if supported) using the randomized key.
56
* The end result is a double-encrypted message string
57
* that is randomized with each call to this function,
58
* even if the supplied message and key are the same.
59
*
60
* @param string the string to encode
61
* @param string the key
62
* @return string
63
*/
64
public function encode($string, $key = '') {
65
$key = $this->get_key($key);
66
$enc = $this->_xor_encode($string, $key);
67
68
if ($this->_mcrypt_exists === TRUE){
69
$enc = $this->mcrypt_encode($enc, $key);
70
}
71
return base64_encode($enc);
72
}
73
74
75
/**
76
* Decode
77
*
78
* Reverses the above process
79
*
80
* @param string
81
* @param string
82
* @return string
83
*/
84
public function decode($string, $key = '') {
85
$key = $this->get_key($key);
86
87
if (preg_match('/[^a-zA-Z0-9\/\+=]/', $string)) {
88
return FALSE;
89
}
90
91
$dec = base64_decode($string);
92
93
if ($this->_mcrypt_exists === TRUE) {
94
if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE) {
95
return FALSE;
96
}
97
}
98
99
return $this->_xor_decode($dec, $key);
100
}
101
102
103
/**
104
* XOR Encode
105
*
106
* Takes a plain-text string and key as input and generates an
107
* encoded bit-string using XOR
108
*
109
* @param string
110
* @param string
111
* @return string
112
*/
113
private function _xor_encode($string, $key) {
114
$rand = '';
115
while (strlen($rand) < 32) {
116
$rand .= mt_rand(0, mt_getrandmax());
117
}
118
119
$rand = $this->hash($rand);
120
121
$enc = '';
122
for ($i = 0; $i < strlen($string); $i++) {
123
$enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
124
}
125
126
return $this->_xor_merge($enc, $key);
127
}
128
129
130
/**
131
* XOR Decode
132
*
133
* Takes an encoded string and key as input and generates the
134
* plain-text original message
135
*
136
* @param string
137
* @param string
138
* @return string
139
*/
140
private function _xor_decode($string, $key) {
141
$string = $this->_xor_merge($string, $key);
142
143
$dec = '';
144
for ($i = 0; $i < strlen($string); $i++) {
145
$dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
146
}
147
148
return $dec;
149
}
150
151
152
/**
153
* XOR key + string Combiner
154
*
155
* Takes a string and key as input and computes the difference using XOR
156
*
157
* @param string
158
* @param string
159
* @return string
160
*/
161
private function _xor_merge($string, $key) {
162
$hash = $this->hash($key);
163
$str = '';
164
for ($i = 0; $i < strlen($string); $i++) {
165
$str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
166
}
167
168
return $str;
169
}
170
171
172
/**
173
* Encrypt using Mcrypt
174
*
175
* @param string
176
* @param string
177
* @return string
178
*/
179
public function mcrypt_encode($data, $key) {
180
$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
181
$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
182
return $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);
183
}
184
185
186
/**
187
* Decrypt using Mcrypt
188
*
189
* @param string
190
* @param string
191
* @return string
192
*/
193
public function mcrypt_decode($data, $key) {
194
$data = $this->_remove_cipher_noise($data, $key);
195
$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());
196
197
if ($init_size > strlen($data)) {
198
return FALSE;
199
}
200
201
$init_vect = substr($data, 0, $init_size);
202
$data = substr($data, $init_size);
203
return rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), "\0");
204
}
205
206
207
/**
208
* Adds permuted noise to the IV + encrypted data to protect
209
* against Man-in-the-middle attacks on CBC mode ciphers
210
* http://www.ciphersbyritter.com/GLOSSARY.HTM#IV
211
*
212
* @param string
213
* @param string
214
* @return string
215
*/
216
private function _add_cipher_noise($data, $key) {
217
$keyhash = $this->hash($key);
218
$keylen = strlen($keyhash);
219
$str = '';
220
221
for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j) {
222
if ($j >= $keylen) {
223
$j = 0;
224
}
225
226
$str .= chr((ord($data[$i]) + ord($keyhash[$j])) % 256);
227
}
228
229
return $str;
230
}
231
232
233
/**
234
* Removes permuted noise from the IV + encrypted data, reversing
235
* _add_cipher_noise()
236
*
237
* @param type
238
* @return type
239
*/
240
private function _remove_cipher_noise($data, $key) {
241
$keyhash = $this->hash($key);
242
$keylen = strlen($keyhash);
243
$str = '';
244
245
for ($i = 0, $j = 0, $len = strlen($data); $i < $len; ++$i, ++$j) {
246
if ($j >= $keylen) {
247
$j = 0;
248
}
249
250
$temp = ord($data[$i]) - ord($keyhash[$j]);
251
252
if ($temp < 0) {
253
$temp = $temp + 256;
254
}
255
256
$str .= chr($temp);
257
}
258
259
return $str;
260
}
261
262
263
/**
264
* Set the Mcrypt Cipher
265
*
266
* @param constant
267
* @return string
268
*/
269
public function set_cipher($cipher) {
270
$this->_mcrypt_cipher = $cipher;
271
}
272
273
274
/**
275
* Set the Mcrypt Mode
276
*
277
* @param constant
278
* @return string
279
*/
280
public function set_mode($mode) {
281
$this->_mcrypt_mode = $mode;
282
}
283
284
285
/**
286
* Get Mcrypt cipher Value
287
*
288
* @return string
289
*/
290
private function _get_cipher() {
291
if ($this->_mcrypt_cipher == '') {
292
$this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
293
}
294
295
return $this->_mcrypt_cipher;
296
}
297
298
299
/**
300
* Get Mcrypt Mode Value
301
*
302
* @return string
303
*/
304
private function _get_mode() {
305
if ($this->_mcrypt_mode == '') {
306
$this->_mcrypt_mode = MCRYPT_MODE_ECB;
307
}
308
309
return $this->_mcrypt_mode;
310
}
311
312
313
/**
314
* Set the Hash type
315
*
316
* @param string
317
* @return string
318
*/
319
public function set_hash($type = 'sha1') {
320
$this->_hash_type = ($type != 'sha1' && $type != 'md5') ? 'sha1' : $type;
321
}
322
323
324
/**
325
* Hash encode a string
326
*
327
* @param string
328
* @return string
329
*/
330
public function hash($str) {
331
return ($this->_hash_type == 'sha1') ? sha1($str) : md5($str);
332
}
333
334
}
335
336
337
/* End of file: ./system/libraries/encrypt/encrypt_library.php */
Page URI: http://www.infopotato.com/index.php/code/library/encrypt/
