PluginProbe
ManageWP Worker / 3.9.28
ManageWP Worker v3.9.28
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / lib / PHPSecLib / Crypt / RC4.php

RC4.php in ManageWP Worker 3.9.28, at lib/PHPSecLib/Crypt/RC4.php

493 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4 /**
5 * Pure-PHP implementation of RC4.
6 *
7 * Uses mcrypt, if available, and an internal implementation, otherwise.
8 *
9 * PHP versions 4 and 5
10 *
11 * Useful resources are as follows:
12 *
13 * - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
14 * - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
15 *
16 * RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
17 * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
18 *
19 * Here's a short example of how to use this library:
20 * <code>
21 * <?php
22 * include('Crypt/RC4.php');
23 *
24 * $rc4 = new Crypt_RC4();
25 *
26 * $rc4->setKey('abcdefgh');
27 *
28 * $size = 10 * 1024;
29 * $plaintext = '';
30 * for ($i = 0; $i < $size; $i++) {
31 * $plaintext.= 'a';
32 * }
33 *
34 * echo $rc4->decrypt($rc4->encrypt($plaintext));
35 * ?>
36 * </code>
37 *
38 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
39 * of this software and associated documentation files (the "Software"), to deal
40 * in the Software without restriction, including without limitation the rights
41 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
42 * copies of the Software, and to permit persons to whom the Software is
43 * furnished to do so, subject to the following conditions:
44 *
45 * The above copyright notice and this permission notice shall be included in
46 * all copies or substantial portions of the Software.
47 *
48 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
51 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
53 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
54 * THE SOFTWARE.
55 *
56 * @category Crypt
57 * @package Crypt_RC4
58 * @author Jim Wigginton <terrafrost@php.net>
59 * @copyright MMVII Jim Wigginton
60 * @license http://www.opensource.org/licenses/mit-license.html MIT License
61 * @link http://phpseclib.sourceforge.net
62 */
63
64 /**#@+
65 * @access private
66 * @see Crypt_RC4::Crypt_RC4()
67 */
68 /**
69 * Toggles the internal implementation
70 */
71 define('CRYPT_RC4_MODE_INTERNAL', 1);
72 /**
73 * Toggles the mcrypt implementation
74 */
75 define('CRYPT_RC4_MODE_MCRYPT', 2);
76 /**#@-*/
77
78 /**#@+
79 * @access private
80 * @see Crypt_RC4::_crypt()
81 */
82 define('CRYPT_RC4_ENCRYPT', 0);
83 define('CRYPT_RC4_DECRYPT', 1);
84 /**#@-*/
85
86 /**
87 * Pure-PHP implementation of RC4.
88 *
89 * @author Jim Wigginton <terrafrost@php.net>
90 * @version 0.1.0
91 * @access public
92 * @package Crypt_RC4
93 */
94 class Crypt_RC4 {
95 /**
96 * The Key
97 *
98 * @see Crypt_RC4::setKey()
99 * @var String
100 * @access private
101 */
102 var $key = "\0";
103
104 /**
105 * The Key Stream for encryption
106 *
107 * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
108 *
109 * @see Crypt_RC4::setKey()
110 * @var Array
111 * @access private
112 */
113 var $encryptStream = false;
114
115 /**
116 * The Key Stream for decryption
117 *
118 * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
119 *
120 * @see Crypt_RC4::setKey()
121 * @var Array
122 * @access private
123 */
124 var $decryptStream = false;
125
126 /**
127 * The $i and $j indexes for encryption
128 *
129 * @see Crypt_RC4::_crypt()
130 * @var Integer
131 * @access private
132 */
133 var $encryptIndex = 0;
134
135 /**
136 * The $i and $j indexes for decryption
137 *
138 * @see Crypt_RC4::_crypt()
139 * @var Integer
140 * @access private
141 */
142 var $decryptIndex = 0;
143
144 /**
145 * The Encryption Algorithm
146 *
147 * Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
148 *
149 * @see Crypt_RC4::Crypt_RC4()
150 * @var Integer
151 * @access private
152 */
153 var $mode;
154
155 /**
156 * Continuous Buffer status
157 *
158 * @see Crypt_RC4::enableContinuousBuffer()
159 * @var Boolean
160 * @access private
161 */
162 var $continuousBuffer = false;
163
164 /**
165 * Default Constructor.
166 *
167 * Determines whether or not the mcrypt extension should be used.
168 *
169 * @return Crypt_RC4
170 * @access public
171 */
172 function Crypt_RC4()
173 {
174 if ( !defined('CRYPT_RC4_MODE') ) {
175 switch (true) {
176 case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')) && in_array('arcfour', mcrypt_list_algorithms()):
177 define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
178 break;
179 default:
180 define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
181 }
182 }
183
184 switch ( CRYPT_RC4_MODE ) {
185 case CRYPT_RC4_MODE_MCRYPT:
186 switch (true) {
187 case defined('MCRYPT_ARCFOUR'):
188 $this->mode = MCRYPT_ARCFOUR;
189 break;
190 case defined('MCRYPT_RC4');
191 $this->mode = MCRYPT_RC4;
192 }
193 $this->encryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
194 $this->decryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
195
196 }
197 }
198
199 /**
200 * Sets the key.
201 *
202 * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
203 * be used. If no key is explicitly set, it'll be assumed to be a single null byte.
204 *
205 * @access public
206 * @param String $key
207 */
208 function setKey($key)
209 {
210 $this->key = $key;
211
212 if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
213 mcrypt_generic_init($this->encryptStream, $this->key, '');
214 mcrypt_generic_init($this->decryptStream, $this->key, '');
215 return;
216 }
217
218 $keyLength = strlen($key);
219 $keyStream = array();
220 for ($i = 0; $i < 256; $i++) {
221 $keyStream[$i] = $i;
222 }
223 $j = 0;
224 for ($i = 0; $i < 256; $i++) {
225 $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
226 $temp = $keyStream[$i];
227 $keyStream[$i] = $keyStream[$j];
228 $keyStream[$j] = $temp;
229 }
230
231 $this->encryptIndex = $this->decryptIndex = array(0, 0);
232 $this->encryptStream = $this->decryptStream = $keyStream;
233 }
234
235 /**
236 * Sets the password.
237 *
238 * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
239 * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
240 * $hash, $salt, $count, $dkLen
241 *
242 * @param String $password
243 * @param optional String $method
244 * @access public
245 */
246 function setPassword($password, $method = 'pbkdf2')
247 {
248 $key = '';
249
250 switch ($method) {
251 default: // 'pbkdf2'
252 list(, , $hash, $salt, $count) = func_get_args();
253 if (!isset($hash)) {
254 $hash = 'sha1';
255 }
256 // WPA and WPA2 use the SSID as the salt
257 if (!isset($salt)) {
258 $salt = 'phpseclib/salt';
259 }
260 // RFC2898#section-4.2 uses 1,000 iterations by default
261 // WPA and WPA2 use 4,096.
262 if (!isset($count)) {
263 $count = 1000;
264 }
265 if (!isset($dkLen)) {
266 $dkLen = 128;
267 }
268
269 if (!class_exists('Crypt_Hash')) {
270 require_once('Crypt/Hash.php');
271 }
272
273 $i = 1;
274 while (strlen($key) < $dkLen) {
275 //$dk.= $this->_pbkdf($password, $salt, $count, $i++);
276 $hmac = new Crypt_Hash();
277 $hmac->setHash($hash);
278 $hmac->setKey($password);
279 $f = $u = $hmac->hash($salt . pack('N', $i++));
280 for ($j = 2; $j <= $count; $j++) {
281 $u = $hmac->hash($u);
282 $f^= $u;
283 }
284 $key.= $f;
285 }
286 }
287
288 $this->setKey(substr($key, 0, $dkLen));
289 }
290
291 /**
292 * Dummy function.
293 *
294 * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
295 * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
296 * calling setKey().
297 *
298 * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
299 * the IV's are relatively easy to predict, an attack described by
300 * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
301 * can be used to quickly guess at the rest of the key. The following links elaborate:
302 *
303 * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
304 * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
305 *
306 * @param String $iv
307 * @see Crypt_RC4::setKey()
308 * @access public
309 */
310 function setIV($iv)
311 {
312 }
313
314 /**
315 * Encrypts a message.
316 *
317 * @see Crypt_RC4::_crypt()
318 * @access public
319 * @param String $plaintext
320 */
321 function encrypt($plaintext)
322 {
323 return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
324 }
325
326 /**
327 * Decrypts a message.
328 *
329 * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
330 * Atleast if the continuous buffer is disabled.
331 *
332 * @see Crypt_RC4::_crypt()
333 * @access public
334 * @param String $ciphertext
335 */
336 function decrypt($ciphertext)
337 {
338 return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
339 }
340
341 /**
342 * Encrypts or decrypts a message.
343 *
344 * @see Crypt_RC4::encrypt()
345 * @see Crypt_RC4::decrypt()
346 * @access private
347 * @param String $text
348 * @param Integer $mode
349 */
350 function _crypt($text, $mode)
351 {
352 if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
353 $keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
354
355 if (!$this->continuousBuffer) {
356 mcrypt_generic_init($this->$keyStream, $this->key, '');
357 }
358
359 return mcrypt_generic($this->$keyStream, $text);
360 }
361
362 if ($this->encryptStream === false) {
363 $this->setKey($this->key);
364 }
365
366 switch ($mode) {
367 case CRYPT_RC4_ENCRYPT:
368 $keyStream = $this->encryptStream;
369 list($i, $j) = $this->encryptIndex;
370 break;
371 case CRYPT_RC4_DECRYPT:
372 $keyStream = $this->decryptStream;
373 list($i, $j) = $this->decryptIndex;
374 }
375
376 $newText = '';
377 for ($k = 0; $k < strlen($text); $k++) {
378 $i = ($i + 1) & 255;
379 $j = ($j + $keyStream[$i]) & 255;
380 $temp = $keyStream[$i];
381 $keyStream[$i] = $keyStream[$j];
382 $keyStream[$j] = $temp;
383 $temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
384 $newText.= chr(ord($text[$k]) ^ $temp);
385 }
386
387 if ($this->continuousBuffer) {
388 switch ($mode) {
389 case CRYPT_RC4_ENCRYPT:
390 $this->encryptStream = $keyStream;
391 $this->encryptIndex = array($i, $j);
392 break;
393 case CRYPT_RC4_DECRYPT:
394 $this->decryptStream = $keyStream;
395 $this->decryptIndex = array($i, $j);
396 }
397 }
398
399 return $newText;
400 }
401
402 /**
403 * Treat consecutive "packets" as if they are a continuous buffer.
404 *
405 * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
406 * will yield different outputs:
407 *
408 * <code>
409 * echo $rc4->encrypt(substr($plaintext, 0, 8));
410 * echo $rc4->encrypt(substr($plaintext, 8, 8));
411 * </code>
412 * <code>
413 * echo $rc4->encrypt($plaintext);
414 * </code>
415 *
416 * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
417 * another, as demonstrated with the following:
418 *
419 * <code>
420 * $rc4->encrypt(substr($plaintext, 0, 8));
421 * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
422 * </code>
423 * <code>
424 * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
425 * </code>
426 *
427 * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
428 * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
429 * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
430 *
431 * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
432 * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
433 * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
434 * however, they are also less intuitive and more likely to cause you problems.
435 *
436 * @see Crypt_RC4::disableContinuousBuffer()
437 * @access public
438 */
439 function enableContinuousBuffer()
440 {
441 if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
442 mcrypt_generic_init($this->encryptStream, $this->key, '');
443 mcrypt_generic_init($this->decryptStream, $this->key, '');
444 }
445
446 $this->continuousBuffer = true;
447 }
448
449 /**
450 * Treat consecutive packets as if they are a discontinuous buffer.
451 *
452 * The default behavior.
453 *
454 * @see Crypt_RC4::enableContinuousBuffer()
455 * @access public
456 */
457 function disableContinuousBuffer()
458 {
459 if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
460 $this->encryptIndex = $this->decryptIndex = array(0, 0);
461 $this->encryptStream = $this->decryptStream = false;
462 }
463
464 $this->continuousBuffer = false;
465 }
466
467 /**
468 * Dummy function.
469 *
470 * Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
471 * included is so that you can switch between a block cipher and a stream cipher transparently.
472 *
473 * @see Crypt_RC4::disablePadding()
474 * @access public
475 */
476 function enablePadding()
477 {
478 }
479
480 /**
481 * Dummy function.
482 *
483 * @see Crypt_RC4::enablePadding()
484 * @access public
485 */
486 function disablePadding()
487 {
488 }
489 }
490
491 // vim: ts=4:sw=4:et:
492 // vim6: fdl=1:
493