Completed
Branch BUG-10412-mcrypt-deprecated (81a654)
by
unknown
49:46 queued 37:21
created

EE_Encryption::acme_decrypt()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 13

Duplication

Lines 4
Ratio 20 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 5
nop 1
dl 4
loc 20
rs 8.8571
c 0
b 0
f 0
1
<?php
2
defined('EVENT_ESPRESSO_VERSION') || exit('No direct script access allowed');
3
4
5
6
/**
7
 * EE_Encryption class
8
 * class for applying low-grade string encryption/decryption
9
 * really only good for hiding content from simple bots and script kiddies
10
 * but better for solving encoding issues with databases
11
 *
12
 * @package    Event Espresso
13
 * @subpackage includes/functions
14
 * @author     Brent Christensen
15
 */
16
class EE_Encryption
17
{
18
19
    /**
20
     * key used for saving the encryption key to the wp_options table
21
     */
22
    const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
23
24
    /**
25
     * the OPENSSL cipher method used
26
     */
27
    const OPENSSL_CIPHER_METHOD = 'aes-256-ctr';
28
29
    /**
30
     * the OPENSSL digest method used
31
     */
32
    const OPENSSL_DIGEST_METHOD = 'sha512';
33
34
    /**
35
     * separates the encrypted text from the initialization vector
36
     */
37
    const OPENSSL_IV_DELIMITER = ':iv:';
38
39
40
41
    /**
42
     * instance of the EE_Encryption object
43
     */
44
    protected static $_instance;
45
46
    /**
47
     * @var string $_encryption_key
48
     */
49
    protected $_encryption_key;
50
51
    /**
52
     * @var boolean $_use_openssl_encrypt
53
     */
54
    protected $_use_openssl_encrypt = false;
55
56
    /**
57
     * @var boolean $_use_mcrypt
58
     */
59
    protected $_use_mcrypt = false;
60
61
    /**
62
     * @var boolean $_use_base64_encode
63
     */
64
    protected $_use_base64_encode = false;
65
66
67
68
    /**
69
     * protected constructor to prevent direct creation
70
     */
71
    protected function __construct()
72
    {
73
        if (! defined('ESPRESSO_ENCRYPT')) {
74
            define('ESPRESSO_ENCRYPT', true);
75
        }
76
        if (function_exists('openssl_encrypt')) {
77
            $this->_use_openssl_encrypt = true;
78
        } else if (function_exists('mcrypt_encrypt')) {
79
            $this->_use_mcrypt = true;
80
        }
81
        if (function_exists('base64_encode')) {
82
            $this->_use_base64_encode = true;
83
        }
84
    }
85
86
87
88
    /**
89
     * singleton method used to instantiate class object
90
     *
91
     * @return EE_Encryption
92
     */
93
    public static function instance()
94
    {
95
        // check if class object is instantiated
96
        if (! self::$_instance instanceof EE_Encryption) {
97
            self::$_instance = new self();
98
        }
99
        return self::$_instance;
100
    }
101
102
103
104
    /**
105
     * get encryption key
106
     *
107
     * @return string
108
     */
109
    public function get_encryption_key()
110
    {
111
        // if encryption key has not been set
112
        if (empty($this->_encryption_key)) {
113
            // retrieve encryption_key from db
114
            $this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
115
            // WHAT?? No encryption_key in the db ??
116
            if ($this->_encryption_key === '') {
117
                // let's make one. And md5 it to make it just the right size for a key
118
                $new_key = md5($this->generate_random_string());
119
                // now save it to the db for later
120
                add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
121
                // here's the key - FINALLY !
122
                $this->_encryption_key = $new_key;
123
            }
124
        }
125
        return $this->_encryption_key;
126
    }
127
128
129
130
    /**
131
     * encrypts data
132
     *
133
     * @param string $text_string - the text to be encrypted
134
     * @return string
135
     * @throws RuntimeException
136
     */
137
    public function encrypt($text_string = '')
138
    {
139
        // you give me nothing??? GET OUT !
140
        if (empty($text_string)) {
141
            return $text_string;
142
        }
143
        if ($this->_use_openssl_encrypt) {
144
            $encrypted_text = $this->openssl_encrypt($text_string);
145
        } else {
146
            $encrypted_text = $this->acme_encrypt($text_string);
147
        }
148
        return $encrypted_text;
149
    }
150
151
152
153
    /**
154
     * decrypts data
155
     *
156
     * @param string $encrypted_text - the text to be decrypted
157
     * @return string
158
     * @throws RuntimeException
159
     */
160
    public function decrypt($encrypted_text = '')
161
    {
162
        // you give me nothing??? GET OUT !
163
        if (empty($encrypted_text)) {
164
            return $encrypted_text;
165
        }
166
        // if PHP's mcrypt functions are installed then we'll use them
167
        if ($this->_use_openssl_encrypt) {
168
            $decrypted_text = $this->openssl_decrypt($encrypted_text);
169
        } else if ($this->_use_mcrypt) {
170
            $decrypted_text = $this->m_decrypt($encrypted_text);
0 ignored issues
show
Deprecated Code introduced by
The method EE_Encryption::m_decrypt() has been deprecated with message: 4.9.39

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
171
        } else {
172
            $decrypted_text = $this->acme_decrypt($encrypted_text);
173
        }
174
        return $decrypted_text;
175
    }
176
177
178
179
    /**
180
     * encodes string with PHP's base64 encoding
181
     *
182
     * @see http://php.net/manual/en/function.base64-encode.php
183
     * @param string $text_string the text to be encoded
184
     * @return string
185
     */
186
    public function base64_string_encode($text_string = '')
187
    {
188
        // you give me nothing??? GET OUT !
189
        if (empty($text_string) || ! $this->_use_base64_encode) {
190
            return $text_string;
191
        }
192
        // encode
193
        return base64_encode($text_string);
194
    }
195
196
197
198
    /**
199
     * decodes string that has been encoded with PHP's base64 encoding
200
     *
201
     * @see http://php.net/manual/en/function.base64-encode.php
202
     * @param string $encoded_string the text to be decoded
203
     * @return string
204
     */
205
    public function base64_string_decode($encoded_string = '')
206
    {
207
        // you give me nothing??? GET OUT !
208
        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
209
            return $encoded_string;
210
        }
211
        // decode
212
        return base64_decode($encoded_string);
213
    }
214
215
216
217
    /**
218
     * encodes  url string with PHP's base64 encoding
219
     *
220
     * @see http://php.net/manual/en/function.base64-encode.php
221
     * @param string $text_string the text to be encoded
222
     * @return string
223
     */
224
    public function base64_url_encode($text_string = '')
225
    {
226
        // you give me nothing??? GET OUT !
227
        if (empty($text_string) || ! $this->_use_base64_encode) {
228
            return $text_string;
229
        }
230
        // encode
231
        $encoded_string = base64_encode($text_string);
232
        // remove chars to make encoding more URL friendly
233
        return strtr($encoded_string, '+/=', '-_,');
234
    }
235
236
237
238
    /**
239
     * decodes  url string that has been encoded with PHP's base64 encoding
240
     *
241
     * @see http://php.net/manual/en/function.base64-encode.php
242
     * @param string $encoded_string the text to be decoded
243
     * @return string
244
     */
245
    public function base64_url_decode($encoded_string = '')
246
    {
247
        // you give me nothing??? GET OUT !
248
        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
249
            return $encoded_string;
250
        }
251
        // replace previously removed characters
252
        $encoded_string = strtr($encoded_string, '-_,', '+/=');
253
        // decode
254
        return base64_decode($encoded_string);
255
    }
256
257
258
259
    /**
260
     * encrypts data using PHP's openssl functions
261
     *
262
     * @param string $text_string the text to be encrypted
263
     * @return string
264
     * @throws RuntimeException
265
     */
266
    protected function openssl_encrypt($text_string = '')
267
    {
268
        // you give me nothing??? GET OUT !
269
        if (empty($text_string)) {
270
            return $text_string;
271
        }
272
        // get initialization vector size
273
        $iv_size = openssl_cipher_iv_length(EE_Encryption::OPENSSL_CIPHER_METHOD);
274
        // generate initialization vector
275
        $iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
276
        if ($iv === false || $is_strong === false) {
277
            throw new RuntimeException(
278
                esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
279
            );
280
        }
281
        // encrypt it
282
        $encrypted_text = openssl_encrypt(
283
            $text_string,
284
            EE_Encryption::OPENSSL_CIPHER_METHOD,
285
            openssl_digest($this->get_encryption_key(), EE_Encryption::OPENSSL_DIGEST_METHOD),
286
            0,
287
            $iv
288
        );
289
        // append the initialization vector
290
        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
291
        // trim and maybe encode
292
        return $this->_use_base64_encode
293
            ? trim(base64_encode($encrypted_text))
294
            : trim($encrypted_text);
295
    }
296
297
298
299
    /**
300
     * decrypts data that has been encrypted with PHP's openssl functions
301
     *
302
     * @param string $encrypted_text the text to be decrypted
303
     * @return string
304
     * @throws RuntimeException
305
     */
306
    protected function openssl_decrypt($encrypted_text = '')
307
    {
308
        // you give me nothing??? GET OUT !
309
        if (empty($encrypted_text)) {
310
            return $encrypted_text;
311
        }
312
        // decode
313
        $encrypted_text = $this->valid_base_64($encrypted_text)
314
            ? base64_decode($encrypted_text)
315
            : $encrypted_text;
316
        $encrypted_components = explode(
317
            EE_Encryption::OPENSSL_IV_DELIMITER,
318
            $encrypted_text,
319
            2
320
        );
321
        // check that iv exists, and if not, maybe text was encoded using mcrypt?
322
        if (! isset($encrypted_components[1]) && $this->_use_mcrypt) {
323
            return $this->m_decrypt($encrypted_text);
0 ignored issues
show
Deprecated Code introduced by
The method EE_Encryption::m_decrypt() has been deprecated with message: 4.9.39

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
324
        }
325
        // decrypt it
326
        $decrypted_text = openssl_decrypt(
327
            $encrypted_components[0],
328
            EE_Encryption::OPENSSL_CIPHER_METHOD,
329
            openssl_digest($this->get_encryption_key(), EE_Encryption::OPENSSL_DIGEST_METHOD),
330
            0,
331
            $encrypted_components[1]
332
        );
333
        $decrypted_text = trim($decrypted_text);
334
        return $decrypted_text;
335
    }
336
337
338
339
    /**
340
     * encrypts data for acme servers that didn't bother to install PHP mcrypt
341
     *
342
     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
343
     * @param string $text_string the text to be decrypted
344
     * @return string
345
     */
346
    protected function acme_encrypt($text_string = '')
347
    {
348
        // you give me nothing??? GET OUT !
349
        if (empty($text_string)) {
350
            return $text_string;
351
        }
352
        $key_bits = str_split(
353
            str_pad('', strlen($text_string), $this->get_encryption_key(), STR_PAD_RIGHT)
354
        );
355
        $string_bits = str_split($text_string);
356 View Code Duplication
        foreach ($string_bits as $k => $v) {
357
            $temp = ord($v) + ord($key_bits[$k]);
358
            $string_bits[$k] = chr($temp > 255 ? ($temp - 256) : $temp);
359
        }
360
        return $this->_use_base64_encode
361
            ? base64_encode(implode('', $string_bits))
362
            : implode('', $string_bits);
363
    }
364
365
366
367
    /**
368
     * decrypts data for acme servers that didn't bother to install PHP mcrypt
369
     *
370
     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
371
     * @param string $encrypted_text the text to be decrypted
372
     * @return string
373
     */
374
    protected function acme_decrypt($encrypted_text = '')
375
    {
376
        // you give me nothing??? GET OUT !
377
        if (empty($encrypted_text)) {
378
            return $encrypted_text;
379
        }
380
        // decode the data ?
381
        $encrypted_text = $this->valid_base_64($encrypted_text)
382
            ? base64_decode($encrypted_text)
383
            : $encrypted_text;
384
        $key_bits = str_split(
385
            str_pad('', strlen($encrypted_text), $this->get_encryption_key(), STR_PAD_RIGHT)
386
        );
387
        $string_bits = str_split($encrypted_text);
388 View Code Duplication
        foreach ($string_bits as $k => $v) {
389
            $temp = ord($v) - ord($key_bits[$k]);
390
            $string_bits[$k] = chr($temp < 0 ? ($temp + 256) : $temp);
391
        }
392
        return implode('', $string_bits);
393
    }
394
395
396
397
    /**
398
     * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
399
     * @param $string
400
     * @return bool
401
     */
402
    protected function valid_base_64($string)
403
    {
404
        // ensure data is a string
405
        if (! is_string($string) || ! $this->_use_base64_encode) {
406
            return false;
407
        }
408
        $decoded = base64_decode($string, true);
409
        // Check if there is no invalid character in string
410
        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
411
            return false;
412
        }
413
        // Decode the string in strict mode and send the response
414
        if (! base64_decode($string, true)) {
415
            return false;
416
        }
417
        // Encode and compare it to original one
418
        return base64_encode($decoded) === $string;
419
    }
420
421
422
423
    /**
424
     * generate random string
425
     *
426
     * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
427
     * @param int $length number of characters for random string
428
     * @return string
429
     */
430
    public function generate_random_string($length = 40)
431
    {
432
        $iterations = ceil($length / 40);
433
        $random_string = '';
434
        for ($i = 0; $i < $iterations; $i++) {
435
            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
436
        }
437
        $random_string = substr($random_string, 0, $length);
438
        return $random_string;
439
    }
440
441
442
443
    /**
444
     * encrypts data using PHP's mcrypt functions
445
     *
446
     * @deprecated 4.9.39
447
     * @param string $text_string
448
     * @internal   param $string - the text to be encrypted
449
     * @return string
450
     * @throws RuntimeException
451
     */
452
    protected function m_encrypt($text_string = '')
453
    {
454
        // you give me nothing??? GET OUT !
455
        if (empty($text_string)) {
456
            return $text_string;
457
        }
458
        // get the initialization vector size
459
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
460
        // initialization vector
461
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
462
        if ($iv === false) {
463
            throw new RuntimeException(
464
                esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
465
            );
466
        }
467
        // encrypt it
468
        $encrypted_text = mcrypt_encrypt(
469
            MCRYPT_RIJNDAEL_256,
470
            $this->get_encryption_key(),
471
            $text_string,
472
            MCRYPT_MODE_ECB,
473
            $iv
474
        );
475
        // trim and maybe encode
476
        return $this->_use_base64_encode
477
            ? trim(base64_encode($encrypted_text))
478
            : trim($encrypted_text);
479
    }
480
481
482
483
    /**
484
     * decrypts data that has been encrypted with PHP's mcrypt functions
485
     *
486
     * @deprecated 4.9.39
487
     * @param string $encrypted_text the text to be decrypted
488
     * @return string
489
     * @throws RuntimeException
490
     */
491
    protected function m_decrypt($encrypted_text = '')
492
    {
493
        // you give me nothing??? GET OUT !
494
        if (empty($encrypted_text)) {
495
            return $encrypted_text;
496
        }
497
        // decode
498
        $encrypted_text = $this->valid_base_64($encrypted_text)
499
            ? base64_decode($encrypted_text)
500
            : $encrypted_text;
501
        // get the initialization vector size
502
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
503
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
504
        if ($iv === false) {
505
            throw new RuntimeException(
506
                esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
507
            );
508
        }
509
        // decrypt it
510
        $decrypted_text = mcrypt_decrypt(
511
            MCRYPT_RIJNDAEL_256,
512
            $this->get_encryption_key(),
513
            $encrypted_text,
514
            MCRYPT_MODE_ECB,
515
            $iv
516
        );
517
        $decrypted_text = trim($decrypted_text);
518
        return $decrypted_text;
519
    }
520
521
}
522
/* End of file EE_Encryption.class.php */
523
/* Location: /includes/core/EE_Encryption.core.php */