]> git.mxchange.org Git - friendica-addons.git/blob - securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php
securemail: update pgp library
[friendica-addons.git] / securemail / vendor / phpseclib / phpseclib / phpseclib / Crypt / RC4.php
1 <?php
2
3 /**
4  * Pure-PHP implementation of RC4.
5  *
6  * Uses mcrypt, if available, and an internal implementation, otherwise.
7  *
8  * PHP versions 4 and 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 'Crypt/RC4.php';
22  *
23  *    $rc4 = new 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  * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
38  * of this software and associated documentation files (the "Software"), to deal
39  * in the Software without restriction, including without limitation the rights
40  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41  * copies of the Software, and to permit persons to whom the Software is
42  * furnished to do so, subject to the following conditions:
43  *
44  * The above copyright notice and this permission notice shall be included in
45  * all copies or substantial portions of the Software.
46  *
47  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53  * THE SOFTWARE.
54  *
55  * @category  Crypt
56  * @package   Crypt_RC4
57  * @author    Jim Wigginton <terrafrost@php.net>
58  * @copyright 2007 Jim Wigginton
59  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
60  * @link      http://phpseclib.sourceforge.net
61  */
62
63 /**
64  * Include Crypt_Base
65  *
66  * Base cipher class
67  */
68 if (!class_exists('Crypt_Base')) {
69     include_once 'Base.php';
70 }
71
72 /**#@+
73  * @access private
74  * @see Crypt_RC4::Crypt_RC4()
75  */
76 /**
77  * Toggles the internal implementation
78  */
79 define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
80 /**
81  * Toggles the mcrypt implementation
82  */
83 define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
84 /**#@-*/
85
86 /**#@+
87  * @access private
88  * @see Crypt_RC4::_crypt()
89  */
90 define('CRYPT_RC4_ENCRYPT', 0);
91 define('CRYPT_RC4_DECRYPT', 1);
92 /**#@-*/
93
94 /**
95  * Pure-PHP implementation of RC4.
96  *
97  * @package Crypt_RC4
98  * @author  Jim Wigginton <terrafrost@php.net>
99  * @access  public
100  */
101 class Crypt_RC4 extends Crypt_Base
102 {
103     /**
104      * Block Length of the cipher
105      *
106      * RC4 is a stream cipher
107      * so we the block_size to 0
108      *
109      * @see Crypt_Base::block_size
110      * @var Integer
111      * @access private
112      */
113     var $block_size = 0;
114
115     /**
116      * The default password key_size used by setPassword()
117      *
118      * @see Crypt_Base::password_key_size
119      * @see Crypt_Base::setPassword()
120      * @var Integer
121      * @access private
122      */
123     var $password_key_size = 128; // = 1024 bits
124
125     /**
126      * The namespace used by the cipher for its constants.
127      *
128      * @see Crypt_Base::const_namespace
129      * @var String
130      * @access private
131      */
132     var $const_namespace = 'RC4';
133
134     /**
135      * The mcrypt specific name of the cipher
136      *
137      * @see Crypt_Base::cipher_name_mcrypt
138      * @var String
139      * @access private
140      */
141     var $cipher_name_mcrypt = 'arcfour';
142
143     /**
144      * Holds whether performance-optimized $inline_crypt() can/should be used.
145      *
146      * @see Crypt_Base::inline_crypt
147      * @var mixed
148      * @access private
149      */
150     var $use_inline_crypt = false; // currently not available
151
152     /**
153      * The Key
154      *
155      * @see Crypt_RC4::setKey()
156      * @var String
157      * @access private
158      */
159     var $key = "\0";
160
161     /**
162      * The Key Stream for decryption and encryption
163      *
164      * @see Crypt_RC4::setKey()
165      * @var Array
166      * @access private
167      */
168     var $stream;
169
170     /**
171      * Default Constructor.
172      *
173      * Determines whether or not the mcrypt extension should be used.
174      *
175      * @see Crypt_Base::Crypt_Base()
176      * @return Crypt_RC4
177      * @access public
178      */
179     function Crypt_RC4()
180     {
181         parent::Crypt_Base(CRYPT_MODE_STREAM);
182     }
183
184     /**
185      * Dummy function.
186      *
187      * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
188      * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
189      * calling setKey().
190      *
191      * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way.  Since, in that protocol,
192      * the IV's are relatively easy to predict, an attack described by
193      * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
194      * can be used to quickly guess at the rest of the key.  The following links elaborate:
195      *
196      * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
197      * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
198      *
199      * @param String $iv
200      * @see Crypt_RC4::setKey()
201      * @access public
202      */
203     function setIV($iv)
204     {
205     }
206
207     /**
208      * Sets the key.
209      *
210      * Keys can be between 1 and 256 bytes long.  If they are longer then 256 bytes, the first 256 bytes will
211      * be used.  If no key is explicitly set, it'll be assumed to be a single null byte.
212      *
213      * @access public
214      * @see Crypt_Base::setKey()
215      * @param String $key
216      */
217     function setKey($key)
218     {
219         parent::setKey(substr($key, 0, 256));
220     }
221
222     /**
223      * Encrypts a message.
224      *
225      * @see Crypt_Base::decrypt()
226      * @see Crypt_RC4::_crypt()
227      * @access public
228      * @param String $plaintext
229      * @return String $ciphertext
230      */
231     function encrypt($plaintext)
232     {
233         if ($this->engine == CRYPT_MODE_MCRYPT) {
234             return parent::encrypt($plaintext);
235         }
236         return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
237     }
238
239     /**
240      * Decrypts a message.
241      *
242      * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
243      * At least if the continuous buffer is disabled.
244      *
245      * @see Crypt_Base::encrypt()
246      * @see Crypt_RC4::_crypt()
247      * @access public
248      * @param String $ciphertext
249      * @return String $plaintext
250      */
251     function decrypt($ciphertext)
252     {
253         if ($this->engine == CRYPT_MODE_MCRYPT) {
254             return parent::decrypt($ciphertext);
255         }
256         return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
257     }
258
259
260     /**
261      * Setup the key (expansion)
262      *
263      * @see Crypt_Base::_setupKey()
264      * @access private
265      */
266     function _setupKey()
267     {
268         $key = $this->key;
269         $keyLength = strlen($key);
270         $keyStream = range(0, 255);
271         $j = 0;
272         for ($i = 0; $i < 256; $i++) {
273             $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
274             $temp = $keyStream[$i];
275             $keyStream[$i] = $keyStream[$j];
276             $keyStream[$j] = $temp;
277         }
278
279         $this->stream = array();
280         $this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
281             0, // index $i
282             0, // index $j
283             $keyStream
284         );
285     }
286
287     /**
288      * Encrypts or decrypts a message.
289      *
290      * @see Crypt_RC4::encrypt()
291      * @see Crypt_RC4::decrypt()
292      * @access private
293      * @param String $text
294      * @param Integer $mode
295      * @return String $text
296      */
297     function _crypt($text, $mode)
298     {
299         if ($this->changed) {
300             $this->_setup();
301             $this->changed = false;
302         }
303
304         $stream = &$this->stream[$mode];
305         if ($this->continuousBuffer) {
306             $i = &$stream[0];
307             $j = &$stream[1];
308             $keyStream = &$stream[2];
309         } else {
310             $i = $stream[0];
311             $j = $stream[1];
312             $keyStream = $stream[2];
313         }
314
315         $len = strlen($text);
316         for ($k = 0; $k < $len; ++$k) {
317             $i = ($i + 1) & 255;
318             $ksi = $keyStream[$i];
319             $j = ($j + $ksi) & 255;
320             $ksj = $keyStream[$j];
321
322             $keyStream[$i] = $ksj;
323             $keyStream[$j] = $ksi;
324             $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
325         }
326
327         return $text;
328     }
329 }