[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
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 // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 277 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" 278 // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not 279 if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { 280 return false; 281 } 282 if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) { 283 return false; 284 } 285 $this->cipher_name_openssl_ecb = 'rc2-ecb'; 286 $this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode(); 287 } 288 289 return parent::isValidEngine($engine); 290 } 291 292 /** 293 * Sets the key length. 294 * 295 * Valid key lengths are 8 to 1024. 296 * Calling this function after setting the key has no effect until the next 297 * \phpseclib\Crypt\RC2::setKey() call. 298 * 299 * @access public 300 * @param int $length in bits 301 */ 302 function setKeyLength($length) 303 { 304 if ($length < 8) { 305 $this->default_key_length = 1; 306 } elseif ($length > 1024) { 307 $this->default_key_length = 128; 308 } else { 309 $this->default_key_length = $length; 310 } 311 $this->current_key_length = $this->default_key_length; 312 313 parent::setKeyLength($length); 314 } 315 316 /** 317 * Returns the current key length 318 * 319 * @access public 320 * @return int 321 */ 322 function getKeyLength() 323 { 324 return $this->current_key_length; 325 } 326 327 /** 328 * Sets the key. 329 * 330 * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg. 331 * strlen($key) <= 128), however, we only use the first 128 bytes if $key 332 * has more then 128 bytes in it, and set $key to a single null byte if 333 * it is empty. 334 * 335 * If the key is not explicitly set, it'll be assumed to be a single 336 * null byte. 337 * 338 * @see \phpseclib\Crypt\Base::setKey() 339 * @access public 340 * @param string $key 341 * @param int $t1 optional Effective key length in bits. 342 */ 343 function setKey($key, $t1 = 0) 344 { 345 $this->orig_key = $key; 346 347 if ($t1 <= 0) { 348 $t1 = $this->default_key_length; 349 } elseif ($t1 > 1024) { 350 $t1 = 1024; 351 } 352 $this->current_key_length = $t1; 353 // Key byte count should be 1..128. 354 $key = strlen($key) ? substr($key, 0, 128) : "\x00"; 355 $t = strlen($key); 356 357 // The mcrypt RC2 implementation only supports effective key length 358 // of 1024 bits. It is however possible to handle effective key 359 // lengths in range 1..1024 by expanding the key and applying 360 // inverse pitable mapping to the first byte before submitting it 361 // to mcrypt. 362 363 // Key expansion. 364 $l = array_values(unpack('C*', $key)); 365 $t8 = ($t1 + 7) >> 3; 366 $tm = 0xFF >> (8 * $t8 - $t1); 367 368 // Expand key. 369 $pitable = $this->pitable; 370 for ($i = $t; $i < 128; $i++) { 371 $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]]; 372 } 373 $i = 128 - $t8; 374 $l[$i] = $pitable[$l[$i] & $tm]; 375 while ($i--) { 376 $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]]; 377 } 378 379 // Prepare the key for mcrypt. 380 $l[0] = $this->invpitable[$l[0]]; 381 array_unshift($l, 'C*'); 382 383 parent::setKey(call_user_func_array('pack', $l)); 384 } 385 386 /** 387 * Encrypts a message. 388 * 389 * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code 390 * 391 * @see self::decrypt() 392 * @access public 393 * @param string $plaintext 394 * @return string $ciphertext 395 */ 396 function encrypt($plaintext) 397 { 398 if ($this->engine == self::ENGINE_OPENSSL) { 399 $temp = $this->key; 400 $this->key = $this->orig_key; 401 $result = parent::encrypt($plaintext); 402 $this->key = $temp; 403 return $result; 404 } 405 406 return parent::encrypt($plaintext); 407 } 408 409 /** 410 * Decrypts a message. 411 * 412 * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code 413 * 414 * @see self::encrypt() 415 * @access public 416 * @param string $ciphertext 417 * @return string $plaintext 418 */ 419 function decrypt($ciphertext) 420 { 421 if ($this->engine == self::ENGINE_OPENSSL) { 422 $temp = $this->key; 423 $this->key = $this->orig_key; 424 $result = parent::decrypt($ciphertext); 425 $this->key = $temp; 426 return $result; 427 } 428 429 return parent::decrypt($ciphertext); 430 } 431 432 /** 433 * Encrypts a block 434 * 435 * @see \phpseclib\Crypt\Base::_encryptBlock() 436 * @see \phpseclib\Crypt\Base::encrypt() 437 * @access private 438 * @param string $in 439 * @return string 440 */ 441 function _encryptBlock($in) 442 { 443 list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); 444 $keys = $this->keys; 445 $limit = 20; 446 $actions = array($limit => 44, 44 => 64); 447 $j = 0; 448 449 for (;;) { 450 // Mixing round. 451 $r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; 452 $r0 |= $r0 >> 16; 453 $r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; 454 $r1 |= $r1 >> 16; 455 $r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; 456 $r2 |= $r2 >> 16; 457 $r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; 458 $r3 |= $r3 >> 16; 459 460 if ($j === $limit) { 461 if ($limit === 64) { 462 break; 463 } 464 465 // Mashing round. 466 $r0 += $keys[$r3 & 0x3F]; 467 $r1 += $keys[$r0 & 0x3F]; 468 $r2 += $keys[$r1 & 0x3F]; 469 $r3 += $keys[$r2 & 0x3F]; 470 $limit = $actions[$limit]; 471 } 472 } 473 474 return pack('vvvv', $r0, $r1, $r2, $r3); 475 } 476 477 /** 478 * Decrypts a block 479 * 480 * @see \phpseclib\Crypt\Base::_decryptBlock() 481 * @see \phpseclib\Crypt\Base::decrypt() 482 * @access private 483 * @param string $in 484 * @return string 485 */ 486 function _decryptBlock($in) 487 { 488 list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in)); 489 $keys = $this->keys; 490 $limit = 44; 491 $actions = array($limit => 20, 20 => 0); 492 $j = 64; 493 494 for (;;) { 495 // R-mixing round. 496 $r3 = ($r3 | ($r3 << 16)) >> 5; 497 $r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; 498 $r2 = ($r2 | ($r2 << 16)) >> 3; 499 $r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; 500 $r1 = ($r1 | ($r1 << 16)) >> 2; 501 $r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; 502 $r0 = ($r0 | ($r0 << 16)) >> 1; 503 $r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF; 504 505 if ($j === $limit) { 506 if ($limit === 0) { 507 break; 508 } 509 510 // R-mashing round. 511 $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; 512 $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; 513 $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; 514 $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF; 515 $limit = $actions[$limit]; 516 } 517 } 518 519 return pack('vvvv', $r0, $r1, $r2, $r3); 520 } 521 522 /** 523 * Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine 524 * 525 * @see \phpseclib\Crypt\Base::_setupMcrypt() 526 * @access private 527 */ 528 function _setupMcrypt() 529 { 530 if (!isset($this->key)) { 531 $this->setKey(''); 532 } 533 534 parent::_setupMcrypt(); 535 } 536 537 /** 538 * Creates the key schedule 539 * 540 * @see \phpseclib\Crypt\Base::_setupKey() 541 * @access private 542 */ 543 function _setupKey() 544 { 545 if (!isset($this->key)) { 546 $this->setKey(''); 547 } 548 549 // Key has already been expanded in \phpseclib\Crypt\RC2::setKey(): 550 // Only the first value must be altered. 551 $l = unpack('Ca/Cb/v*', $this->key); 552 array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8)); 553 unset($l['a']); 554 unset($l['b']); 555 $this->keys = $l; 556 } 557 558 /** 559 * Setup the performance-optimized function for de/encrypt() 560 * 561 * @see \phpseclib\Crypt\Base::_setupInlineCrypt() 562 * @access private 563 */ 564 function _setupInlineCrypt() 565 { 566 $lambda_functions =& self::_getLambdaFunctions(); 567 568 // The first 10 generated $lambda_functions will use the $keys hardcoded as integers 569 // for the mixing rounds, for better inline crypt performance [~20% faster]. 570 // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10. 571 // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit) 572 $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); 573 574 // Generation of a unique hash for our generated code 575 $code_hash = "Crypt_RC2, {$this->mode}"; 576 if ($gen_hi_opt_code) { 577 $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); 578 } 579 580 // Is there a re-usable $lambda_functions in there? 581 // If not, we have to create it. 582 if (!isset($lambda_functions[$code_hash])) { 583 // Init code for both, encrypt and decrypt. 584 $init_crypt = '$keys = $self->keys;'; 585 586 switch (true) { 587 case $gen_hi_opt_code: 588 $keys = $this->keys; 589 default: 590 $keys = array(); 591 foreach ($this->keys as $k => $v) { 592 $keys[$k] = '$keys[' . $k . ']'; 593 } 594 } 595 596 // $in is the current 8 bytes block which has to be en/decrypt 597 $encrypt_block = $decrypt_block = ' 598 $in = unpack("v4", $in); 599 $r0 = $in[1]; 600 $r1 = $in[2]; 601 $r2 = $in[3]; 602 $r3 = $in[4]; 603 '; 604 605 // Create code for encryption. 606 $limit = 20; 607 $actions = array($limit => 44, 44 => 64); 608 $j = 0; 609 610 for (;;) { 611 // Mixing round. 612 $encrypt_block .= ' 613 $r0 = (($r0 + ' . $keys[$j++] . ' + 614 ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1; 615 $r0 |= $r0 >> 16; 616 $r1 = (($r1 + ' . $keys[$j++] . ' + 617 ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2; 618 $r1 |= $r1 >> 16; 619 $r2 = (($r2 + ' . $keys[$j++] . ' + 620 ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3; 621 $r2 |= $r2 >> 16; 622 $r3 = (($r3 + ' . $keys[$j++] . ' + 623 ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5; 624 $r3 |= $r3 >> 16;'; 625 626 if ($j === $limit) { 627 if ($limit === 64) { 628 break; 629 } 630 631 // Mashing round. 632 $encrypt_block .= ' 633 $r0 += $keys[$r3 & 0x3F]; 634 $r1 += $keys[$r0 & 0x3F]; 635 $r2 += $keys[$r1 & 0x3F]; 636 $r3 += $keys[$r2 & 0x3F];'; 637 $limit = $actions[$limit]; 638 } 639 } 640 641 $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; 642 643 // Create code for decryption. 644 $limit = 44; 645 $actions = array($limit => 20, 20 => 0); 646 $j = 64; 647 648 for (;;) { 649 // R-mixing round. 650 $decrypt_block .= ' 651 $r3 = ($r3 | ($r3 << 16)) >> 5; 652 $r3 = ($r3 - ' . $keys[--$j] . ' - 653 ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF; 654 $r2 = ($r2 | ($r2 << 16)) >> 3; 655 $r2 = ($r2 - ' . $keys[--$j] . ' - 656 ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF; 657 $r1 = ($r1 | ($r1 << 16)) >> 2; 658 $r1 = ($r1 - ' . $keys[--$j] . ' - 659 ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF; 660 $r0 = ($r0 | ($r0 << 16)) >> 1; 661 $r0 = ($r0 - ' . $keys[--$j] . ' - 662 ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;'; 663 664 if ($j === $limit) { 665 if ($limit === 0) { 666 break; 667 } 668 669 // R-mashing round. 670 $decrypt_block .= ' 671 $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF; 672 $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF; 673 $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF; 674 $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;'; 675 $limit = $actions[$limit]; 676 } 677 } 678 679 $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);'; 680 681 // Creates the inline-crypt function 682 $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( 683 array( 684 'init_crypt' => $init_crypt, 685 'encrypt_block' => $encrypt_block, 686 'decrypt_block' => $decrypt_block 687 ) 688 ); 689 } 690 691 // Set the inline-crypt function as callback in: $this->inline_crypt 692 $this->inline_crypt = $lambda_functions[$code_hash]; 693 } 694 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body