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