PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt / RC2.php
backup / src / JetBackup / 3rdparty / phpseclib3 / Crypt Last commit date
Common 1 year ago DH 1 year ago DSA 1 year ago EC 1 year ago RSA 1 year ago .htaccess 1 year ago AES.php 1 year ago Blowfish.php 1 year ago ChaCha20.php 1 year ago DES.php 1 year ago DH.php 1 year ago DSA.php 1 year ago EC.php 1 year ago Hash.php 1 year ago PublicKeyLoader.php 1 year ago RC2.php 1 year ago RC4.php 1 year ago RSA.php 1 year ago Random.php 1 year ago Rijndael.php 1 year ago Salsa20.php 1 year ago TripleDES.php 1 year ago Twofish.php 1 year ago index.html 1 year ago web.config 1 year ago
RC2.php
615 lines
1 <?php
2
3 /**
4 * Pure-PHP implementation of RC2.
5 *
6 * Uses OpenSSL, if available/possible, 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 \phpseclib3\Crypt\RC2('ctr');
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 * @author Patrick Monnerat <pm@datasphere.ch>
30 * @license http://www.opensource.org/licenses/mit-license.html MIT License
31 * @link http://phpseclib.sourceforge.net
32 */
33
34 declare(strict_types=1);
35
36 namespace phpseclib3\Crypt;
37
38 use phpseclib3\Crypt\Common\BlockCipher;
39 use phpseclib3\Exception\BadModeException;
40 use phpseclib3\Exception\InvalidArgumentException;
41 use phpseclib3\Exception\LengthException;
42
43 /**
44 * Pure-PHP implementation of RC2.
45 */
46 class RC2 extends BlockCipher
47 {
48 /**
49 * Block Length of the cipher
50 *
51 * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
52 * @var int
53 */
54 protected $block_size = 8;
55
56 /**
57 * The Key
58 *
59 * @see \phpseclib3\Crypt\Common\SymmetricKey::key
60 * @see self::setKey()
61 * @var string
62 */
63 protected $key;
64
65 /**
66 * The Original (unpadded) Key
67 *
68 * @see \phpseclib3\Crypt\Common\SymmetricKey::key
69 * @see self::setKey()
70 * @see self::encrypt()
71 * @see self::decrypt()
72 * @var string
73 */
74 private $orig_key;
75
76 /**
77 * Key Length (in bytes)
78 *
79 * @see \phpseclib3\Crypt\RC2::setKeyLength()
80 * @var int
81 */
82 protected $key_length = 16; // = 128 bits
83
84 /**
85 * The key length in bits.
86 *
87 * {@internal Should be in range [1..1024].}
88 *
89 * {@internal Changing this value after setting the key has no effect.}
90 *
91 * @see self::setKeyLength()
92 * @see self::setKey()
93 * @var int
94 */
95 private $default_key_length = 1024;
96
97 /**
98 * The key length in bits.
99 *
100 * {@internal Should be in range [1..1024].}
101 *
102 * @see self::isValidEnine()
103 * @see self::setKey()
104 * @var int
105 */
106 private $current_key_length;
107
108 /**
109 * The Key Schedule
110 *
111 * @see self::setupKey()
112 * @var array
113 */
114 private $keys;
115
116 /**
117 * Key expansion randomization table.
118 * Twice the same 256-value sequence to save a modulus in key expansion.
119 *
120 * @see self::setKey()
121 * @var array
122 */
123 private static $pitable = [
124 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
125 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
126 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
127 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
128 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
129 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
130 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
131 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
132 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
133 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
134 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
135 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
136 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
137 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
138 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
139 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
140 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
141 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
142 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
143 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
144 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
145 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
146 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
147 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
148 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
149 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
150 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
151 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
152 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
153 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
154 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
155 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
156 0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
157 0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
158 0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
159 0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
160 0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
161 0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
162 0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
163 0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
164 0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
165 0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
166 0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
167 0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
168 0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
169 0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
170 0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
171 0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
172 0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
173 0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
174 0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
175 0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
176 0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
177 0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
178 0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
179 0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
180 0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
181 0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
182 0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
183 0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
184 0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
185 0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
186 0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
187 0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
188 ];
189
190 /**
191 * Inverse key expansion randomization table.
192 *
193 * @see self::setKey()
194 * @var array
195 */
196 private static $invpitable = [
197 0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
198 0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
199 0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
200 0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
201 0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
202 0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
203 0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
204 0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
205 0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
206 0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
207 0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
208 0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
209 0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
210 0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
211 0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
212 0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
213 0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
214 0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
215 0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
216 0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
217 0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
218 0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
219 0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
220 0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
221 0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
222 0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
223 0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
224 0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
225 0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
226 0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
227 0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
228 0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6,
229 ];
230
231 /**
232 * Default Constructor.
233 *
234 * @throws InvalidArgumentException if an invalid / unsupported mode is provided
235 */
236 public function __construct(string $mode)
237 {
238 parent::__construct($mode);
239
240 if ($this->mode == self::MODE_STREAM) {
241 throw new BadModeException('Block ciphers cannot be ran in stream mode');
242 }
243 }
244
245 /**
246 * Test for engine validity
247 *
248 * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
249 *
250 * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
251 */
252 protected function isValidEngineHelper(int $engine): bool
253 {
254 switch ($engine) {
255 case self::ENGINE_OPENSSL:
256 if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
257 return false;
258 }
259 // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1
260 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider"
261 // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not
262 if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) {
263 return false;
264 }
265 $this->cipher_name_openssl_ecb = 'rc2-ecb';
266 $this->cipher_name_openssl = 'rc2-' . $this->openssl_translate_mode();
267 }
268
269 return parent::isValidEngineHelper($engine);
270 }
271
272 /**
273 * Sets the key length.
274 *
275 * Valid key lengths are 8 to 1024.
276 * Calling this function after setting the key has no effect until the next
277 * \phpseclib3\Crypt\RC2::setKey() call.
278 *
279 * @param int $length in bits
280 * @throws LengthException if the key length isn't supported
281 */
282 public function setKeyLength(int $length): void
283 {
284 if ($length < 8 || $length > 1024) {
285 throw new LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
286 }
287
288 $this->default_key_length = $this->current_key_length = $length;
289 $this->explicit_key_length = $length >> 3;
290 }
291
292 /**
293 * Returns the current key length
294 */
295 public function getKeyLength(): int
296 {
297 return $this->current_key_length;
298 }
299
300 /**
301 * Sets the key.
302 *
303 * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
304 * strlen($key) <= 128), however, we only use the first 128 bytes if $key
305 * has more then 128 bytes in it, and set $key to a single null byte if
306 * it is empty.
307 *
308 * @throws LengthException if the key length isn't supported
309 * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
310 */
311 public function setKey(string $key, ?int $t1 = null): void
312 {
313 $this->orig_key = $key;
314
315 if ($t1 === null) {
316 $t1 = $this->default_key_length;
317 }
318
319 if ($t1 < 1 || $t1 > 1024) {
320 throw new LengthException('Key size of ' . $t1 . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
321 }
322
323 $this->current_key_length = $t1;
324 if (strlen($key) < 1 || strlen($key) > 128) {
325 throw new LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes between 8 and 1024 bits, inclusive, are supported');
326 }
327
328 $t = strlen($key);
329
330 // The mcrypt RC2 implementation only supports effective key length
331 // of 1024 bits. It is however possible to handle effective key
332 // lengths in range 1..1024 by expanding the key and applying
333 // inverse pitable mapping to the first byte before submitting it
334 // to mcrypt.
335
336 // Key expansion.
337 $l = array_values(unpack('C*', $key));
338 $t8 = ($t1 + 7) >> 3;
339 $tm = 0xFF >> (8 * $t8 - $t1);
340
341 // Expand key.
342 $pitable = self::$pitable;
343 for ($i = $t; $i < 128; $i++) {
344 $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
345 }
346 $i = 128 - $t8;
347 $l[$i] = $pitable[$l[$i] & $tm];
348 while ($i--) {
349 $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
350 }
351
352 // Prepare the key for mcrypt.
353 $l[0] = self::$invpitable[$l[0]];
354 array_unshift($l, 'C*');
355
356 $this->key = pack(...$l);
357 $this->key_length = strlen($this->key);
358 $this->changed = $this->nonIVChanged = true;
359 $this->setEngine();
360 }
361
362 /**
363 * Encrypts a message.
364 *
365 * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::encrypt, with some additional OpenSSL handling code
366 *
367 * @return string $ciphertext
368 * @see self::decrypt()
369 */
370 public function encrypt(string $plaintext): string
371 {
372 if ($this->engine == self::ENGINE_OPENSSL) {
373 $temp = $this->key;
374 $this->key = $this->orig_key;
375 $result = parent::encrypt($plaintext);
376 $this->key = $temp;
377 return $result;
378 }
379
380 return parent::encrypt($plaintext);
381 }
382
383 /**
384 * Decrypts a message.
385 *
386 * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::decrypt, with some additional OpenSSL handling code
387 *
388 * @return string $plaintext
389 * @see self::encrypt()
390 */
391 public function decrypt(string $ciphertext): string
392 {
393 if ($this->engine == self::ENGINE_OPENSSL) {
394 $temp = $this->key;
395 $this->key = $this->orig_key;
396 $result = parent::decrypt($ciphertext);
397 $this->key = $temp;
398 return $result;
399 }
400
401 return parent::decrypt($ciphertext);
402 }
403
404 /**
405 * Encrypts a block
406 *
407 * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
408 * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
409 */
410 protected function encryptBlock(string $in): string
411 {
412 [$r0, $r1, $r2, $r3] = array_values(unpack('v*', $in));
413 $keys = $this->keys;
414 $limit = 20;
415 $actions = [$limit => 44, 44 => 64];
416 $j = 0;
417
418 for (;;) {
419 // Mixing round.
420 $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
421 $r0 |= $r0 >> 16;
422 $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
423 $r1 |= $r1 >> 16;
424 $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
425 $r2 |= $r2 >> 16;
426 $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
427 $r3 |= $r3 >> 16;
428
429 if ($j === $limit) {
430 if ($limit === 64) {
431 break;
432 }
433
434 // Mashing round.
435 $r0 += $keys[$r3 & 0x3F];
436 $r1 += $keys[$r0 & 0x3F];
437 $r2 += $keys[$r1 & 0x3F];
438 $r3 += $keys[$r2 & 0x3F];
439 $limit = $actions[$limit];
440 }
441 }
442
443 return pack('vvvv', $r0, $r1, $r2, $r3);
444 }
445
446 /**
447 * Decrypts a block
448 *
449 * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
450 * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
451 */
452 protected function decryptBlock(string $in): string
453 {
454 [$r0, $r1, $r2, $r3] = array_values(unpack('v*', $in));
455 $keys = $this->keys;
456 $limit = 44;
457 $actions = [$limit => 20, 20 => 0];
458 $j = 64;
459
460 for (;;) {
461 // R-mixing round.
462 $r3 = ($r3 | ($r3 << 16)) >> 5;
463 $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
464 $r2 = ($r2 | ($r2 << 16)) >> 3;
465 $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
466 $r1 = ($r1 | ($r1 << 16)) >> 2;
467 $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
468 $r0 = ($r0 | ($r0 << 16)) >> 1;
469 $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
470
471 if ($j === $limit) {
472 if ($limit === 0) {
473 break;
474 }
475
476 // R-mashing round.
477 $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
478 $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
479 $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
480 $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
481 $limit = $actions[$limit];
482 }
483 }
484
485 return pack('vvvv', $r0, $r1, $r2, $r3);
486 }
487
488 /**
489 * Creates the key schedule
490 *
491 * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
492 */
493 protected function setupKey(): void
494 {
495 if (!isset($this->key)) {
496 $this->setKey('');
497 }
498
499 // Key has already been expanded in \phpseclib3\Crypt\RC2::setKey():
500 // Only the first value must be altered.
501 $l = unpack('Ca/Cb/v*', $this->key);
502 array_unshift($l, self::$pitable[$l['a']] | ($l['b'] << 8));
503 unset($l['a']);
504 unset($l['b']);
505 $this->keys = $l;
506 }
507
508 /**
509 * Setup the performance-optimized function for de/encrypt()
510 *
511 * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
512 */
513 protected function setupInlineCrypt(): void
514 {
515 // Init code for both, encrypt and decrypt.
516 $init_crypt = '$keys = $this->keys;';
517
518 $keys = $this->keys;
519
520 // $in is the current 8 bytes block which has to be en/decrypt
521 $encrypt_block = $decrypt_block = '
522 $in = unpack("v4", $in);
523 $r0 = $in[1];
524 $r1 = $in[2];
525 $r2 = $in[3];
526 $r3 = $in[4];
527 ';
528
529 // Create code for encryption.
530 $limit = 20;
531 $actions = [$limit => 44, 44 => 64];
532 $j = 0;
533
534 for (;;) {
535 // Mixing round.
536 $encrypt_block .= '
537 $r0 = (($r0 + ' . $keys[$j++] . ' +
538 ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
539 $r0 |= $r0 >> 16;
540 $r1 = (($r1 + ' . $keys[$j++] . ' +
541 ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
542 $r1 |= $r1 >> 16;
543 $r2 = (($r2 + ' . $keys[$j++] . ' +
544 ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
545 $r2 |= $r2 >> 16;
546 $r3 = (($r3 + ' . $keys[$j++] . ' +
547 ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
548 $r3 |= $r3 >> 16;';
549
550 if ($j === $limit) {
551 if ($limit === 64) {
552 break;
553 }
554
555 // Mashing round.
556 $encrypt_block .= '
557 $r0 += $keys[$r3 & 0x3F];
558 $r1 += $keys[$r0 & 0x3F];
559 $r2 += $keys[$r1 & 0x3F];
560 $r3 += $keys[$r2 & 0x3F];';
561 $limit = $actions[$limit];
562 }
563 }
564
565 $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
566
567 // Create code for decryption.
568 $limit = 44;
569 $actions = [$limit => 20, 20 => 0];
570 $j = 64;
571
572 for (;;) {
573 // R-mixing round.
574 $decrypt_block .= '
575 $r3 = ($r3 | ($r3 << 16)) >> 5;
576 $r3 = ($r3 - ' . $keys[--$j] . ' -
577 ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
578 $r2 = ($r2 | ($r2 << 16)) >> 3;
579 $r2 = ($r2 - ' . $keys[--$j] . ' -
580 ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
581 $r1 = ($r1 | ($r1 << 16)) >> 2;
582 $r1 = ($r1 - ' . $keys[--$j] . ' -
583 ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
584 $r0 = ($r0 | ($r0 << 16)) >> 1;
585 $r0 = ($r0 - ' . $keys[--$j] . ' -
586 ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
587
588 if ($j === $limit) {
589 if ($limit === 0) {
590 break;
591 }
592
593 // R-mashing round.
594 $decrypt_block .= '
595 $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
596 $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
597 $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
598 $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
599 $limit = $actions[$limit];
600 }
601 }
602
603 $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
604
605 // Creates the inline-crypt function
606 $this->inline_crypt = $this->createInlineCryptFunction(
607 [
608 'init_crypt' => $init_crypt,
609 'encrypt_block' => $encrypt_block,
610 'decrypt_block' => $decrypt_block,
611 ]
612 );
613 }
614 }
615