Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
103 - 1
<?php
2
 
3
/**
4
 * Pure-PHP implementation of RC2.
5
 *
6
 * Uses mcrypt, if available, and an internal implementation, otherwise.
7
 *
8
 * PHP version 5
9
 *
10
 * Useful resources are as follows:
11
 *
12
 *  - {@link http://tools.ietf.org/html/rfc2268}
13
 *
14
 * Here's a short example of how to use this library:
15
 * <code>
16
 * <?php
17
 *    include 'vendor/autoload.php';
18
 *
19
 *    $rc2 = new \phpseclib\Crypt\RC2();
20
 *
21
 *    $rc2->setKey('abcdefgh');
22
 *
23
 *    $plaintext = str_repeat('a', 1024);
24
 *
25
 *    echo $rc2->decrypt($rc2->encrypt($plaintext));
26
 * ?>
27
 * </code>
28
 *
29
 * @category Crypt
30
 * @package  RC2
31
 * @author   Patrick Monnerat <pm@datasphere.ch>
32
 * @license  http://www.opensource.org/licenses/mit-license.html  MIT License
33
 * @link     http://phpseclib.sourceforge.net
34
 */
35
 
36
namespace phpseclib\Crypt;
37
 
38
/**
39
 * Pure-PHP implementation of RC2.
40
 *
41
 * @package RC2
42
 * @access  public
43
 */
44
class RC2 extends Base
45
{
46
    /**
47
     * Block Length of the cipher
48
     *
49
     * @see \phpseclib\Crypt\Base::block_size
50
     * @var int
51
     * @access private
52
     */
53
    var $block_size = 8;
54
 
55
    /**
56
     * The Key
57
     *
58
     * @see \phpseclib\Crypt\Base::key
59
     * @see self::setKey()
60
     * @var string
61
     * @access private
62
     */
63
    var $key;
64
 
65
    /**
66
     * The Original (unpadded) Key
67
     *
68
     * @see \phpseclib\Crypt\Base::key
69
     * @see self::setKey()
70
     * @see self::encrypt()
71
     * @see self::decrypt()
72
     * @var string
73
     * @access private
74
     */
75
    var $orig_key;
76
 
77
    /**
78
     * Don't truncate / null pad key
79
     *
80
     * @see \phpseclib\Crypt\Base::_clearBuffers()
81
     * @var bool
82
     * @access private
83
     */
84
    var $skip_key_adjustment = true;
85
 
86
    /**
87
     * Key Length (in bytes)
88
     *
89
     * @see \phpseclib\Crypt\RC2::setKeyLength()
90
     * @var int
91
     * @access private
92
     */
93
    var $key_length = 16; // = 128 bits
94
 
95
    /**
96
     * The mcrypt specific name of the cipher
97
     *
98
     * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
99
     * @var string
100
     * @access private
101
     */
102
    var $cipher_name_mcrypt = 'rc2';
103
 
104
    /**
105
     * Optimizing value while CFB-encrypting
106
     *
107
     * @see \phpseclib\Crypt\Base::cfb_init_len
108
     * @var int
109
     * @access private
110
     */
111
    var $cfb_init_len = 500;
112
 
113
    /**
114
     * The key length in bits.
115
     *
116
     * @see self::setKeyLength()
117
     * @see self::setKey()
118
     * @var int
119
     * @access private
120
     * @internal Should be in range [1..1024].
121
     * @internal Changing this value after setting the key has no effect.
122
     */
123
    var $default_key_length = 1024;
124
 
125
    /**
126
     * The key length in bits.
127
     *
128
     * @see self::isValidEnine()
129
     * @see self::setKey()
130
     * @var int
131
     * @access private
132
     * @internal Should be in range [1..1024].
133
     */
134
    var $current_key_length;
135
 
136
    /**
137
     * The Key Schedule
138
     *
139
     * @see self::_setupKey()
140
     * @var array
141
     * @access private
142
     */
143
    var $keys;
144
 
145
    /**
146
     * Key expansion randomization table.
147
     * Twice the same 256-value sequence to save a modulus in key expansion.
148
     *
149
     * @see self::setKey()
150
     * @var array
151
     * @access private
152
     */
153
    var $pitable = array(
154
        0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
155
        0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
156
        0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
157
        0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
158
        0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
159
        0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
160
        0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
161
        0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
162
        0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
163
        0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
164
        0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
165
        0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
166
        0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
167
        0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
168
        0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
169
        0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
170
        0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
171
        0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
172
        0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
173
        0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
174
        0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
175
        0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
176
        0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
177
        0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
178
        0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
179
        0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
180
        0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
181
        0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
182
        0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
183
        0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
184
        0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
185
        0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
186
        0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
187
        0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
188
        0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
189
        0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
190
        0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
191
        0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
192
        0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
193
        0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
194
        0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
195
        0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
196
        0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
197
        0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
198
        0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
199
        0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
200
        0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
201
        0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
202
        0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
203
        0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
204
        0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
205
        0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
206
        0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
207
        0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
208
        0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
209
        0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
210
        0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
211
        0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
212
        0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
213
        0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
214
        0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
215
        0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
216
        0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
217
        0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
218
    );
219
 
220
    /**
221
     * Inverse key expansion randomization table.
222
     *
223
     * @see self::setKey()
224
     * @var array
225
     * @access private
226
     */
227
    var $invpitable = array(
228
        0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
229
        0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
230
        0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
231
        0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
232
        0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
233
        0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
234
        0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
235
        0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
236
        0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
237
        0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
238
        0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
239
        0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
240
        0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
241
        0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
242
        0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
243
        0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
244
        0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
245
        0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
246
        0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
247
        0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
248
        0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
249
        0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
250
        0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
251
        0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
252
        0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
253
        0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
254
        0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
255
        0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
256
        0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
257
        0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
258
        0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
259
        0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
260
    );
261
 
262
    /**
263
     * Test for engine validity
264
     *
265
     * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
266
     *
267
     * @see \phpseclib\Crypt\Base::__construct()
268
     * @param int $engine
269
     * @access public
270
     * @return bool
271
     */
272
    function isValidEngine($engine)
273
    {
274
        switch ($engine) {
275
            case self::ENGINE_OPENSSL:
276
                if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
277
                    return false;
278
                }
279
                $this->cipher_name_openssl_ecb = 'rc2-ecb';
280
                $this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
281
        }
282
 
283
        return parent::isValidEngine($engine);
284
    }
285
 
286
    /**
287
     * Sets the key length.
288
     *
289
     * Valid key lengths are 8 to 1024.
290
     * Calling this function after setting the key has no effect until the next
291
     *  \phpseclib\Crypt\RC2::setKey() call.
292
     *
293
     * @access public
294
     * @param int $length in bits
295
     */
296
    function setKeyLength($length)
297
    {
298
        if ($length < 8) {
299
            $this->default_key_length = 8;
300
        } elseif ($length > 1024) {
301
            $this->default_key_length = 128;
302
        } else {
303
            $this->default_key_length = $length;
304
        }
305
        $this->current_key_length = $this->default_key_length;
306
 
307
        parent::setKeyLength($length);
308
    }
309
 
310
    /**
311
     * Returns the current key length
312
     *
313
     * @access public
314
     * @return int
315
     */
316
    function getKeyLength()
317
    {
318
        return $this->current_key_length;
319
    }
320
 
321
    /**
322
     * Sets the key.
323
     *
324
     * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
325
     * strlen($key) <= 128), however, we only use the first 128 bytes if $key
326
     * has more then 128 bytes in it, and set $key to a single null byte if
327
     * it is empty.
328
     *
329
     * If the key is not explicitly set, it'll be assumed to be a single
330
     * null byte.
331
     *
332
     * @see \phpseclib\Crypt\Base::setKey()
333
     * @access public
334
     * @param string $key
335
     * @param int $t1 optional Effective key length in bits.
336
     */
337
    function setKey($key, $t1 = 0)
338
    {
339
        $this->orig_key = $key;
340
 
341
        if ($t1 <= 0) {
342
            $t1 = $this->default_key_length;
343
        } elseif ($t1 > 1024) {
344
            $t1 = 1024;
345
        }
346
        $this->current_key_length = $t1;
347
        // Key byte count should be 1..128.
348
        $key = strlen($key) ? substr($key, 0, 128) : "\x00";
349
        $t = strlen($key);
350
 
351
        // The mcrypt RC2 implementation only supports effective key length
352
        // of 1024 bits. It is however possible to handle effective key
353
        // lengths in range 1..1024 by expanding the key and applying
354
        // inverse pitable mapping to the first byte before submitting it
355
        // to mcrypt.
356
 
357
        // Key expansion.
358
        $l = array_values(unpack('C*', $key));
359
        $t8 = ($t1 + 7) >> 3;
360
        $tm = 0xFF >> (8 * $t8 - $t1);
361
 
362
        // Expand key.
363
        $pitable = $this->pitable;
364
        for ($i = $t; $i < 128; $i++) {
365
            $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
366
        }
367
        $i = 128 - $t8;
368
        $l[$i] = $pitable[$l[$i] & $tm];
369
        while ($i--) {
370
            $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
371
        }
372
 
373
        // Prepare the key for mcrypt.
374
        $l[0] = $this->invpitable[$l[0]];
375
        array_unshift($l, 'C*');
376
 
377
        parent::setKey(call_user_func_array('pack', $l));
378
    }
379
 
380
    /**
381
     * Encrypts a message.
382
     *
383
     * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
384
     *
385
     * @see self::decrypt()
386
     * @access public
387
     * @param string $plaintext
388
     * @return string $ciphertext
389
     */
390
    function encrypt($plaintext)
391
    {
392
        if ($this->engine == self::ENGINE_OPENSSL) {
393
            $temp = $this->key;
394
            $this->key = $this->orig_key;
395
            $result = parent::encrypt($plaintext);
396
            $this->key = $temp;
397
            return $result;
398
        }
399
 
400
        return parent::encrypt($plaintext);
401
    }
402
 
403
    /**
404
     * Decrypts a message.
405
     *
406
     * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
407
     *
408
     * @see self::encrypt()
409
     * @access public
410
     * @param string $ciphertext
411
     * @return string $plaintext
412
     */
413
    function decrypt($ciphertext)
414
    {
415
        if ($this->engine == self::ENGINE_OPENSSL) {
416
            $temp = $this->key;
417
            $this->key = $this->orig_key;
418
            $result = parent::decrypt($ciphertext);
419
            $this->key = $temp;
420
            return $result;
421
        }
422
 
423
        return parent::decrypt($ciphertext);
424
    }
425
 
426
    /**
427
     * Encrypts a block
428
     *
429
     * @see \phpseclib\Crypt\Base::_encryptBlock()
430
     * @see \phpseclib\Crypt\Base::encrypt()
431
     * @access private
432
     * @param string $in
433
     * @return string
434
     */
435
    function _encryptBlock($in)
436
    {
437
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
438
        $keys = $this->keys;
439
        $limit = 20;
440
        $actions = array($limit => 44, 44 => 64);
441
        $j = 0;
442
 
443
        for (;;) {
444
            // Mixing round.
445
            $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
446
            $r0 |= $r0 >> 16;
447
            $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
448
            $r1 |= $r1 >> 16;
449
            $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
450
            $r2 |= $r2 >> 16;
451
            $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
452
            $r3 |= $r3 >> 16;
453
 
454
            if ($j === $limit) {
455
                if ($limit === 64) {
456
                    break;
457
                }
458
 
459
                // Mashing round.
460
                $r0 += $keys[$r3 & 0x3F];
461
                $r1 += $keys[$r0 & 0x3F];
462
                $r2 += $keys[$r1 & 0x3F];
463
                $r3 += $keys[$r2 & 0x3F];
464
                $limit = $actions[$limit];
465
            }
466
        }
467
 
468
        return pack('vvvv', $r0, $r1, $r2, $r3);
469
    }
470
 
471
    /**
472
     * Decrypts a block
473
     *
474
     * @see \phpseclib\Crypt\Base::_decryptBlock()
475
     * @see \phpseclib\Crypt\Base::decrypt()
476
     * @access private
477
     * @param string $in
478
     * @return string
479
     */
480
    function _decryptBlock($in)
481
    {
482
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
483
        $keys = $this->keys;
484
        $limit = 44;
485
        $actions = array($limit => 20, 20 => 0);
486
        $j = 64;
487
 
488
        for (;;) {
489
            // R-mixing round.
490
            $r3 = ($r3 | ($r3 << 16)) >> 5;
491
            $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
492
            $r2 = ($r2 | ($r2 << 16)) >> 3;
493
            $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
494
            $r1 = ($r1 | ($r1 << 16)) >> 2;
495
            $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
496
            $r0 = ($r0 | ($r0 << 16)) >> 1;
497
            $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
498
 
499
            if ($j === $limit) {
500
                if ($limit === 0) {
501
                    break;
502
                }
503
 
504
                // R-mashing round.
505
                $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
506
                $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
507
                $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
508
                $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
509
                $limit = $actions[$limit];
510
            }
511
        }
512
 
513
        return pack('vvvv', $r0, $r1, $r2, $r3);
514
    }
515
 
516
    /**
517
     * Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
518
     *
519
     * @see \phpseclib\Crypt\Base::_setupMcrypt()
520
     * @access private
521
     */
522
    function _setupMcrypt()
523
    {
524
        if (!isset($this->key)) {
525
            $this->setKey('');
526
        }
527
 
528
        parent::_setupMcrypt();
529
    }
530
 
531
    /**
532
     * Creates the key schedule
533
     *
534
     * @see \phpseclib\Crypt\Base::_setupKey()
535
     * @access private
536
     */
537
    function _setupKey()
538
    {
539
        if (!isset($this->key)) {
540
            $this->setKey('');
541
        }
542
 
543
        // Key has already been expanded in \phpseclib\Crypt\RC2::setKey():
544
        // Only the first value must be altered.
545
        $l = unpack('Ca/Cb/v*', $this->key);
546
        array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
547
        unset($l['a']);
548
        unset($l['b']);
549
        $this->keys = $l;
550
    }
551
 
552
    /**
553
     * Setup the performance-optimized function for de/encrypt()
554
     *
555
     * @see \phpseclib\Crypt\Base::_setupInlineCrypt()
556
     * @access private
557
     */
558
    function _setupInlineCrypt()
559
    {
560
        $lambda_functions =& self::_getLambdaFunctions();
561
 
562
        // The first 10 generated $lambda_functions will use the $keys hardcoded as integers
563
        // for the mixing rounds, for better inline crypt performance [~20% faster].
564
        // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
565
        // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
566
        $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
567
 
568
        // Generation of a unique hash for our generated code
569
        $code_hash = "Crypt_RC2, {$this->mode}";
570
        if ($gen_hi_opt_code) {
571
            $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
572
        }
573
 
574
        // Is there a re-usable $lambda_functions in there?
575
        // If not, we have to create it.
576
        if (!isset($lambda_functions[$code_hash])) {
577
            // Init code for both, encrypt and decrypt.
578
            $init_crypt = '$keys = $self->keys;';
579
 
580
            switch (true) {
581
                case $gen_hi_opt_code:
582
                    $keys = $this->keys;
583
                default:
584
                    $keys = array();
585
                    foreach ($this->keys as $k => $v) {
586
                        $keys[$k] = '$keys[' . $k . ']';
587
                    }
588
            }
589
 
590
            // $in is the current 8 bytes block which has to be en/decrypt
591
            $encrypt_block = $decrypt_block = '
592
                $in = unpack("v4", $in);
593
                $r0 = $in[1];
594
                $r1 = $in[2];
595
                $r2 = $in[3];
596
                $r3 = $in[4];
597
            ';
598
 
599
            // Create code for encryption.
600
            $limit = 20;
601
            $actions = array($limit => 44, 44 => 64);
602
            $j = 0;
603
 
604
            for (;;) {
605
                // Mixing round.
606
                $encrypt_block .= '
607
                    $r0 = (($r0 + ' . $keys[$j++] . ' +
608
                           ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
609
                    $r0 |= $r0 >> 16;
610
                    $r1 = (($r1 + ' . $keys[$j++] . ' +
611
                           ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
612
                    $r1 |= $r1 >> 16;
613
                    $r2 = (($r2 + ' . $keys[$j++] . ' +
614
                           ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
615
                    $r2 |= $r2 >> 16;
616
                    $r3 = (($r3 + ' . $keys[$j++] . ' +
617
                           ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
618
                    $r3 |= $r3 >> 16;';
619
 
620
                if ($j === $limit) {
621
                    if ($limit === 64) {
622
                        break;
623
                    }
624
 
625
                    // Mashing round.
626
                    $encrypt_block .= '
627
                        $r0 += $keys[$r3 & 0x3F];
628
                        $r1 += $keys[$r0 & 0x3F];
629
                        $r2 += $keys[$r1 & 0x3F];
630
                        $r3 += $keys[$r2 & 0x3F];';
631
                    $limit = $actions[$limit];
632
                }
633
            }
634
 
635
            $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
636
 
637
            // Create code for decryption.
638
            $limit = 44;
639
            $actions = array($limit => 20, 20 => 0);
640
            $j = 64;
641
 
642
            for (;;) {
643
                // R-mixing round.
644
                $decrypt_block .= '
645
                    $r3 = ($r3 | ($r3 << 16)) >> 5;
646
                    $r3 = ($r3 - ' . $keys[--$j] . ' -
647
                           ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
648
                    $r2 = ($r2 | ($r2 << 16)) >> 3;
649
                    $r2 = ($r2 - ' . $keys[--$j] . ' -
650
                           ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
651
                    $r1 = ($r1 | ($r1 << 16)) >> 2;
652
                    $r1 = ($r1 - ' . $keys[--$j] . ' -
653
                           ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
654
                    $r0 = ($r0 | ($r0 << 16)) >> 1;
655
                    $r0 = ($r0 - ' . $keys[--$j] . ' -
656
                           ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
657
 
658
                if ($j === $limit) {
659
                    if ($limit === 0) {
660
                        break;
661
                    }
662
 
663
                    // R-mashing round.
664
                    $decrypt_block .= '
665
                        $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
666
                        $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
667
                        $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
668
                        $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
669
                    $limit = $actions[$limit];
670
                }
671
            }
672
 
673
            $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
674
 
675
            // Creates the inline-crypt function
676
            $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
677
                array(
678
                   'init_crypt'    => $init_crypt,
679
                   'encrypt_block' => $encrypt_block,
680
                   'decrypt_block' => $decrypt_block
681
                )
682
            );
683
        }
684
 
685
        // Set the inline-crypt function as callback in: $this->inline_crypt
686
        $this->inline_crypt = $lambda_functions[$code_hash];
687
    }
688
}