[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Pure-PHP implementation of RC4. 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://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm} 13 * - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4} 14 * 15 * RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not 16 * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification. 17 * 18 * Here's a short example of how to use this library: 19 * <code> 20 * <?php 21 * include 'vendor/autoload.php'; 22 * 23 * $rc4 = new \phpseclib\Crypt\RC4(); 24 * 25 * $rc4->setKey('abcdefgh'); 26 * 27 * $size = 10 * 1024; 28 * $plaintext = ''; 29 * for ($i = 0; $i < $size; $i++) { 30 * $plaintext.= 'a'; 31 * } 32 * 33 * echo $rc4->decrypt($rc4->encrypt($plaintext)); 34 * ?> 35 * </code> 36 * 37 * @category Crypt 38 * @package RC4 39 * @author Jim Wigginton <terrafrost@php.net> 40 * @copyright 2007 Jim Wigginton 41 * @license http://www.opensource.org/licenses/mit-license.html MIT License 42 * @link http://phpseclib.sourceforge.net 43 */ 44 45 namespace phpseclib\Crypt; 46 47 /** 48 * Pure-PHP implementation of RC4. 49 * 50 * @package RC4 51 * @author Jim Wigginton <terrafrost@php.net> 52 * @access public 53 */ 54 class RC4 extends Base 55 { 56 /**#@+ 57 * @access private 58 * @see \phpseclib\Crypt\RC4::_crypt() 59 */ 60 const ENCRYPT = 0; 61 const DECRYPT = 1; 62 /**#@-*/ 63 64 /** 65 * Block Length of the cipher 66 * 67 * RC4 is a stream cipher 68 * so we the block_size to 0 69 * 70 * @see \phpseclib\Crypt\Base::block_size 71 * @var int 72 * @access private 73 */ 74 var $block_size = 0; 75 76 /** 77 * Key Length (in bytes) 78 * 79 * @see \phpseclib\Crypt\RC4::setKeyLength() 80 * @var int 81 * @access private 82 */ 83 var $key_length = 128; // = 1024 bits 84 85 /** 86 * The mcrypt specific name of the cipher 87 * 88 * @see \phpseclib\Crypt\Base::cipher_name_mcrypt 89 * @var string 90 * @access private 91 */ 92 var $cipher_name_mcrypt = 'arcfour'; 93 94 /** 95 * Holds whether performance-optimized $inline_crypt() can/should be used. 96 * 97 * @see \phpseclib\Crypt\Base::inline_crypt 98 * @var mixed 99 * @access private 100 */ 101 var $use_inline_crypt = false; // currently not available 102 103 /** 104 * The Key 105 * 106 * @see self::setKey() 107 * @var string 108 * @access private 109 */ 110 var $key; 111 112 /** 113 * The Key Stream for decryption and encryption 114 * 115 * @see self::setKey() 116 * @var array 117 * @access private 118 */ 119 var $stream; 120 121 /** 122 * Default Constructor. 123 * 124 * Determines whether or not the mcrypt extension should be used. 125 * 126 * @see \phpseclib\Crypt\Base::__construct() 127 * @return \phpseclib\Crypt\RC4 128 * @access public 129 */ 130 function __construct() 131 { 132 parent::__construct(Base::MODE_STREAM); 133 } 134 135 /** 136 * Test for engine validity 137 * 138 * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() 139 * 140 * @see \phpseclib\Crypt\Base::__construct() 141 * @param int $engine 142 * @access public 143 * @return bool 144 */ 145 function isValidEngine($engine) 146 { 147 if ($engine == self::ENGINE_OPENSSL) { 148 // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 149 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" 150 // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not 151 if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { 152 return false; 153 } 154 if (version_compare(PHP_VERSION, '5.3.7') >= 0) { 155 $this->cipher_name_openssl = 'rc4-40'; 156 } else { 157 switch (strlen($this->key)) { 158 case 5: 159 $this->cipher_name_openssl = 'rc4-40'; 160 break; 161 case 8: 162 $this->cipher_name_openssl = 'rc4-64'; 163 break; 164 case 16: 165 $this->cipher_name_openssl = 'rc4'; 166 break; 167 default: 168 return false; 169 } 170 } 171 } 172 173 return parent::isValidEngine($engine); 174 } 175 176 /** 177 * Dummy function. 178 * 179 * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1]. 180 * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before 181 * calling setKey(). 182 * 183 * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol, 184 * the IV's are relatively easy to predict, an attack described by 185 * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir} 186 * can be used to quickly guess at the rest of the key. The following links elaborate: 187 * 188 * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009} 189 * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack} 190 * 191 * @param string $iv 192 * @see self::setKey() 193 * @access public 194 */ 195 function setIV($iv) 196 { 197 } 198 199 /** 200 * Sets the key length 201 * 202 * Keys can be between 1 and 256 bytes long. 203 * 204 * @access public 205 * @param int $length 206 */ 207 function setKeyLength($length) 208 { 209 if ($length < 8) { 210 $this->key_length = 1; 211 } elseif ($length > 2048) { 212 $this->key_length = 256; 213 } else { 214 $this->key_length = $length >> 3; 215 } 216 217 parent::setKeyLength($length); 218 } 219 220 /** 221 * Encrypts a message. 222 * 223 * @see \phpseclib\Crypt\Base::decrypt() 224 * @see self::_crypt() 225 * @access public 226 * @param string $plaintext 227 * @return string $ciphertext 228 */ 229 function encrypt($plaintext) 230 { 231 if ($this->engine != self::ENGINE_INTERNAL) { 232 return parent::encrypt($plaintext); 233 } 234 return $this->_crypt($plaintext, self::ENCRYPT); 235 } 236 237 /** 238 * Decrypts a message. 239 * 240 * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). 241 * At least if the continuous buffer is disabled. 242 * 243 * @see \phpseclib\Crypt\Base::encrypt() 244 * @see self::_crypt() 245 * @access public 246 * @param string $ciphertext 247 * @return string $plaintext 248 */ 249 function decrypt($ciphertext) 250 { 251 if ($this->engine != self::ENGINE_INTERNAL) { 252 return parent::decrypt($ciphertext); 253 } 254 return $this->_crypt($ciphertext, self::DECRYPT); 255 } 256 257 /** 258 * Encrypts a block 259 * 260 * @access private 261 * @param string $in 262 */ 263 function _encryptBlock($in) 264 { 265 // RC4 does not utilize this method 266 } 267 268 /** 269 * Decrypts a block 270 * 271 * @access private 272 * @param string $in 273 */ 274 function _decryptBlock($in) 275 { 276 // RC4 does not utilize this method 277 } 278 279 /** 280 * Setup the key (expansion) 281 * 282 * @see \phpseclib\Crypt\Base::_setupKey() 283 * @access private 284 */ 285 function _setupKey() 286 { 287 $key = $this->key; 288 $keyLength = strlen($key); 289 $keyStream = range(0, 255); 290 $j = 0; 291 for ($i = 0; $i < 256; $i++) { 292 $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; 293 $temp = $keyStream[$i]; 294 $keyStream[$i] = $keyStream[$j]; 295 $keyStream[$j] = $temp; 296 } 297 298 $this->stream = array(); 299 $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array( 300 0, // index $i 301 0, // index $j 302 $keyStream 303 ); 304 } 305 306 /** 307 * Encrypts or decrypts a message. 308 * 309 * @see self::encrypt() 310 * @see self::decrypt() 311 * @access private 312 * @param string $text 313 * @param int $mode 314 * @return string $text 315 */ 316 function _crypt($text, $mode) 317 { 318 if ($this->changed) { 319 $this->_setup(); 320 $this->changed = false; 321 } 322 323 $stream = &$this->stream[$mode]; 324 if ($this->continuousBuffer) { 325 $i = &$stream[0]; 326 $j = &$stream[1]; 327 $keyStream = &$stream[2]; 328 } else { 329 $i = $stream[0]; 330 $j = $stream[1]; 331 $keyStream = $stream[2]; 332 } 333 334 $len = strlen($text); 335 for ($k = 0; $k < $len; ++$k) { 336 $i = ($i + 1) & 255; 337 $ksi = $keyStream[$i]; 338 $j = ($j + $ksi) & 255; 339 $ksj = $keyStream[$j]; 340 341 $keyStream[$i] = $ksj; 342 $keyStream[$j] = $ksi; 343 $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]); 344 } 345 346 return $text; 347 } 348 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body