SSH SFTP Updater Support - Version 0.7.2

Version Description

  • update phpseclib to latest version
Download this release

Release Info

Developer DavidAnderson
Plugin Icon wp plugin SSH SFTP Updater Support
Version 0.7.2
Comparing to
See all releases

Code changes from version 0.7.1 to 0.7.2

phpseclib/Crypt/AES.php CHANGED
@@ -7,17 +7,17 @@
7
  *
8
  * PHP versions 4 and 5
9
  *
10
- * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
11
  * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
12
  * to save one include_once().
13
  *
14
- * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
15
- * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
16
- * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
17
  * is called, again, at which point, it'll be recalculated.
18
  *
19
  * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
20
- * make a whole lot of sense. {@link Crypt_AES::setBlockLength() setBlockLength()}, for instance. Calling that function,
21
  * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
22
  *
23
  * Here's a short example of how to use this library:
@@ -74,8 +74,8 @@ if (!class_exists('Crypt_Rijndael')) {
74
 
75
  /**#@+
76
  * @access public
77
- * @see Crypt_AES::encrypt()
78
- * @see Crypt_AES::decrypt()
79
  */
80
  /**
81
  * Encrypt / decrypt using the Counter mode.
@@ -124,7 +124,7 @@ class Crypt_AES extends Crypt_Rijndael
124
  * The namespace used by the cipher for its constants.
125
  *
126
  * @see Crypt_Base::const_namespace
127
- * @var String
128
  * @access private
129
  */
130
  var $const_namespace = 'AES';
@@ -136,7 +136,7 @@ class Crypt_AES extends Crypt_Rijndael
136
  *
137
  * @see Crypt_Rijndael::setBlockLength()
138
  * @access public
139
- * @param Integer $length
140
  */
141
  function setBlockLength($length)
142
  {
@@ -151,7 +151,7 @@ class Crypt_AES extends Crypt_Rijndael
151
  *
152
  * @see Crypt_Rijndael:setKeyLength()
153
  * @access public
154
- * @param Integer $length
155
  */
156
  function setKeyLength($length)
157
  {
@@ -173,7 +173,7 @@ class Crypt_AES extends Crypt_Rijndael
173
  * @see Crypt_Rijndael:setKey()
174
  * @see setKeyLength()
175
  * @access public
176
- * @param String $key
177
  */
178
  function setKey($key)
179
  {
@@ -183,13 +183,13 @@ class Crypt_AES extends Crypt_Rijndael
183
  $length = strlen($key);
184
  switch (true) {
185
  case $length <= 16:
186
- $this->key_size = 16;
187
  break;
188
  case $length <= 24:
189
- $this->key_size = 24;
190
  break;
191
  default:
192
- $this->key_size = 32;
193
  }
194
  $this->_setEngine();
195
  }
7
  *
8
  * PHP versions 4 and 5
9
  *
10
+ * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
11
  * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
12
  * to save one include_once().
13
  *
14
+ * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
15
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
16
+ * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
17
  * is called, again, at which point, it'll be recalculated.
18
  *
19
  * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
20
+ * make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function,
21
  * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
22
  *
23
  * Here's a short example of how to use this library:
74
 
75
  /**#@+
76
  * @access public
77
+ * @see self::encrypt()
78
+ * @see self::decrypt()
79
  */
80
  /**
81
  * Encrypt / decrypt using the Counter mode.
124
  * The namespace used by the cipher for its constants.
125
  *
126
  * @see Crypt_Base::const_namespace
127
+ * @var string
128
  * @access private
129
  */
130
  var $const_namespace = 'AES';
136
  *
137
  * @see Crypt_Rijndael::setBlockLength()
138
  * @access public
139
+ * @param int $length
140
  */
141
  function setBlockLength($length)
142
  {
151
  *
152
  * @see Crypt_Rijndael:setKeyLength()
153
  * @access public
154
+ * @param int $length
155
  */
156
  function setKeyLength($length)
157
  {
173
  * @see Crypt_Rijndael:setKey()
174
  * @see setKeyLength()
175
  * @access public
176
+ * @param string $key
177
  */
178
  function setKey($key)
179
  {
183
  $length = strlen($key);
184
  switch (true) {
185
  case $length <= 16:
186
+ $this->key_length = 16;
187
  break;
188
  case $length <= 24:
189
+ $this->key_length = 24;
190
  break;
191
  default:
192
+ $this->key_length = 32;
193
  }
194
  $this->_setEngine();
195
  }
phpseclib/Crypt/Base.php CHANGED
@@ -1,2539 +1,2616 @@
1
- <?php
2
-
3
- /**
4
- * Base Class for all Crypt_* cipher classes
5
- *
6
- * PHP versions 4 and 5
7
- *
8
- * Internally for phpseclib developers:
9
- * If you plan to add a new cipher class, please note following rules:
10
- *
11
- * - The new Crypt_* cipher class should extend Crypt_Base
12
- *
13
- * - Following methods are then required to be overridden/overloaded:
14
- *
15
- * - _encryptBlock()
16
- *
17
- * - _decryptBlock()
18
- *
19
- * - _setupKey()
20
- *
21
- * - All other methods are optional to be overridden/overloaded
22
- *
23
- * - Look at the source code of the current ciphers how they extend Crypt_Base
24
- * and take one of them as a start up for the new cipher class.
25
- *
26
- * - Please read all the other comments/notes/hints here also for each class var/method
27
- *
28
- * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
29
- * of this software and associated documentation files (the "Software"), to deal
30
- * in the Software without restriction, including without limitation the rights
31
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32
- * copies of the Software, and to permit persons to whom the Software is
33
- * furnished to do so, subject to the following conditions:
34
- *
35
- * The above copyright notice and this permission notice shall be included in
36
- * all copies or substantial portions of the Software.
37
- *
38
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
- * THE SOFTWARE.
45
- *
46
- * @category Crypt
47
- * @package Crypt_Base
48
- * @author Jim Wigginton <terrafrost@php.net>
49
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
50
- * @copyright 2007 Jim Wigginton
51
- * @license http://www.opensource.org/licenses/mit-license.html MIT License
52
- * @link http://phpseclib.sourceforge.net
53
- */
54
-
55
- /**#@+
56
- * @access public
57
- * @see Crypt_Base::encrypt()
58
- * @see Crypt_Base::decrypt()
59
- */
60
- /**
61
- * Encrypt / decrypt using the Counter mode.
62
- *
63
- * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
64
- *
65
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
66
- */
67
- define('CRYPT_MODE_CTR', -1);
68
- /**
69
- * Encrypt / decrypt using the Electronic Code Book mode.
70
- *
71
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
72
- */
73
- define('CRYPT_MODE_ECB', 1);
74
- /**
75
- * Encrypt / decrypt using the Code Book Chaining mode.
76
- *
77
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
78
- */
79
- define('CRYPT_MODE_CBC', 2);
80
- /**
81
- * Encrypt / decrypt using the Cipher Feedback mode.
82
- *
83
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
84
- */
85
- define('CRYPT_MODE_CFB', 3);
86
- /**
87
- * Encrypt / decrypt using the Output Feedback mode.
88
- *
89
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
90
- */
91
- define('CRYPT_MODE_OFB', 4);
92
- /**
93
- * Encrypt / decrypt using streaming mode.
94
- */
95
- define('CRYPT_MODE_STREAM', 5);
96
- /**#@-*/
97
-
98
- /**#@+
99
- * @access private
100
- * @see Crypt_Base::Crypt_Base()
101
- * @internal These constants are for internal use only
102
- */
103
- /**
104
- * Base value for the internal implementation $engine switch
105
- */
106
- define('CRYPT_ENGINE_INTERNAL', 1);
107
- /**
108
- * Base value for the mcrypt implementation $engine switch
109
- */
110
- define('CRYPT_ENGINE_MCRYPT', 2);
111
- /**
112
- * Base value for the OpenSSL implementation $engine switch
113
- */
114
- define('CRYPT_ENGINE_OPENSSL', 3);
115
- /**#@-*/
116
-
117
- /**
118
- * Base Class for all Crypt_* cipher classes
119
- *
120
- * @package Crypt_Base
121
- * @author Jim Wigginton <terrafrost@php.net>
122
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
123
- * @access public
124
- */
125
- class Crypt_Base
126
- {
127
- /**
128
- * The Encryption Mode
129
- *
130
- * @see Crypt_Base::Crypt_Base()
131
- * @var Integer
132
- * @access private
133
- */
134
- var $mode;
135
-
136
- /**
137
- * The Block Length of the block cipher
138
- *
139
- * @var Integer
140
- * @access private
141
- */
142
- var $block_size = 16;
143
-
144
- /**
145
- * The Key
146
- *
147
- * @see Crypt_Base::setKey()
148
- * @var String
149
- * @access private
150
- */
151
- var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
152
-
153
- /**
154
- * The Initialization Vector
155
- *
156
- * @see Crypt_Base::setIV()
157
- * @var String
158
- * @access private
159
- */
160
- var $iv;
161
-
162
- /**
163
- * A "sliding" Initialization Vector
164
- *
165
- * @see Crypt_Base::enableContinuousBuffer()
166
- * @see Crypt_Base::_clearBuffers()
167
- * @var String
168
- * @access private
169
- */
170
- var $encryptIV;
171
-
172
- /**
173
- * A "sliding" Initialization Vector
174
- *
175
- * @see Crypt_Base::enableContinuousBuffer()
176
- * @see Crypt_Base::_clearBuffers()
177
- * @var String
178
- * @access private
179
- */
180
- var $decryptIV;
181
-
182
- /**
183
- * Continuous Buffer status
184
- *
185
- * @see Crypt_Base::enableContinuousBuffer()
186
- * @var Boolean
187
- * @access private
188
- */
189
- var $continuousBuffer = false;
190
-
191
- /**
192
- * Encryption buffer for CTR, OFB and CFB modes
193
- *
194
- * @see Crypt_Base::encrypt()
195
- * @see Crypt_Base::_clearBuffers()
196
- * @var Array
197
- * @access private
198
- */
199
- var $enbuffer;
200
-
201
- /**
202
- * Decryption buffer for CTR, OFB and CFB modes
203
- *
204
- * @see Crypt_Base::decrypt()
205
- * @see Crypt_Base::_clearBuffers()
206
- * @var Array
207
- * @access private
208
- */
209
- var $debuffer;
210
-
211
- /**
212
- * mcrypt resource for encryption
213
- *
214
- * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
215
- * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
216
- *
217
- * @see Crypt_Base::encrypt()
218
- * @var Resource
219
- * @access private
220
- */
221
- var $enmcrypt;
222
-
223
- /**
224
- * mcrypt resource for decryption
225
- *
226
- * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
227
- * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
228
- *
229
- * @see Crypt_Base::decrypt()
230
- * @var Resource
231
- * @access private
232
- */
233
- var $demcrypt;
234
-
235
- /**
236
- * Does the enmcrypt resource need to be (re)initialized?
237
- *
238
- * @see Crypt_Twofish::setKey()
239
- * @see Crypt_Twofish::setIV()
240
- * @var Boolean
241
- * @access private
242
- */
243
- var $enchanged = true;
244
-
245
- /**
246
- * Does the demcrypt resource need to be (re)initialized?
247
- *
248
- * @see Crypt_Twofish::setKey()
249
- * @see Crypt_Twofish::setIV()
250
- * @var Boolean
251
- * @access private
252
- */
253
- var $dechanged = true;
254
-
255
- /**
256
- * mcrypt resource for CFB mode
257
- *
258
- * mcrypt's CFB mode, in (and only in) buffered context,
259
- * is broken, so phpseclib implements the CFB mode by it self,
260
- * even when the mcrypt php extension is available.
261
- *
262
- * In order to do the CFB-mode work (fast) phpseclib
263
- * use a separate ECB-mode mcrypt resource.
264
- *
265
- * @link http://phpseclib.sourceforge.net/cfb-demo.phps
266
- * @see Crypt_Base::encrypt()
267
- * @see Crypt_Base::decrypt()
268
- * @see Crypt_Base::_setupMcrypt()
269
- * @var Resource
270
- * @access private
271
- */
272
- var $ecb;
273
-
274
- /**
275
- * Optimizing value while CFB-encrypting
276
- *
277
- * Only relevant if $continuousBuffer enabled
278
- * and $engine == CRYPT_ENGINE_MCRYPT
279
- *
280
- * It's faster to re-init $enmcrypt if
281
- * $buffer bytes > $cfb_init_len than
282
- * using the $ecb resource furthermore.
283
- *
284
- * This value depends of the chosen cipher
285
- * and the time it would be needed for it's
286
- * initialization [by mcrypt_generic_init()]
287
- * which, typically, depends on the complexity
288
- * on its internaly Key-expanding algorithm.
289
- *
290
- * @see Crypt_Base::encrypt()
291
- * @var Integer
292
- * @access private
293
- */
294
- var $cfb_init_len = 600;
295
-
296
- /**
297
- * Does internal cipher state need to be (re)initialized?
298
- *
299
- * @see setKey()
300
- * @see setIV()
301
- * @see disableContinuousBuffer()
302
- * @var Boolean
303
- * @access private
304
- */
305
- var $changed = true;
306
-
307
- /**
308
- * Padding status
309
- *
310
- * @see Crypt_Base::enablePadding()
311
- * @var Boolean
312
- * @access private
313
- */
314
- var $padding = true;
315
-
316
- /**
317
- * Is the mode one that is paddable?
318
- *
319
- * @see Crypt_Base::Crypt_Base()
320
- * @var Boolean
321
- * @access private
322
- */
323
- var $paddable = false;
324
-
325
- /**
326
- * Holds which crypt engine internaly should be use,
327
- * which will be determined automatically on __construct()
328
- *
329
- * Currently available $engines are:
330
- * - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
331
- * - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
332
- * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
333
- *
334
- * @see Crypt_Base::_setEngine()
335
- * @see Crypt_Base::encrypt()
336
- * @see Crypt_Base::decrypt()
337
- * @var Integer
338
- * @access private
339
- */
340
- var $engine;
341
-
342
- /**
343
- * Holds the preferred crypt engine
344
- *
345
- * @see Crypt_Base::_setEngine()
346
- * @see Crypt_Base::setPreferredEngine()
347
- * @var Integer
348
- * @access private
349
- */
350
- var $preferredEngine;
351
-
352
- /**
353
- * The mcrypt specific name of the cipher
354
- *
355
- * Only used if $engine == CRYPT_ENGINE_MCRYPT
356
- *
357
- * @link http://www.php.net/mcrypt_module_open
358
- * @link http://www.php.net/mcrypt_list_algorithms
359
- * @see Crypt_Base::_setupMcrypt()
360
- * @var String
361
- * @access private
362
- */
363
- var $cipher_name_mcrypt;
364
-
365
- /**
366
- * The openssl specific name of the cipher
367
- *
368
- * Only used if $engine == CRYPT_ENGINE_OPENSSL
369
- *
370
- * @link http://www.php.net/openssl-get-cipher-methods
371
- * @var String
372
- * @access private
373
- */
374
- var $cipher_name_openssl;
375
-
376
- /**
377
- * The openssl specific name of the cipher in ECB mode
378
- *
379
- * If OpenSSL does not support the mode we're trying to use (CTR)
380
- * it can still be emulated with ECB mode.
381
- *
382
- * @link http://www.php.net/openssl-get-cipher-methods
383
- * @var String
384
- * @access private
385
- */
386
- var $cipher_name_openssl_ecb;
387
-
388
- /**
389
- * The default password key_size used by setPassword()
390
- *
391
- * @see Crypt_Base::setPassword()
392
- * @var Integer
393
- * @access private
394
- */
395
- var $password_key_size = 32;
396
-
397
- /**
398
- * The default salt used by setPassword()
399
- *
400
- * @see Crypt_Base::setPassword()
401
- * @var String
402
- * @access private
403
- */
404
- var $password_default_salt = 'phpseclib/salt';
405
-
406
- /**
407
- * The namespace used by the cipher for its constants.
408
- *
409
- * ie: AES.php is using CRYPT_AES_MODE_* for its constants
410
- * so $const_namespace is AES
411
- *
412
- * DES.php is using CRYPT_DES_MODE_* for its constants
413
- * so $const_namespace is DES... and so on
414
- *
415
- * All CRYPT_<$const_namespace>_MODE_* are aliases of
416
- * the generic CRYPT_MODE_* constants, so both could be used
417
- * for each cipher.
418
- *
419
- * Example:
420
- * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
421
- * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
422
- *
423
- * @see Crypt_Base::Crypt_Base()
424
- * @var String
425
- * @access private
426
- */
427
- var $const_namespace;
428
-
429
- /**
430
- * The name of the performance-optimized callback function
431
- *
432
- * Used by encrypt() / decrypt()
433
- * only if $engine == CRYPT_ENGINE_INTERNAL
434
- *
435
- * @see Crypt_Base::encrypt()
436
- * @see Crypt_Base::decrypt()
437
- * @see Crypt_Base::_setupInlineCrypt()
438
- * @see Crypt_Base::$use_inline_crypt
439
- * @var Callback
440
- * @access private
441
- */
442
- var $inline_crypt;
443
-
444
- /**
445
- * Holds whether performance-optimized $inline_crypt() can/should be used.
446
- *
447
- * @see Crypt_Base::encrypt()
448
- * @see Crypt_Base::decrypt()
449
- * @see Crypt_Base::inline_crypt
450
- * @var mixed
451
- * @access private
452
- */
453
- var $use_inline_crypt;
454
-
455
- /**
456
- * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
457
- *
458
- * @see Crypt_Base::_openssl_ctr_process()
459
- * @var Boolean
460
- * @access private
461
- */
462
- var $openssl_emulate_ctr = false;
463
-
464
- /**
465
- * Determines what options are passed to openssl_encrypt/decrypt
466
- *
467
- * @see Crypt_Base::isValidEngine()
468
- * @var mixed
469
- * @access private
470
- */
471
- var $openssl_options;
472
-
473
- /**
474
- * Default Constructor.
475
- *
476
- * Determines whether or not the mcrypt extension should be used.
477
- *
478
- * $mode could be:
479
- *
480
- * - CRYPT_MODE_ECB
481
- *
482
- * - CRYPT_MODE_CBC
483
- *
484
- * - CRYPT_MODE_CTR
485
- *
486
- * - CRYPT_MODE_CFB
487
- *
488
- * - CRYPT_MODE_OFB
489
- *
490
- * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
491
- *
492
- * If not explicitly set, CRYPT_MODE_CBC will be used.
493
- *
494
- * @param optional Integer $mode
495
- * @access public
496
- */
497
- function Crypt_Base($mode = CRYPT_MODE_CBC)
498
- {
499
- // $mode dependent settings
500
- switch ($mode) {
501
- case CRYPT_MODE_ECB:
502
- $this->paddable = true;
503
- $this->mode = CRYPT_MODE_ECB;
504
- break;
505
- case CRYPT_MODE_CTR:
506
- case CRYPT_MODE_CFB:
507
- case CRYPT_MODE_OFB:
508
- case CRYPT_MODE_STREAM:
509
- $this->mode = $mode;
510
- break;
511
- case CRYPT_MODE_CBC:
512
- default:
513
- $this->paddable = true;
514
- $this->mode = CRYPT_MODE_CBC;
515
- }
516
-
517
- $this->_setEngine();
518
-
519
- // Determining whether inline crypting can be used by the cipher
520
- if ($this->use_inline_crypt !== false && function_exists('create_function')) {
521
- $this->use_inline_crypt = true;
522
- }
523
- }
524
-
525
- /**
526
- * Sets the initialization vector. (optional)
527
- *
528
- * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
529
- * to be all zero's.
530
- *
531
- * @access public
532
- * @param String $iv
533
- * @internal Can be overwritten by a sub class, but does not have to be
534
- */
535
- function setIV($iv)
536
- {
537
- if ($this->mode == CRYPT_MODE_ECB) {
538
- return;
539
- }
540
-
541
- $this->iv = $iv;
542
- $this->changed = true;
543
- }
544
-
545
- /**
546
- * Sets the key.
547
- *
548
- * The min/max length(s) of the key depends on the cipher which is used.
549
- * If the key not fits the length(s) of the cipher it will paded with null bytes
550
- * up to the closest valid key length. If the key is more than max length,
551
- * we trim the excess bits.
552
- *
553
- * If the key is not explicitly set, it'll be assumed to be all null bytes.
554
- *
555
- * @access public
556
- * @param String $key
557
- * @internal Could, but not must, extend by the child Crypt_* class
558
- */
559
- function setKey($key)
560
- {
561
- $this->key = $key;
562
- $this->changed = true;
563
- $this->_setEngine();
564
- }
565
-
566
- /**
567
- * Sets the password.
568
- *
569
- * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
570
- * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
571
- * $hash, $salt, $count, $dkLen
572
- *
573
- * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
574
- *
575
- * @see Crypt/Hash.php
576
- * @param String $password
577
- * @param optional String $method
578
- * @return Boolean
579
- * @access public
580
- * @internal Could, but not must, extend by the child Crypt_* class
581
- */
582
- function setPassword($password, $method = 'pbkdf2')
583
- {
584
- $key = '';
585
-
586
- switch ($method) {
587
- default: // 'pbkdf2' or 'pbkdf1'
588
- $func_args = func_get_args();
589
-
590
- // Hash function
591
- $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
592
-
593
- // WPA and WPA2 use the SSID as the salt
594
- $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
595
-
596
- // RFC2898#section-4.2 uses 1,000 iterations by default
597
- // WPA and WPA2 use 4,096.
598
- $count = isset($func_args[4]) ? $func_args[4] : 1000;
599
-
600
- // Keylength
601
- if (isset($func_args[5])) {
602
- $dkLen = $func_args[5];
603
- } else {
604
- $dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size;
605
- }
606
-
607
- switch (true) {
608
- case $method == 'pbkdf1':
609
- if (!class_exists('Crypt_Hash')) {
610
- include_once 'Crypt/Hash.php';
611
- }
612
- $hashObj = new Crypt_Hash();
613
- $hashObj->setHash($hash);
614
- if ($dkLen > $hashObj->getLength()) {
615
- user_error('Derived key too long');
616
- return false;
617
- }
618
- $t = $password . $salt;
619
- for ($i = 0; $i < $count; ++$i) {
620
- $t = $hashObj->hash($t);
621
- }
622
- $key = substr($t, 0, $dkLen);
623
-
624
- $this->setKey(substr($key, 0, $dkLen >> 1));
625
- $this->setIV(substr($key, $dkLen >> 1));
626
-
627
- return true;
628
- // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
629
- case !function_exists('hash_pbkdf2'):
630
- case !function_exists('hash_algos'):
631
- case !in_array($hash, hash_algos()):
632
- if (!class_exists('Crypt_Hash')) {
633
- include_once 'Crypt/Hash.php';
634
- }
635
- $i = 1;
636
- while (strlen($key) < $dkLen) {
637
- $hmac = new Crypt_Hash();
638
- $hmac->setHash($hash);
639
- $hmac->setKey($password);
640
- $f = $u = $hmac->hash($salt . pack('N', $i++));
641
- for ($j = 2; $j <= $count; ++$j) {
642
- $u = $hmac->hash($u);
643
- $f^= $u;
644
- }
645
- $key.= $f;
646
- }
647
- $key = substr($key, 0, $dkLen);
648
- break;
649
- default:
650
- $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
651
- }
652
- }
653
-
654
- $this->setKey($key);
655
-
656
- return true;
657
- }
658
-
659
- /**
660
- * Encrypts a message.
661
- *
662
- * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
663
- * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
664
- * necessary are discussed in the following
665
- * URL:
666
- *
667
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
668
- *
669
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
670
- * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
671
- * length.
672
- *
673
- * @see Crypt_Base::decrypt()
674
- * @access public
675
- * @param String $plaintext
676
- * @return String $ciphertext
677
- * @internal Could, but not must, extend by the child Crypt_* class
678
- */
679
- function encrypt($plaintext)
680
- {
681
- if ($this->paddable) {
682
- $plaintext = $this->_pad($plaintext);
683
- }
684
-
685
- if ($this->engine === CRYPT_ENGINE_OPENSSL) {
686
- if ($this->changed) {
687
- $this->_clearBuffers();
688
- $this->changed = false;
689
- }
690
- switch ($this->mode) {
691
- case CRYPT_MODE_STREAM:
692
- return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
693
- case CRYPT_MODE_ECB:
694
- $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
695
- return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
696
- case CRYPT_MODE_CBC:
697
- $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
698
- if ($this->continuousBuffer) {
699
- $this->encryptIV = substr($result, -$this->block_size);
700
- }
701
- return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
702
- case CRYPT_MODE_CTR:
703
- return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
704
- case CRYPT_MODE_CFB:
705
- // cfb loosely routines inspired by openssl's:
706
- // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
707
- $ciphertext = '';
708
- if ($this->continuousBuffer) {
709
- $iv = &$this->encryptIV;
710
- $pos = &$this->enbuffer['pos'];
711
- } else {
712
- $iv = $this->encryptIV;
713
- $pos = 0;
714
- }
715
- $len = strlen($plaintext);
716
- $i = 0;
717
- if ($pos) {
718
- $orig_pos = $pos;
719
- $max = $this->block_size - $pos;
720
- if ($len >= $max) {
721
- $i = $max;
722
- $len-= $max;
723
- $pos = 0;
724
- } else {
725
- $i = $len;
726
- $pos+= $len;
727
- $len = 0;
728
- }
729
- // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
730
- $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
731
- $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
732
- $plaintext = substr($plaintext, $i);
733
- }
734
-
735
- $overflow = $len % $this->block_size;
736
-
737
- if ($overflow) {
738
- $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
739
- $iv = $this->_string_pop($ciphertext, $this->block_size);
740
-
741
- $size = $len - $overflow;
742
- $block = $iv ^ substr($plaintext, -$overflow);
743
- $iv = substr_replace($iv, $block, 0, $overflow);
744
- $ciphertext.= $block;
745
- $pos = $overflow;
746
- } else if ($len) {
747
- $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
748
- $iv = substr($ciphertext, -$this->block_size);
749
- }
750
-
751
- return $ciphertext;
752
- case CRYPT_MODE_OFB:
753
- return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
754
- }
755
- }
756
-
757
- if ($this->engine === CRYPT_ENGINE_MCRYPT) {
758
- if ($this->changed) {
759
- $this->_setupMcrypt();
760
- $this->changed = false;
761
- }
762
- if ($this->enchanged) {
763
- mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
764
- $this->enchanged = false;
765
- }
766
-
767
- // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
768
- // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
769
- // rewritten CFB implementation the above outputs the same thing twice.
770
- if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
771
- $block_size = $this->block_size;
772
- $iv = &$this->encryptIV;
773
- $pos = &$this->enbuffer['pos'];
774
- $len = strlen($plaintext);
775
- $ciphertext = '';
776
- $i = 0;
777
- if ($pos) {
778
- $orig_pos = $pos;
779
- $max = $block_size - $pos;
780
- if ($len >= $max) {
781
- $i = $max;
782
- $len-= $max;
783
- $pos = 0;
784
- } else {
785
- $i = $len;
786
- $pos+= $len;
787
- $len = 0;
788
- }
789
- $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
790
- $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
791
- $this->enbuffer['enmcrypt_init'] = true;
792
- }
793
- if ($len >= $block_size) {
794
- if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
795
- if ($this->enbuffer['enmcrypt_init'] === true) {
796
- mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
797
- $this->enbuffer['enmcrypt_init'] = false;
798
- }
799
- $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
800
- $iv = substr($ciphertext, -$block_size);
801
- $len%= $block_size;
802
- } else {
803
- while ($len >= $block_size) {
804
- $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
805
- $ciphertext.= $iv;
806
- $len-= $block_size;
807
- $i+= $block_size;
808
- }
809
- }
810
- }
811
-
812
- if ($len) {
813
- $iv = mcrypt_generic($this->ecb, $iv);
814
- $block = $iv ^ substr($plaintext, -$len);
815
- $iv = substr_replace($iv, $block, 0, $len);
816
- $ciphertext.= $block;
817
- $pos = $len;
818
- }
819
-
820
- return $ciphertext;
821
- }
822
-
823
- $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
824
-
825
- if (!$this->continuousBuffer) {
826
- mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
827
- }
828
-
829
- return $ciphertext;
830
- }
831
-
832
- if ($this->changed) {
833
- $this->_setup();
834
- $this->changed = false;
835
- }
836
- if ($this->use_inline_crypt) {
837
- $inline = $this->inline_crypt;
838
- return $inline('encrypt', $this, $plaintext);
839
- }
840
-
841
- $buffer = &$this->enbuffer;
842
- $block_size = $this->block_size;
843
- $ciphertext = '';
844
- switch ($this->mode) {
845
- case CRYPT_MODE_ECB:
846
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
847
- $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
848
- }
849
- break;
850
- case CRYPT_MODE_CBC:
851
- $xor = $this->encryptIV;
852
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
853
- $block = substr($plaintext, $i, $block_size);
854
- $block = $this->_encryptBlock($block ^ $xor);
855
- $xor = $block;
856
- $ciphertext.= $block;
857
- }
858
- if ($this->continuousBuffer) {
859
- $this->encryptIV = $xor;
860
- }
861
- break;
862
- case CRYPT_MODE_CTR:
863
- $xor = $this->encryptIV;
864
- if (strlen($buffer['ciphertext'])) {
865
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
866
- $block = substr($plaintext, $i, $block_size);
867
- if (strlen($block) > strlen($buffer['ciphertext'])) {
868
- $buffer['ciphertext'].= $this->_encryptBlock($xor);
869
- }
870
- $this->_increment_str($xor);
871
- $key = $this->_string_shift($buffer['ciphertext'], $block_size);
872
- $ciphertext.= $block ^ $key;
873
- }
874
- } else {
875
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
876
- $block = substr($plaintext, $i, $block_size);
877
- $key = $this->_encryptBlock($xor);
878
- $this->_increment_str($xor);
879
- $ciphertext.= $block ^ $key;
880
- }
881
- }
882
- if ($this->continuousBuffer) {
883
- $this->encryptIV = $xor;
884
- if ($start = strlen($plaintext) % $block_size) {
885
- $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
886
- }
887
- }
888
- break;
889
- case CRYPT_MODE_CFB:
890
- // cfb loosely routines inspired by openssl's:
891
- // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
892
- if ($this->continuousBuffer) {
893
- $iv = &$this->encryptIV;
894
- $pos = &$buffer['pos'];
895
- } else {
896
- $iv = $this->encryptIV;
897
- $pos = 0;
898
- }
899
- $len = strlen($plaintext);
900
- $i = 0;
901
- if ($pos) {
902
- $orig_pos = $pos;
903
- $max = $block_size - $pos;
904
- if ($len >= $max) {
905
- $i = $max;
906
- $len-= $max;
907
- $pos = 0;
908
- } else {
909
- $i = $len;
910
- $pos+= $len;
911
- $len = 0;
912
- }
913
- // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
914
- $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
915
- $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
916
- }
917
- while ($len >= $block_size) {
918
- $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
919
- $ciphertext.= $iv;
920
- $len-= $block_size;
921
- $i+= $block_size;
922
- }
923
- if ($len) {
924
- $iv = $this->_encryptBlock($iv);
925
- $block = $iv ^ substr($plaintext, $i);
926
- $iv = substr_replace($iv, $block, 0, $len);
927
- $ciphertext.= $block;
928
- $pos = $len;
929
- }
930
- break;
931
- case CRYPT_MODE_OFB:
932
- $xor = $this->encryptIV;
933
- if (strlen($buffer['xor'])) {
934
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
935
- $block = substr($plaintext, $i, $block_size);
936
- if (strlen($block) > strlen($buffer['xor'])) {
937
- $xor = $this->_encryptBlock($xor);
938
- $buffer['xor'].= $xor;
939
- }
940
- $key = $this->_string_shift($buffer['xor'], $block_size);
941
- $ciphertext.= $block ^ $key;
942
- }
943
- } else {
944
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
945
- $xor = $this->_encryptBlock($xor);
946
- $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
947
- }
948
- $key = $xor;
949
- }
950
- if ($this->continuousBuffer) {
951
- $this->encryptIV = $xor;
952
- if ($start = strlen($plaintext) % $block_size) {
953
- $buffer['xor'] = substr($key, $start) . $buffer['xor'];
954
- }
955
- }
956
- break;
957
- case CRYPT_MODE_STREAM:
958
- $ciphertext = $this->_encryptBlock($plaintext);
959
- break;
960
- }
961
-
962
- return $ciphertext;
963
- }
964
-
965
- /**
966
- * Decrypts a message.
967
- *
968
- * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
969
- * it is.
970
- *
971
- * @see Crypt_Base::encrypt()
972
- * @access public
973
- * @param String $ciphertext
974
- * @return String $plaintext
975
- * @internal Could, but not must, extend by the child Crypt_* class
976
- */
977
- function decrypt($ciphertext)
978
- {
979
- if ($this->paddable) {
980
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
981
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
982
- $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
983
- }
984
-
985
- if ($this->engine === CRYPT_ENGINE_OPENSSL) {
986
- if ($this->changed) {
987
- $this->_clearBuffers();
988
- $this->changed = false;
989
- }
990
- switch ($this->mode) {
991
- case CRYPT_MODE_STREAM:
992
- $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
993
- break;
994
- case CRYPT_MODE_ECB:
995
- if (!defined('OPENSSL_RAW_DATA')) {
996
- $ciphetext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
997
- }
998
- $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
999
- break;
1000
- case CRYPT_MODE_CBC:
1001
- if (!defined('OPENSSL_RAW_DATA')) {
1002
- $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
1003
- $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
1004
- }
1005
- $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1006
- if ($this->continuousBuffer) {
1007
- $this->decryptIV = substr($ciphertext, -$this->block_size);
1008
- }
1009
- break;
1010
- case CRYPT_MODE_CTR:
1011
- $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1012
- break;
1013
- case CRYPT_MODE_CFB:
1014
- // cfb loosely routines inspired by openssl's:
1015
- // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1016
- $plaintext = '';
1017
- if ($this->continuousBuffer) {
1018
- $iv = &$this->decryptIV;
1019
- $pos = &$this->buffer['pos'];
1020
- } else {
1021
- $iv = $this->decryptIV;
1022
- $pos = 0;
1023
- }
1024
- $len = strlen($ciphertext);
1025
- $i = 0;
1026
- if ($pos) {
1027
- $orig_pos = $pos;
1028
- $max = $this->block_size - $pos;
1029
- if ($len >= $max) {
1030
- $i = $max;
1031
- $len-= $max;
1032
- $pos = 0;
1033
- } else {
1034
- $i = $len;
1035
- $pos+= $len;
1036
- $len = 0;
1037
- }
1038
- // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1039
- $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1040
- $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1041
- $ciphertext = substr($ciphertext, $i);
1042
- }
1043
- $overflow = $len % $this->block_size;
1044
- if ($overflow) {
1045
- $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1046
- if ($len - $overflow) {
1047
- $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1048
- }
1049
- $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1050
- $plaintext.= $iv ^ substr($ciphertext, -$overflow);
1051
- $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1052
- $pos = $overflow;
1053
- } else if ($len) {
1054
- $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1055
- $iv = substr($ciphertext, -$this->block_size);
1056
- }
1057
- break;
1058
- case CRYPT_MODE_OFB:
1059
- $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1060
- }
1061
-
1062
- return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1063
- }
1064
-
1065
- if ($this->engine === CRYPT_ENGINE_MCRYPT) {
1066
- $block_size = $this->block_size;
1067
- if ($this->changed) {
1068
- $this->_setupMcrypt();
1069
- $this->changed = false;
1070
- }
1071
- if ($this->dechanged) {
1072
- mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1073
- $this->dechanged = false;
1074
- }
1075
-
1076
- if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
1077
- $iv = &$this->decryptIV;
1078
- $pos = &$this->debuffer['pos'];
1079
- $len = strlen($ciphertext);
1080
- $plaintext = '';
1081
- $i = 0;
1082
- if ($pos) {
1083
- $orig_pos = $pos;
1084
- $max = $block_size - $pos;
1085
- if ($len >= $max) {
1086
- $i = $max;
1087
- $len-= $max;
1088
- $pos = 0;
1089
- } else {
1090
- $i = $len;
1091
- $pos+= $len;
1092
- $len = 0;
1093
- }
1094
- // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1095
- $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1096
- $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1097
- }
1098
- if ($len >= $block_size) {
1099
- $cb = substr($ciphertext, $i, $len - $len % $block_size);
1100
- $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1101
- $iv = substr($cb, -$block_size);
1102
- $len%= $block_size;
1103
- }
1104
- if ($len) {
1105
- $iv = mcrypt_generic($this->ecb, $iv);
1106
- $plaintext.= $iv ^ substr($ciphertext, -$len);
1107
- $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1108
- $pos = $len;
1109
- }
1110
-
1111
- return $plaintext;
1112
- }
1113
-
1114
- $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
1115
-
1116
- if (!$this->continuousBuffer) {
1117
- mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1118
- }
1119
-
1120
- return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1121
- }
1122
-
1123
- if ($this->changed) {
1124
- $this->_setup();
1125
- $this->changed = false;
1126
- }
1127
- if ($this->use_inline_crypt) {
1128
- $inline = $this->inline_crypt;
1129
- return $inline('decrypt', $this, $ciphertext);
1130
- }
1131
-
1132
- $block_size = $this->block_size;
1133
-
1134
- $buffer = &$this->debuffer;
1135
- $plaintext = '';
1136
- switch ($this->mode) {
1137
- case CRYPT_MODE_ECB:
1138
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1139
- $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
1140
- }
1141
- break;
1142
- case CRYPT_MODE_CBC:
1143
- $xor = $this->decryptIV;
1144
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1145
- $block = substr($ciphertext, $i, $block_size);
1146
- $plaintext.= $this->_decryptBlock($block) ^ $xor;
1147
- $xor = $block;
1148
- }
1149
- if ($this->continuousBuffer) {
1150
- $this->decryptIV = $xor;
1151
- }
1152
- break;
1153
- case CRYPT_MODE_CTR:
1154
- $xor = $this->decryptIV;
1155
- if (strlen($buffer['ciphertext'])) {
1156
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1157
- $block = substr($ciphertext, $i, $block_size);
1158
- if (strlen($block) > strlen($buffer['ciphertext'])) {
1159
- $buffer['ciphertext'].= $this->_encryptBlock($xor);
1160
- $this->_increment_str($xor);
1161
- }
1162
- $key = $this->_string_shift($buffer['ciphertext'], $block_size);
1163
- $plaintext.= $block ^ $key;
1164
- }
1165
- } else {
1166
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1167
- $block = substr($ciphertext, $i, $block_size);
1168
- $key = $this->_encryptBlock($xor);
1169
- $this->_increment_str($xor);
1170
- $plaintext.= $block ^ $key;
1171
- }
1172
- }
1173
- if ($this->continuousBuffer) {
1174
- $this->decryptIV = $xor;
1175
- if ($start = strlen($ciphertext) % $block_size) {
1176
- $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1177
- }
1178
- }
1179
- break;
1180
- case CRYPT_MODE_CFB:
1181
- if ($this->continuousBuffer) {
1182
- $iv = &$this->decryptIV;
1183
- $pos = &$buffer['pos'];
1184
- } else {
1185
- $iv = $this->decryptIV;
1186
- $pos = 0;
1187
- }
1188
- $len = strlen($ciphertext);
1189
- $i = 0;
1190
- if ($pos) {
1191
- $orig_pos = $pos;
1192
- $max = $block_size - $pos;
1193
- if ($len >= $max) {
1194
- $i = $max;
1195
- $len-= $max;
1196
- $pos = 0;
1197
- } else {
1198
- $i = $len;
1199
- $pos+= $len;
1200
- $len = 0;
1201
- }
1202
- // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1203
- $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1204
- $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1205
- }
1206
- while ($len >= $block_size) {
1207
- $iv = $this->_encryptBlock($iv);
1208
- $cb = substr($ciphertext, $i, $block_size);
1209
- $plaintext.= $iv ^ $cb;
1210
- $iv = $cb;
1211
- $len-= $block_size;
1212
- $i+= $block_size;
1213
- }
1214
- if ($len) {
1215
- $iv = $this->_encryptBlock($iv);
1216
- $plaintext.= $iv ^ substr($ciphertext, $i);
1217
- $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1218
- $pos = $len;
1219
- }
1220
- break;
1221
- case CRYPT_MODE_OFB:
1222
- $xor = $this->decryptIV;
1223
- if (strlen($buffer['xor'])) {
1224
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1225
- $block = substr($ciphertext, $i, $block_size);
1226
- if (strlen($block) > strlen($buffer['xor'])) {
1227
- $xor = $this->_encryptBlock($xor);
1228
- $buffer['xor'].= $xor;
1229
- }
1230
- $key = $this->_string_shift($buffer['xor'], $block_size);
1231
- $plaintext.= $block ^ $key;
1232
- }
1233
- } else {
1234
- for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1235
- $xor = $this->_encryptBlock($xor);
1236
- $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
1237
- }
1238
- $key = $xor;
1239
- }
1240
- if ($this->continuousBuffer) {
1241
- $this->decryptIV = $xor;
1242
- if ($start = strlen($ciphertext) % $block_size) {
1243
- $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1244
- }
1245
- }
1246
- break;
1247
- case CRYPT_MODE_STREAM:
1248
- $plaintext = $this->_decryptBlock($ciphertext);
1249
- break;
1250
- }
1251
- return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1252
- }
1253
-
1254
- /**
1255
- * OpenSSL CTR Processor
1256
- *
1257
- * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1258
- * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1259
- * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1260
- * function will emulate CTR with ECB when necesary.
1261
- *
1262
- * @see Crypt_Base::encrypt()
1263
- * @see Crypt_Base::decrypt()
1264
- * @param String $plaintext
1265
- * @param String $encryptIV
1266
- * @param Array $buffer
1267
- * @return String
1268
- * @access private
1269
- */
1270
- function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1271
- {
1272
- $ciphertext = '';
1273
-
1274
- $block_size = $this->block_size;
1275
- $key = $this->key;
1276
-
1277
- if ($this->openssl_emulate_ctr) {
1278
- $xor = $encryptIV;
1279
- if (strlen($buffer['ciphertext'])) {
1280
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1281
- $block = substr($plaintext, $i, $block_size);
1282
- if (strlen($block) > strlen($buffer['ciphertext'])) {
1283
- $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1284
- $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
1285
- $buffer['ciphertext'].= $result;
1286
- }
1287
- $this->_increment_str($xor);
1288
- $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
1289
- $ciphertext.= $block ^ $otp;
1290
- }
1291
- } else {
1292
- for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1293
- $block = substr($plaintext, $i, $block_size);
1294
- $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1295
- $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
1296
- $this->_increment_str($xor);
1297
- $ciphertext.= $block ^ $otp;
1298
- }
1299
- }
1300
- if ($this->continuousBuffer) {
1301
- $encryptIV = $xor;
1302
- if ($start = strlen($plaintext) % $block_size) {
1303
- $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1304
- }
1305
- }
1306
-
1307
- return $ciphertext;
1308
- }
1309
-
1310
- if (strlen($buffer['ciphertext'])) {
1311
- $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
1312
- $plaintext = substr($plaintext, strlen($ciphertext));
1313
-
1314
- if (!strlen($plaintext)) {
1315
- return $ciphertext;
1316
- }
1317
- }
1318
-
1319
- $overflow = strlen($plaintext) % $block_size;
1320
- if ($overflow) {
1321
- $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
1322
- $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1323
- $temp = $this->_string_pop($encrypted, $block_size);
1324
- $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
1325
- if ($this->continuousBuffer) {
1326
- $buffer['ciphertext'] = substr($temp, $overflow);
1327
- $encryptIV = $temp;
1328
- }
1329
- } else if (!strlen($buffer['ciphertext'])) {
1330
- $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1331
- $temp = $this->_string_pop($ciphertext, $block_size);
1332
- if ($this->continuousBuffer) {
1333
- $encryptIV = $temp;
1334
- }
1335
- }
1336
- if ($this->continuousBuffer) {
1337
- if (!defined('OPENSSL_RAW_DATA')) {
1338
- $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1339
- }
1340
- $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1341
- if ($overflow) {
1342
- $this->_increment_str($encryptIV);
1343
- }
1344
- }
1345
-
1346
- return $ciphertext;
1347
- }
1348
-
1349
- /**
1350
- * OpenSSL OFB Processor
1351
- *
1352
- * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1353
- * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1354
- * and Crypt_Base::decrypt().
1355
- *
1356
- * @see Crypt_Base::encrypt()
1357
- * @see Crypt_Base::decrypt()
1358
- * @param String $plaintext
1359
- * @param String $encryptIV
1360
- * @param Array $buffer
1361
- * @return String
1362
- * @access private
1363
- */
1364
- function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
1365
- {
1366
- if (strlen($buffer['xor'])) {
1367
- $ciphertext = $plaintext ^ $buffer['xor'];
1368
- $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
1369
- $plaintext = substr($plaintext, strlen($ciphertext));
1370
- } else {
1371
- $ciphertext = '';
1372
- }
1373
-
1374
- $block_size = $this->block_size;
1375
-
1376
- $len = strlen($plaintext);
1377
- $key = $this->key;
1378
- $overflow = $len % $block_size;
1379
-
1380
- if (strlen($plaintext)) {
1381
- if ($overflow) {
1382
- $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1383
- $xor = $this->_string_pop($ciphertext, $block_size);
1384
- if ($this->continuousBuffer) {
1385
- $encryptIV = $xor;
1386
- }
1387
- $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
1388
- if ($this->continuousBuffer) {
1389
- $buffer['xor'] = $xor;
1390
- }
1391
- } else {
1392
- $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1393
- if ($this->continuousBuffer) {
1394
- $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
1395
- }
1396
- }
1397
- }
1398
-
1399
- return $ciphertext;
1400
- }
1401
-
1402
- /**
1403
- * phpseclib <-> OpenSSL Mode Mapper
1404
- *
1405
- * May need to be overwritten by classes extending this one in some cases
1406
- *
1407
- * @return Integer
1408
- * @access private
1409
- */
1410
- function _openssl_translate_mode()
1411
- {
1412
- switch ($this->mode) {
1413
- case CRYPT_MODE_ECB:
1414
- return 'ecb';
1415
- case CRYPT_MODE_CBC:
1416
- return 'cbc';
1417
- case CRYPT_MODE_CTR:
1418
- return 'ctr';
1419
- case CRYPT_MODE_CFB:
1420
- return 'cfb';
1421
- case CRYPT_MODE_OFB:
1422
- return 'ofb';
1423
- }
1424
- }
1425
-
1426
- /**
1427
- * Pad "packets".
1428
- *
1429
- * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1430
- * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1431
- * pad the input so that it is of the proper length.
1432
- *
1433
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1434
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1435
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1436
- * transmitted separately)
1437
- *
1438
- * @see Crypt_Base::disablePadding()
1439
- * @access public
1440
- */
1441
- function enablePadding()
1442
- {
1443
- $this->padding = true;
1444
- }
1445
-
1446
- /**
1447
- * Do not pad packets.
1448
- *
1449
- * @see Crypt_Base::enablePadding()
1450
- * @access public
1451
- */
1452
- function disablePadding()
1453
- {
1454
- $this->padding = false;
1455
- }
1456
-
1457
- /**
1458
- * Treat consecutive "packets" as if they are a continuous buffer.
1459
- *
1460
- * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1461
- * will yield different outputs:
1462
- *
1463
- * <code>
1464
- * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1465
- * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1466
- * </code>
1467
- * <code>
1468
- * echo $rijndael->encrypt($plaintext);
1469
- * </code>
1470
- *
1471
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1472
- * another, as demonstrated with the following:
1473
- *
1474
- * <code>
1475
- * $rijndael->encrypt(substr($plaintext, 0, 16));
1476
- * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1477
- * </code>
1478
- * <code>
1479
- * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1480
- * </code>
1481
- *
1482
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1483
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1484
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1485
- *
1486
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
1487
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1488
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1489
- * however, they are also less intuitive and more likely to cause you problems.
1490
- *
1491
- * @see Crypt_Base::disableContinuousBuffer()
1492
- * @access public
1493
- * @internal Could, but not must, extend by the child Crypt_* class
1494
- */
1495
- function enableContinuousBuffer()
1496
- {
1497
- if ($this->mode == CRYPT_MODE_ECB) {
1498
- return;
1499
- }
1500
-
1501
- $this->continuousBuffer = true;
1502
-
1503
- $this->_setEngine();
1504
- }
1505
-
1506
- /**
1507
- * Treat consecutive packets as if they are a discontinuous buffer.
1508
- *
1509
- * The default behavior.
1510
- *
1511
- * @see Crypt_Base::enableContinuousBuffer()
1512
- * @access public
1513
- * @internal Could, but not must, extend by the child Crypt_* class
1514
- */
1515
- function disableContinuousBuffer()
1516
- {
1517
- if ($this->mode == CRYPT_MODE_ECB) {
1518
- return;
1519
- }
1520
- if (!$this->continuousBuffer) {
1521
- return;
1522
- }
1523
-
1524
- $this->continuousBuffer = false;
1525
- $this->changed = true;
1526
-
1527
- $this->_setEngine();
1528
- }
1529
-
1530
- /**
1531
- * Test for engine validity
1532
- *
1533
- * @see Crypt_Base::Crypt_Base()
1534
- * @param Integer $engine
1535
- * @access public
1536
- * @return Boolean
1537
- */
1538
- function isValidEngine($engine)
1539
- {
1540
- switch ($engine) {
1541
- case CRYPT_ENGINE_OPENSSL:
1542
- if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
1543
- return false;
1544
- }
1545
- $this->openssl_emulate_ctr = false;
1546
- $result = $this->cipher_name_openssl &&
1547
- extension_loaded('openssl') &&
1548
- // PHP 5.3.0 - 5.3.2 did not let you set IV's
1549
- version_compare(PHP_VERSION, '5.3.3', '>=');
1550
- if (!$result) {
1551
- return false;
1552
- }
1553
-
1554
- // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
1555
- // $options openssl_encrypt expected a boolean $raw_data.
1556
- if (!defined('OPENSSL_RAW_DATA')) {
1557
- $this->openssl_options = true;
1558
- } else {
1559
- $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1560
- }
1561
-
1562
- $methods = openssl_get_cipher_methods();
1563
- if (in_array($this->cipher_name_openssl, $methods)) {
1564
- return true;
1565
- }
1566
- // not all of openssl's symmetric cipher's support ctr. for those
1567
- // that don't we'll emulate it
1568
- switch ($this->mode) {
1569
- case CRYPT_MODE_CTR:
1570
- if (in_array($this->cipher_name_openssl_ecb, $methods)) {
1571
- $this->openssl_emulate_ctr = true;
1572
- return true;
1573
- }
1574
- }
1575
- return false;
1576
- case CRYPT_ENGINE_MCRYPT:
1577
- return $this->cipher_name_mcrypt &&
1578
- extension_loaded('mcrypt') &&
1579
- in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
1580
- case CRYPT_ENGINE_INTERNAL:
1581
- return true;
1582
- }
1583
-
1584
- return false;
1585
- }
1586
-
1587
- /**
1588
- * Sets the preferred crypt engine
1589
- *
1590
- * Currently, $engine could be:
1591
- *
1592
- * - CRYPT_ENGINE_OPENSSL [very fast]
1593
- *
1594
- * - CRYPT_ENGINE_MCRYPT [fast]
1595
- *
1596
- * - CRYPT_ENGINE_INTERNAL [slow]
1597
- *
1598
- * If the preferred crypt engine is not available the fastest available one will be used
1599
- *
1600
- * @see Crypt_Base::Crypt_Base()
1601
- * @param Integer $engine
1602
- * @access public
1603
- */
1604
- function setPreferredEngine($engine)
1605
- {
1606
- switch ($engine) {
1607
- //case CRYPT_ENGINE_OPENSSL:
1608
- case CRYPT_ENGINE_MCRYPT:
1609
- case CRYPT_ENGINE_INTERNAL:
1610
- $this->preferredEngine = $engine;
1611
- break;
1612
- default:
1613
- $this->preferredEngine = CRYPT_ENGINE_OPENSSL;
1614
- }
1615
-
1616
- $this->_setEngine();
1617
- }
1618
-
1619
- /**
1620
- * Returns the engine currently being utilized
1621
- *
1622
- * @see Crypt_Base::_setEngine()
1623
- * @access public
1624
- */
1625
- function getEngine()
1626
- {
1627
- return $this->engine;
1628
- }
1629
-
1630
- /**
1631
- * Sets the engine as appropriate
1632
- *
1633
- * @see Crypt_Base::Crypt_Base()
1634
- * @access private
1635
- */
1636
- function _setEngine()
1637
- {
1638
- $this->engine = null;
1639
-
1640
- $candidateEngines = array(
1641
- $this->preferredEngine,
1642
- CRYPT_ENGINE_OPENSSL,
1643
- CRYPT_ENGINE_MCRYPT
1644
- );
1645
- foreach ($candidateEngines as $engine) {
1646
- if ($this->isValidEngine($engine)) {
1647
- $this->engine = $engine;
1648
- break;
1649
- }
1650
- }
1651
- if (!$this->engine) {
1652
- $this->engine = CRYPT_ENGINE_INTERNAL;
1653
- }
1654
-
1655
- if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
1656
- // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
1657
- // (re)open them with the module named in $this->cipher_name_mcrypt
1658
- mcrypt_module_close($this->enmcrypt);
1659
- mcrypt_module_close($this->demcrypt);
1660
- $this->enmcrypt = null;
1661
- $this->demcrypt = null;
1662
-
1663
- if ($this->ecb) {
1664
- mcrypt_module_close($this->ecb);
1665
- $this->ecb = null;
1666
- }
1667
- }
1668
-
1669
- $this->changed = true;
1670
- }
1671
-
1672
- /**
1673
- * Encrypts a block
1674
- *
1675
- * @access private
1676
- * @param String $in
1677
- * @return String
1678
- * @internal Must be extended by the child Crypt_* class
1679
- */
1680
- function _encryptBlock($in)
1681
- {
1682
- user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1683
- }
1684
-
1685
- /**
1686
- * Decrypts a block
1687
- *
1688
- * @access private
1689
- * @param String $in
1690
- * @return String
1691
- * @internal Must be extended by the child Crypt_* class
1692
- */
1693
- function _decryptBlock($in)
1694
- {
1695
- user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1696
- }
1697
-
1698
- /**
1699
- * Setup the key (expansion)
1700
- *
1701
- * Only used if $engine == CRYPT_ENGINE_INTERNAL
1702
- *
1703
- * @see Crypt_Base::_setup()
1704
- * @access private
1705
- * @internal Must be extended by the child Crypt_* class
1706
- */
1707
- function _setupKey()
1708
- {
1709
- user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1710
- }
1711
-
1712
- /**
1713
- * Setup the CRYPT_ENGINE_INTERNAL $engine
1714
- *
1715
- * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1716
- * Used (only) if $engine == CRYPT_ENGINE_INTERNAL
1717
- *
1718
- * _setup() will be called each time if $changed === true
1719
- * typically this happens when using one or more of following public methods:
1720
- *
1721
- * - setKey()
1722
- *
1723
- * - setIV()
1724
- *
1725
- * - disableContinuousBuffer()
1726
- *
1727
- * - First run of encrypt() / decrypt() with no init-settings
1728
- *
1729
- * @see setKey()
1730
- * @see setIV()
1731
- * @see disableContinuousBuffer()
1732
- * @access private
1733
- * @internal _setup() is always called before en/decryption.
1734
- * @internal Could, but not must, extend by the child Crypt_* class
1735
- */
1736
- function _setup()
1737
- {
1738
- $this->_clearBuffers();
1739
- $this->_setupKey();
1740
-
1741
- if ($this->use_inline_crypt) {
1742
- $this->_setupInlineCrypt();
1743
- }
1744
- }
1745
-
1746
- /**
1747
- * Setup the CRYPT_ENGINE_MCRYPT $engine
1748
- *
1749
- * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1750
- * Used (only) if $engine = CRYPT_ENGINE_MCRYPT
1751
- *
1752
- * _setupMcrypt() will be called each time if $changed === true
1753
- * typically this happens when using one or more of following public methods:
1754
- *
1755
- * - setKey()
1756
- *
1757
- * - setIV()
1758
- *
1759
- * - disableContinuousBuffer()
1760
- *
1761
- * - First run of encrypt() / decrypt()
1762
- *
1763
- * @see setKey()
1764
- * @see setIV()
1765
- * @see disableContinuousBuffer()
1766
- * @access private
1767
- * @internal Could, but not must, extend by the child Crypt_* class
1768
- */
1769
- function _setupMcrypt()
1770
- {
1771
- $this->_clearBuffers();
1772
- $this->enchanged = $this->dechanged = true;
1773
-
1774
- if (!isset($this->enmcrypt)) {
1775
- static $mcrypt_modes = array(
1776
- CRYPT_MODE_CTR => 'ctr',
1777
- CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
1778
- CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
1779
- CRYPT_MODE_CFB => 'ncfb',
1780
- CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
1781
- CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
1782
- );
1783
-
1784
- $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1785
- $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1786
-
1787
- // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1788
- // to workaround mcrypt's broken ncfb implementation in buffered mode
1789
- // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1790
- if ($this->mode == CRYPT_MODE_CFB) {
1791
- $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1792
- }
1793
-
1794
- } // else should mcrypt_generic_deinit be called?
1795
-
1796
- if ($this->mode == CRYPT_MODE_CFB) {
1797
- mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1798
- }
1799
- }
1800
-
1801
- /**
1802
- * Pads a string
1803
- *
1804
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1805
- * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1806
- * chr($this->block_size - (strlen($text) % $this->block_size)
1807
- *
1808
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1809
- * and padding will, hence forth, be enabled.
1810
- *
1811
- * @see Crypt_Base::_unpad()
1812
- * @param String $text
1813
- * @access private
1814
- * @return String
1815
- */
1816
- function _pad($text)
1817
- {
1818
- $length = strlen($text);
1819
-
1820
- if (!$this->padding) {
1821
- if ($length % $this->block_size == 0) {
1822
- return $text;
1823
- } else {
1824
- user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1825
- $this->padding = true;
1826
- }
1827
- }
1828
-
1829
- $pad = $this->block_size - ($length % $this->block_size);
1830
-
1831
- return str_pad($text, $length + $pad, chr($pad));
1832
- }
1833
-
1834
- /**
1835
- * Unpads a string.
1836
- *
1837
- * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1838
- * and false will be returned.
1839
- *
1840
- * @see Crypt_Base::_pad()
1841
- * @param String $text
1842
- * @access private
1843
- * @return String
1844
- */
1845
- function _unpad($text)
1846
- {
1847
- if (!$this->padding) {
1848
- return $text;
1849
- }
1850
-
1851
- $length = ord($text[strlen($text) - 1]);
1852
-
1853
- if (!$length || $length > $this->block_size) {
1854
- return false;
1855
- }
1856
-
1857
- return substr($text, 0, -$length);
1858
- }
1859
-
1860
- /**
1861
- * Clears internal buffers
1862
- *
1863
- * Clearing/resetting the internal buffers is done everytime
1864
- * after disableContinuousBuffer() or on cipher $engine (re)init
1865
- * ie after setKey() or setIV()
1866
- *
1867
- * @access public
1868
- * @internal Could, but not must, extend by the child Crypt_* class
1869
- */
1870
- function _clearBuffers()
1871
- {
1872
- $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1873
-
1874
- // mcrypt's handling of invalid's $iv:
1875
- // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1876
- $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1877
- }
1878
-
1879
- /**
1880
- * String Shift
1881
- *
1882
- * Inspired by array_shift
1883
- *
1884
- * @param String $string
1885
- * @param optional Integer $index
1886
- * @access private
1887
- * @return String
1888
- */
1889
- function _string_shift(&$string, $index = 1)
1890
- {
1891
- $substr = substr($string, 0, $index);
1892
- $string = substr($string, $index);
1893
- return $substr;
1894
- }
1895
-
1896
- /**
1897
- * String Pop
1898
- *
1899
- * Inspired by array_pop
1900
- *
1901
- * @param String $string
1902
- * @param optional Integer $index
1903
- * @access private
1904
- * @return String
1905
- */
1906
- function _string_pop(&$string, $index = 1)
1907
- {
1908
- $substr = substr($string, -$index);
1909
- $string = substr($string, 0, -$index);
1910
- return $substr;
1911
- }
1912
-
1913
- /**
1914
- * Increment the current string
1915
- *
1916
- * @see Crypt_Base::decrypt()
1917
- * @see Crypt_Base::encrypt()
1918
- * @param String $var
1919
- * @access private
1920
- */
1921
- function _increment_str(&$var)
1922
- {
1923
- for ($i = 4; $i <= strlen($var); $i+= 4) {
1924
- $temp = substr($var, -$i, 4);
1925
- switch ($temp) {
1926
- case "\xFF\xFF\xFF\xFF":
1927
- $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
1928
- break;
1929
- case "\x7F\xFF\xFF\xFF":
1930
- $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
1931
- return;
1932
- default:
1933
- $temp = unpack('Nnum', $temp);
1934
- $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
1935
- return;
1936
- }
1937
- }
1938
-
1939
- $remainder = strlen($var) % 4;
1940
-
1941
- if ($remainder == 0) {
1942
- return;
1943
- }
1944
-
1945
- $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
1946
- $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
1947
- $var = substr_replace($var, $temp, 0, $remainder);
1948
- }
1949
-
1950
- /**
1951
- * Setup the performance-optimized function for de/encrypt()
1952
- *
1953
- * Stores the created (or existing) callback function-name
1954
- * in $this->inline_crypt
1955
- *
1956
- * Internally for phpseclib developers:
1957
- *
1958
- * _setupInlineCrypt() would be called only if:
1959
- *
1960
- * - $engine == CRYPT_ENGINE_INTERNAL and
1961
- *
1962
- * - $use_inline_crypt === true
1963
- *
1964
- * - each time on _setup(), after(!) _setupKey()
1965
- *
1966
- *
1967
- * This ensures that _setupInlineCrypt() has always a
1968
- * full ready2go initializated internal cipher $engine state
1969
- * where, for example, the keys allready expanded,
1970
- * keys/block_size calculated and such.
1971
- *
1972
- * It is, each time if called, the responsibility of _setupInlineCrypt():
1973
- *
1974
- * - to set $this->inline_crypt to a valid and fully working callback function
1975
- * as a (faster) replacement for encrypt() / decrypt()
1976
- *
1977
- * - NOT to create unlimited callback functions (for memory reasons!)
1978
- * no matter how often _setupInlineCrypt() would be called. At some
1979
- * point of amount they must be generic re-useable.
1980
- *
1981
- * - the code of _setupInlineCrypt() it self,
1982
- * and the generated callback code,
1983
- * must be, in following order:
1984
- * - 100% safe
1985
- * - 100% compatible to encrypt()/decrypt()
1986
- * - using only php5+ features/lang-constructs/php-extensions if
1987
- * compatibility (down to php4) or fallback is provided
1988
- * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
1989
- * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
1990
- * the reason for the existence of _setupInlineCrypt() :-)]
1991
- * - memory-nice
1992
- * - short (as good as possible)
1993
- *
1994
- * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
1995
- * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
1996
- * - The following variable names are reserved:
1997
- * - $_* (all variable names prefixed with an underscore)
1998
- * - $self (object reference to it self. Do not use $this, but $self instead)
1999
- * - $in (the content of $in has to en/decrypt by the generated code)
2000
- * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2001
- *
2002
- *
2003
- * @see Crypt_Base::_setup()
2004
- * @see Crypt_Base::_createInlineCryptFunction()
2005
- * @see Crypt_Base::encrypt()
2006
- * @see Crypt_Base::decrypt()
2007
- * @access private
2008
- * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
2009
- */
2010
- function _setupInlineCrypt()
2011
- {
2012
- // If, for any reason, an extending Crypt_Base() Crypt_* class
2013
- // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
2014
- // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
2015
- // in the constructor at object instance-time
2016
- // or, if it's runtime-specific, at runtime
2017
-
2018
- $this->use_inline_crypt = false;
2019
- }
2020
-
2021
- /**
2022
- * Creates the performance-optimized function for en/decrypt()
2023
- *
2024
- * Internally for phpseclib developers:
2025
- *
2026
- * _createInlineCryptFunction():
2027
- *
2028
- * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2029
- * with the current [$this->]mode of operation code
2030
- *
2031
- * - create the $inline function, which called by encrypt() / decrypt()
2032
- * as its replacement to speed up the en/decryption operations.
2033
- *
2034
- * - return the name of the created $inline callback function
2035
- *
2036
- * - used to speed up en/decryption
2037
- *
2038
- *
2039
- *
2040
- * The main reason why can speed up things [up to 50%] this way are:
2041
- *
2042
- * - using variables more effective then regular.
2043
- * (ie no use of expensive arrays but integers $k_0, $k_1 ...
2044
- * or even, for example, the pure $key[] values hardcoded)
2045
- *
2046
- * - avoiding 1000's of function calls of ie _encryptBlock()
2047
- * but inlining the crypt operations.
2048
- * in the mode of operation for() loop.
2049
- *
2050
- * - full loop unroll the (sometimes key-dependent) rounds
2051
- * avoiding this way ++$i counters and runtime-if's etc...
2052
- *
2053
- * The basic code architectur of the generated $inline en/decrypt()
2054
- * lambda function, in pseudo php, is:
2055
- *
2056
- * <code>
2057
- * +----------------------------------------------------------------------------------------------+
2058
- * | callback $inline = create_function: |
2059
- * | lambda_function_0001_crypt_ECB($action, $text) |
2060
- * | { |
2061
- * | INSERT PHP CODE OF: |
2062
- * | $cipher_code['init_crypt']; // general init code. |
2063
- * | // ie: $sbox'es declarations used for |
2064
- * | // encrypt and decrypt'ing. |
2065
- * | |
2066
- * | switch ($action) { |
2067
- * | case 'encrypt': |
2068
- * | INSERT PHP CODE OF: |
2069
- * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
2070
- * | ie: specified $key or $box |
2071
- * | declarations for encrypt'ing. |
2072
- * | |
2073
- * | foreach ($ciphertext) { |
2074
- * | $in = $block_size of $ciphertext; |
2075
- * | |
2076
- * | INSERT PHP CODE OF: |
2077
- * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
2078
- * | // strlen($in) == $this->block_size |
2079
- * | // here comes the cipher algorithm in action |
2080
- * | // for encryption. |
2081
- * | // $cipher_code['encrypt_block'] has to |
2082
- * | // encrypt the content of the $in variable |
2083
- * | |
2084
- * | $plaintext .= $in; |
2085
- * | } |
2086
- * | return $plaintext; |
2087
- * | |
2088
- * | case 'decrypt': |
2089
- * | INSERT PHP CODE OF: |
2090
- * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
2091
- * | ie: specified $key or $box |
2092
- * | declarations for decrypt'ing. |
2093
- * | foreach ($plaintext) { |
2094
- * | $in = $block_size of $plaintext; |
2095
- * | |
2096
- * | INSERT PHP CODE OF: |
2097
- * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
2098
- * | // strlen($in) == $this->block_size |
2099
- * | // here comes the cipher algorithm in action |
2100
- * | // for decryption. |
2101
- * | // $cipher_code['decrypt_block'] has to |
2102
- * | // decrypt the content of the $in variable |
2103
- * | $ciphertext .= $in; |
2104
- * | } |
2105
- * | return $ciphertext; |
2106
- * | } |
2107
- * | } |
2108
- * +----------------------------------------------------------------------------------------------+
2109
- * </code>
2110
- *
2111
- * See also the Crypt_*::_setupInlineCrypt()'s for
2112
- * productive inline $cipher_code's how they works.
2113
- *
2114
- * Structure of:
2115
- * <code>
2116
- * $cipher_code = array(
2117
- * 'init_crypt' => (string) '', // optional
2118
- * 'init_encrypt' => (string) '', // optional
2119
- * 'init_decrypt' => (string) '', // optional
2120
- * 'encrypt_block' => (string) '', // required
2121
- * 'decrypt_block' => (string) '' // required
2122
- * );
2123
- * </code>
2124
- *
2125
- * @see Crypt_Base::_setupInlineCrypt()
2126
- * @see Crypt_Base::encrypt()
2127
- * @see Crypt_Base::decrypt()
2128
- * @param Array $cipher_code
2129
- * @access private
2130
- * @return String (the name of the created callback function)
2131
- */
2132
- function _createInlineCryptFunction($cipher_code)
2133
- {
2134
- $block_size = $this->block_size;
2135
-
2136
- // optional
2137
- $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
2138
- $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
2139
- $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
2140
- // required
2141
- $encrypt_block = $cipher_code['encrypt_block'];
2142
- $decrypt_block = $cipher_code['decrypt_block'];
2143
-
2144
- // Generating mode of operation inline code,
2145
- // merged with the $cipher_code algorithm
2146
- // for encrypt- and decryption.
2147
- switch ($this->mode) {
2148
- case CRYPT_MODE_ECB:
2149
- $encrypt = $init_encrypt . '
2150
- $_ciphertext = "";
2151
- $_plaintext_len = strlen($_text);
2152
-
2153
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2154
- $in = substr($_text, $_i, '.$block_size.');
2155
- '.$encrypt_block.'
2156
- $_ciphertext.= $in;
2157
- }
2158
-
2159
- return $_ciphertext;
2160
- ';
2161
-
2162
- $decrypt = $init_decrypt . '
2163
- $_plaintext = "";
2164
- $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2165
- $_ciphertext_len = strlen($_text);
2166
-
2167
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2168
- $in = substr($_text, $_i, '.$block_size.');
2169
- '.$decrypt_block.'
2170
- $_plaintext.= $in;
2171
- }
2172
-
2173
- return $self->_unpad($_plaintext);
2174
- ';
2175
- break;
2176
- case CRYPT_MODE_CTR:
2177
- $encrypt = $init_encrypt . '
2178
- $_ciphertext = "";
2179
- $_plaintext_len = strlen($_text);
2180
- $_xor = $self->encryptIV;
2181
- $_buffer = &$self->enbuffer;
2182
- if (strlen($_buffer["ciphertext"])) {
2183
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2184
- $_block = substr($_text, $_i, '.$block_size.');
2185
- if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2186
- $in = $_xor;
2187
- '.$encrypt_block.'
2188
- $self->_increment_str($_xor);
2189
- $_buffer["ciphertext"].= $in;
2190
- }
2191
- $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2192
- $_ciphertext.= $_block ^ $_key;
2193
- }
2194
- } else {
2195
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2196
- $_block = substr($_text, $_i, '.$block_size.');
2197
- $in = $_xor;
2198
- '.$encrypt_block.'
2199
- $self->_increment_str($_xor);
2200
- $_key = $in;
2201
- $_ciphertext.= $_block ^ $_key;
2202
- }
2203
- }
2204
- if ($self->continuousBuffer) {
2205
- $self->encryptIV = $_xor;
2206
- if ($_start = $_plaintext_len % '.$block_size.') {
2207
- $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2208
- }
2209
- }
2210
-
2211
- return $_ciphertext;
2212
- ';
2213
-
2214
- $decrypt = $init_encrypt . '
2215
- $_plaintext = "";
2216
- $_ciphertext_len = strlen($_text);
2217
- $_xor = $self->decryptIV;
2218
- $_buffer = &$self->debuffer;
2219
-
2220
- if (strlen($_buffer["ciphertext"])) {
2221
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2222
- $_block = substr($_text, $_i, '.$block_size.');
2223
- if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2224
- $in = $_xor;
2225
- '.$encrypt_block.'
2226
- $self->_increment_str($_xor);
2227
- $_buffer["ciphertext"].= $in;
2228
- }
2229
- $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2230
- $_plaintext.= $_block ^ $_key;
2231
- }
2232
- } else {
2233
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2234
- $_block = substr($_text, $_i, '.$block_size.');
2235
- $in = $_xor;
2236
- '.$encrypt_block.'
2237
- $self->_increment_str($_xor);
2238
- $_key = $in;
2239
- $_plaintext.= $_block ^ $_key;
2240
- }
2241
- }
2242
- if ($self->continuousBuffer) {
2243
- $self->decryptIV = $_xor;
2244
- if ($_start = $_ciphertext_len % '.$block_size.') {
2245
- $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2246
- }
2247
- }
2248
-
2249
- return $_plaintext;
2250
- ';
2251
- break;
2252
- case CRYPT_MODE_CFB:
2253
- $encrypt = $init_encrypt . '
2254
- $_ciphertext = "";
2255
- $_buffer = &$self->enbuffer;
2256
-
2257
- if ($self->continuousBuffer) {
2258
- $_iv = &$self->encryptIV;
2259
- $_pos = &$_buffer["pos"];
2260
- } else {
2261
- $_iv = $self->encryptIV;
2262
- $_pos = 0;
2263
- }
2264
- $_len = strlen($_text);
2265
- $_i = 0;
2266
- if ($_pos) {
2267
- $_orig_pos = $_pos;
2268
- $_max = '.$block_size.' - $_pos;
2269
- if ($_len >= $_max) {
2270
- $_i = $_max;
2271
- $_len-= $_max;
2272
- $_pos = 0;
2273
- } else {
2274
- $_i = $_len;
2275
- $_pos+= $_len;
2276
- $_len = 0;
2277
- }
2278
- $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2279
- $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2280
- }
2281
- while ($_len >= '.$block_size.') {
2282
- $in = $_iv;
2283
- '.$encrypt_block.';
2284
- $_iv = $in ^ substr($_text, $_i, '.$block_size.');
2285
- $_ciphertext.= $_iv;
2286
- $_len-= '.$block_size.';
2287
- $_i+= '.$block_size.';
2288
- }
2289
- if ($_len) {
2290
- $in = $_iv;
2291
- '.$encrypt_block.'
2292
- $_iv = $in;
2293
- $_block = $_iv ^ substr($_text, $_i);
2294
- $_iv = substr_replace($_iv, $_block, 0, $_len);
2295
- $_ciphertext.= $_block;
2296
- $_pos = $_len;
2297
- }
2298
- return $_ciphertext;
2299
- ';
2300
-
2301
- $decrypt = $init_encrypt . '
2302
- $_plaintext = "";
2303
- $_buffer = &$self->debuffer;
2304
-
2305
- if ($self->continuousBuffer) {
2306
- $_iv = &$self->decryptIV;
2307
- $_pos = &$_buffer["pos"];
2308
- } else {
2309
- $_iv = $self->decryptIV;
2310
- $_pos = 0;
2311
- }
2312
- $_len = strlen($_text);
2313
- $_i = 0;
2314
- if ($_pos) {
2315
- $_orig_pos = $_pos;
2316
- $_max = '.$block_size.' - $_pos;
2317
- if ($_len >= $_max) {
2318
- $_i = $_max;
2319
- $_len-= $_max;
2320
- $_pos = 0;
2321
- } else {
2322
- $_i = $_len;
2323
- $_pos+= $_len;
2324
- $_len = 0;
2325
- }
2326
- $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2327
- $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2328
- }
2329
- while ($_len >= '.$block_size.') {
2330
- $in = $_iv;
2331
- '.$encrypt_block.'
2332
- $_iv = $in;
2333
- $cb = substr($_text, $_i, '.$block_size.');
2334
- $_plaintext.= $_iv ^ $cb;
2335
- $_iv = $cb;
2336
- $_len-= '.$block_size.';
2337
- $_i+= '.$block_size.';
2338
- }
2339
- if ($_len) {
2340
- $in = $_iv;
2341
- '.$encrypt_block.'
2342
- $_iv = $in;
2343
- $_plaintext.= $_iv ^ substr($_text, $_i);
2344
- $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2345
- $_pos = $_len;
2346
- }
2347
-
2348
- return $_plaintext;
2349
- ';
2350
- break;
2351
- case CRYPT_MODE_OFB:
2352
- $encrypt = $init_encrypt . '
2353
- $_ciphertext = "";
2354
- $_plaintext_len = strlen($_text);
2355
- $_xor = $self->encryptIV;
2356
- $_buffer = &$self->enbuffer;
2357
-
2358
- if (strlen($_buffer["xor"])) {
2359
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2360
- $_block = substr($_text, $_i, '.$block_size.');
2361
- if (strlen($_block) > strlen($_buffer["xor"])) {
2362
- $in = $_xor;
2363
- '.$encrypt_block.'
2364
- $_xor = $in;
2365
- $_buffer["xor"].= $_xor;
2366
- }
2367
- $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2368
- $_ciphertext.= $_block ^ $_key;
2369
- }
2370
- } else {
2371
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2372
- $in = $_xor;
2373
- '.$encrypt_block.'
2374
- $_xor = $in;
2375
- $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2376
- }
2377
- $_key = $_xor;
2378
- }
2379
- if ($self->continuousBuffer) {
2380
- $self->encryptIV = $_xor;
2381
- if ($_start = $_plaintext_len % '.$block_size.') {
2382
- $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2383
- }
2384
- }
2385
- return $_ciphertext;
2386
- ';
2387
-
2388
- $decrypt = $init_encrypt . '
2389
- $_plaintext = "";
2390
- $_ciphertext_len = strlen($_text);
2391
- $_xor = $self->decryptIV;
2392
- $_buffer = &$self->debuffer;
2393
-
2394
- if (strlen($_buffer["xor"])) {
2395
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2396
- $_block = substr($_text, $_i, '.$block_size.');
2397
- if (strlen($_block) > strlen($_buffer["xor"])) {
2398
- $in = $_xor;
2399
- '.$encrypt_block.'
2400
- $_xor = $in;
2401
- $_buffer["xor"].= $_xor;
2402
- }
2403
- $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2404
- $_plaintext.= $_block ^ $_key;
2405
- }
2406
- } else {
2407
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2408
- $in = $_xor;
2409
- '.$encrypt_block.'
2410
- $_xor = $in;
2411
- $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2412
- }
2413
- $_key = $_xor;
2414
- }
2415
- if ($self->continuousBuffer) {
2416
- $self->decryptIV = $_xor;
2417
- if ($_start = $_ciphertext_len % '.$block_size.') {
2418
- $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2419
- }
2420
- }
2421
- return $_plaintext;
2422
- ';
2423
- break;
2424
- case CRYPT_MODE_STREAM:
2425
- $encrypt = $init_encrypt . '
2426
- $_ciphertext = "";
2427
- '.$encrypt_block.'
2428
- return $_ciphertext;
2429
- ';
2430
- $decrypt = $init_decrypt . '
2431
- $_plaintext = "";
2432
- '.$decrypt_block.'
2433
- return $_plaintext;
2434
- ';
2435
- break;
2436
- // case CRYPT_MODE_CBC:
2437
- default:
2438
- $encrypt = $init_encrypt . '
2439
- $_ciphertext = "";
2440
- $_plaintext_len = strlen($_text);
2441
-
2442
- $in = $self->encryptIV;
2443
-
2444
- for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2445
- $in = substr($_text, $_i, '.$block_size.') ^ $in;
2446
- '.$encrypt_block.'
2447
- $_ciphertext.= $in;
2448
- }
2449
-
2450
- if ($self->continuousBuffer) {
2451
- $self->encryptIV = $in;
2452
- }
2453
-
2454
- return $_ciphertext;
2455
- ';
2456
-
2457
- $decrypt = $init_decrypt . '
2458
- $_plaintext = "";
2459
- $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2460
- $_ciphertext_len = strlen($_text);
2461
-
2462
- $_iv = $self->decryptIV;
2463
-
2464
- for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2465
- $in = $_block = substr($_text, $_i, '.$block_size.');
2466
- '.$decrypt_block.'
2467
- $_plaintext.= $in ^ $_iv;
2468
- $_iv = $_block;
2469
- }
2470
-
2471
- if ($self->continuousBuffer) {
2472
- $self->decryptIV = $_iv;
2473
- }
2474
-
2475
- return $self->_unpad($_plaintext);
2476
- ';
2477
- break;
2478
- }
2479
-
2480
- // Create the $inline function and return its name as string. Ready to run!
2481
- return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
2482
- }
2483
-
2484
- /**
2485
- * Holds the lambda_functions table (classwide)
2486
- *
2487
- * Each name of the lambda function, created from
2488
- * _setupInlineCrypt() && _createInlineCryptFunction()
2489
- * is stored, classwide (!), here for reusing.
2490
- *
2491
- * The string-based index of $function is a classwide
2492
- * uniqe value representing, at least, the $mode of
2493
- * operation (or more... depends of the optimizing level)
2494
- * for which $mode the lambda function was created.
2495
- *
2496
- * @access private
2497
- * @return Array &$functions
2498
- */
2499
- function &_getLambdaFunctions()
2500
- {
2501
- static $functions = array();
2502
- return $functions;
2503
- }
2504
-
2505
- /**
2506
- * Generates a digest from $bytes
2507
- *
2508
- * @see _setupInlineCrypt()
2509
- * @access private
2510
- * @param $bytes
2511
- * @return String
2512
- */
2513
- function _hashInlineCryptFunction($bytes)
2514
- {
2515
- if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
2516
- define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos())));
2517
- }
2518
-
2519
- $result = '';
2520
- $hash = $bytes;
2521
-
2522
- switch (true) {
2523
- case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
2524
- foreach (str_split($bytes, 64) as $t) {
2525
- $hash = hash('whirlpool', $hash, true);
2526
- $result .= $t ^ $hash;
2527
- }
2528
- return $result . hash('whirlpool', $hash, true);
2529
- default:
2530
- $len = strlen($bytes);
2531
- for ($i = 0; $i < $len; $i+=20) {
2532
- $t = substr($bytes, $i, 20);
2533
- $hash = pack('H*', sha1($hash));
2534
- $result .= $t ^ $hash;
2535
- }
2536
- return $result . pack('H*', sha1($hash));
2537
- }
2538
- }
2539
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Base Class for all Crypt_* cipher classes
5
+ *
6
+ * PHP versions 4 and 5
7
+ *
8
+ * Internally for phpseclib developers:
9
+ * If you plan to add a new cipher class, please note following rules:
10
+ *
11
+ * - The new Crypt_* cipher class should extend Crypt_Base
12
+ *
13
+ * - Following methods are then required to be overridden/overloaded:
14
+ *
15
+ * - _encryptBlock()
16
+ *
17
+ * - _decryptBlock()
18
+ *
19
+ * - _setupKey()
20
+ *
21
+ * - All other methods are optional to be overridden/overloaded
22
+ *
23
+ * - Look at the source code of the current ciphers how they extend Crypt_Base
24
+ * and take one of them as a start up for the new cipher class.
25
+ *
26
+ * - Please read all the other comments/notes/hints here also for each class var/method
27
+ *
28
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
29
+ * of this software and associated documentation files (the "Software"), to deal
30
+ * in the Software without restriction, including without limitation the rights
31
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32
+ * copies of the Software, and to permit persons to whom the Software is
33
+ * furnished to do so, subject to the following conditions:
34
+ *
35
+ * The above copyright notice and this permission notice shall be included in
36
+ * all copies or substantial portions of the Software.
37
+ *
38
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
+ * THE SOFTWARE.
45
+ *
46
+ * @category Crypt
47
+ * @package Crypt_Base
48
+ * @author Jim Wigginton <terrafrost@php.net>
49
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
50
+ * @copyright 2007 Jim Wigginton
51
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
52
+ * @link http://phpseclib.sourceforge.net
53
+ */
54
+
55
+ /**#@+
56
+ * @access public
57
+ * @see self::encrypt()
58
+ * @see self::decrypt()
59
+ */
60
+ /**
61
+ * Encrypt / decrypt using the Counter mode.
62
+ *
63
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
64
+ *
65
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
66
+ */
67
+ define('CRYPT_MODE_CTR', -1);
68
+ /**
69
+ * Encrypt / decrypt using the Electronic Code Book mode.
70
+ *
71
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
72
+ */
73
+ define('CRYPT_MODE_ECB', 1);
74
+ /**
75
+ * Encrypt / decrypt using the Code Book Chaining mode.
76
+ *
77
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
78
+ */
79
+ define('CRYPT_MODE_CBC', 2);
80
+ /**
81
+ * Encrypt / decrypt using the Cipher Feedback mode.
82
+ *
83
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
84
+ */
85
+ define('CRYPT_MODE_CFB', 3);
86
+ /**
87
+ * Encrypt / decrypt using the Output Feedback mode.
88
+ *
89
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
90
+ */
91
+ define('CRYPT_MODE_OFB', 4);
92
+ /**
93
+ * Encrypt / decrypt using streaming mode.
94
+ */
95
+ define('CRYPT_MODE_STREAM', 5);
96
+ /**#@-*/
97
+
98
+ /**#@+
99
+ * @access private
100
+ * @see self::Crypt_Base()
101
+ * @internal These constants are for internal use only
102
+ */
103
+ /**
104
+ * Base value for the internal implementation $engine switch
105
+ */
106
+ define('CRYPT_ENGINE_INTERNAL', 1);
107
+ /**
108
+ * Base value for the mcrypt implementation $engine switch
109
+ */
110
+ define('CRYPT_ENGINE_MCRYPT', 2);
111
+ /**
112
+ * Base value for the OpenSSL implementation $engine switch
113
+ */
114
+ define('CRYPT_ENGINE_OPENSSL', 3);
115
+ /**#@-*/
116
+
117
+ /**
118
+ * Base Class for all Crypt_* cipher classes
119
+ *
120
+ * @package Crypt_Base
121
+ * @author Jim Wigginton <terrafrost@php.net>
122
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
123
+ * @access public
124
+ */
125
+ class Crypt_Base
126
+ {
127
+ /**
128
+ * The Encryption Mode
129
+ *
130
+ * @see self::Crypt_Base()
131
+ * @var int
132
+ * @access private
133
+ */
134
+ var $mode;
135
+
136
+ /**
137
+ * The Block Length of the block cipher
138
+ *
139
+ * @var int
140
+ * @access private
141
+ */
142
+ var $block_size = 16;
143
+
144
+ /**
145
+ * The Key
146
+ *
147
+ * @see self::setKey()
148
+ * @var string
149
+ * @access private
150
+ */
151
+ var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
152
+
153
+ /**
154
+ * The Initialization Vector
155
+ *
156
+ * @see self::setIV()
157
+ * @var string
158
+ * @access private
159
+ */
160
+ var $iv;
161
+
162
+ /**
163
+ * A "sliding" Initialization Vector
164
+ *
165
+ * @see self::enableContinuousBuffer()
166
+ * @see self::_clearBuffers()
167
+ * @var string
168
+ * @access private
169
+ */
170
+ var $encryptIV;
171
+
172
+ /**
173
+ * A "sliding" Initialization Vector
174
+ *
175
+ * @see self::enableContinuousBuffer()
176
+ * @see self::_clearBuffers()
177
+ * @var string
178
+ * @access private
179
+ */
180
+ var $decryptIV;
181
+
182
+ /**
183
+ * Continuous Buffer status
184
+ *
185
+ * @see self::enableContinuousBuffer()
186
+ * @var bool
187
+ * @access private
188
+ */
189
+ var $continuousBuffer = false;
190
+
191
+ /**
192
+ * Encryption buffer for CTR, OFB and CFB modes
193
+ *
194
+ * @see self::encrypt()
195
+ * @see self::_clearBuffers()
196
+ * @var array
197
+ * @access private
198
+ */
199
+ var $enbuffer;
200
+
201
+ /**
202
+ * Decryption buffer for CTR, OFB and CFB modes
203
+ *
204
+ * @see self::decrypt()
205
+ * @see self::_clearBuffers()
206
+ * @var array
207
+ * @access private
208
+ */
209
+ var $debuffer;
210
+
211
+ /**
212
+ * mcrypt resource for encryption
213
+ *
214
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
215
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
216
+ *
217
+ * @see self::encrypt()
218
+ * @var resource
219
+ * @access private
220
+ */
221
+ var $enmcrypt;
222
+
223
+ /**
224
+ * mcrypt resource for decryption
225
+ *
226
+ * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
227
+ * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
228
+ *
229
+ * @see self::decrypt()
230
+ * @var resource
231
+ * @access private
232
+ */
233
+ var $demcrypt;
234
+
235
+ /**
236
+ * Does the enmcrypt resource need to be (re)initialized?
237
+ *
238
+ * @see Crypt_Twofish::setKey()
239
+ * @see Crypt_Twofish::setIV()
240
+ * @var bool
241
+ * @access private
242
+ */
243
+ var $enchanged = true;
244
+
245
+ /**
246
+ * Does the demcrypt resource need to be (re)initialized?
247
+ *
248
+ * @see Crypt_Twofish::setKey()
249
+ * @see Crypt_Twofish::setIV()
250
+ * @var bool
251
+ * @access private
252
+ */
253
+ var $dechanged = true;
254
+
255
+ /**
256
+ * mcrypt resource for CFB mode
257
+ *
258
+ * mcrypt's CFB mode, in (and only in) buffered context,
259
+ * is broken, so phpseclib implements the CFB mode by it self,
260
+ * even when the mcrypt php extension is available.
261
+ *
262
+ * In order to do the CFB-mode work (fast) phpseclib
263
+ * use a separate ECB-mode mcrypt resource.
264
+ *
265
+ * @link http://phpseclib.sourceforge.net/cfb-demo.phps
266
+ * @see self::encrypt()
267
+ * @see self::decrypt()
268
+ * @see self::_setupMcrypt()
269
+ * @var resource
270
+ * @access private
271
+ */
272
+ var $ecb;
273
+
274
+ /**
275
+ * Optimizing value while CFB-encrypting
276
+ *
277
+ * Only relevant if $continuousBuffer enabled
278
+ * and $engine == CRYPT_ENGINE_MCRYPT
279
+ *
280
+ * It's faster to re-init $enmcrypt if
281
+ * $buffer bytes > $cfb_init_len than
282
+ * using the $ecb resource furthermore.
283
+ *
284
+ * This value depends of the chosen cipher
285
+ * and the time it would be needed for it's
286
+ * initialization [by mcrypt_generic_init()]
287
+ * which, typically, depends on the complexity
288
+ * on its internaly Key-expanding algorithm.
289
+ *
290
+ * @see self::encrypt()
291
+ * @var int
292
+ * @access private
293
+ */
294
+ var $cfb_init_len = 600;
295
+
296
+ /**
297
+ * Does internal cipher state need to be (re)initialized?
298
+ *
299
+ * @see self::setKey()
300
+ * @see self::setIV()
301
+ * @see self::disableContinuousBuffer()
302
+ * @var bool
303
+ * @access private
304
+ */
305
+ var $changed = true;
306
+
307
+ /**
308
+ * Padding status
309
+ *
310
+ * @see self::enablePadding()
311
+ * @var bool
312
+ * @access private
313
+ */
314
+ var $padding = true;
315
+
316
+ /**
317
+ * Is the mode one that is paddable?
318
+ *
319
+ * @see self::Crypt_Base()
320
+ * @var bool
321
+ * @access private
322
+ */
323
+ var $paddable = false;
324
+
325
+ /**
326
+ * Holds which crypt engine internaly should be use,
327
+ * which will be determined automatically on __construct()
328
+ *
329
+ * Currently available $engines are:
330
+ * - CRYPT_ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
331
+ * - CRYPT_ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
332
+ * - CRYPT_ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
333
+ *
334
+ * @see self::_setEngine()
335
+ * @see self::encrypt()
336
+ * @see self::decrypt()
337
+ * @var int
338
+ * @access private
339
+ */
340
+ var $engine;
341
+
342
+ /**
343
+ * Holds the preferred crypt engine
344
+ *
345
+ * @see self::_setEngine()
346
+ * @see self::setPreferredEngine()
347
+ * @var int
348
+ * @access private
349
+ */
350
+ var $preferredEngine;
351
+
352
+ /**
353
+ * The mcrypt specific name of the cipher
354
+ *
355
+ * Only used if $engine == CRYPT_ENGINE_MCRYPT
356
+ *
357
+ * @link http://www.php.net/mcrypt_module_open
358
+ * @link http://www.php.net/mcrypt_list_algorithms
359
+ * @see self::_setupMcrypt()
360
+ * @var string
361
+ * @access private
362
+ */
363
+ var $cipher_name_mcrypt;
364
+
365
+ /**
366
+ * The openssl specific name of the cipher
367
+ *
368
+ * Only used if $engine == CRYPT_ENGINE_OPENSSL
369
+ *
370
+ * @link http://www.php.net/openssl-get-cipher-methods
371
+ * @var string
372
+ * @access private
373
+ */
374
+ var $cipher_name_openssl;
375
+
376
+ /**
377
+ * The openssl specific name of the cipher in ECB mode
378
+ *
379
+ * If OpenSSL does not support the mode we're trying to use (CTR)
380
+ * it can still be emulated with ECB mode.
381
+ *
382
+ * @link http://www.php.net/openssl-get-cipher-methods
383
+ * @var string
384
+ * @access private
385
+ */
386
+ var $cipher_name_openssl_ecb;
387
+
388
+ /**
389
+ * The default salt used by setPassword()
390
+ *
391
+ * @see self::setPassword()
392
+ * @var string
393
+ * @access private
394
+ */
395
+ var $password_default_salt = 'phpseclib/salt';
396
+
397
+ /**
398
+ * The namespace used by the cipher for its constants.
399
+ *
400
+ * ie: AES.php is using CRYPT_AES_MODE_* for its constants
401
+ * so $const_namespace is AES
402
+ *
403
+ * DES.php is using CRYPT_DES_MODE_* for its constants
404
+ * so $const_namespace is DES... and so on
405
+ *
406
+ * All CRYPT_<$const_namespace>_MODE_* are aliases of
407
+ * the generic CRYPT_MODE_* constants, so both could be used
408
+ * for each cipher.
409
+ *
410
+ * Example:
411
+ * $aes = new Crypt_AES(CRYPT_AES_MODE_CFB); // $aes will operate in cfb mode
412
+ * $aes = new Crypt_AES(CRYPT_MODE_CFB); // identical
413
+ *
414
+ * @see self::Crypt_Base()
415
+ * @var string
416
+ * @access private
417
+ */
418
+ var $const_namespace;
419
+
420
+ /**
421
+ * The name of the performance-optimized callback function
422
+ *
423
+ * Used by encrypt() / decrypt()
424
+ * only if $engine == CRYPT_ENGINE_INTERNAL
425
+ *
426
+ * @see self::encrypt()
427
+ * @see self::decrypt()
428
+ * @see self::_setupInlineCrypt()
429
+ * @see self::$use_inline_crypt
430
+ * @var Callback
431
+ * @access private
432
+ */
433
+ var $inline_crypt;
434
+
435
+ /**
436
+ * Holds whether performance-optimized $inline_crypt() can/should be used.
437
+ *
438
+ * @see self::encrypt()
439
+ * @see self::decrypt()
440
+ * @see self::inline_crypt
441
+ * @var mixed
442
+ * @access private
443
+ */
444
+ var $use_inline_crypt;
445
+
446
+ /**
447
+ * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
448
+ *
449
+ * @see self::_openssl_ctr_process()
450
+ * @var bool
451
+ * @access private
452
+ */
453
+ var $openssl_emulate_ctr = false;
454
+
455
+ /**
456
+ * Determines what options are passed to openssl_encrypt/decrypt
457
+ *
458
+ * @see self::isValidEngine()
459
+ * @var mixed
460
+ * @access private
461
+ */
462
+ var $openssl_options;
463
+
464
+ /**
465
+ * Has the key length explicitly been set or should it be derived from the key, itself?
466
+ *
467
+ * @see self::setKeyLength()
468
+ * @var bool
469
+ * @access private
470
+ */
471
+ var $explicit_key_length = false;
472
+
473
+ /**
474
+ * Don't truncate / null pad key
475
+ *
476
+ * @see self::_clearBuffers()
477
+ * @var bool
478
+ * @access private
479
+ */
480
+ var $skip_key_adjustment = false;
481
+
482
+ /**
483
+ * Default Constructor.
484
+ *
485
+ * Determines whether or not the mcrypt extension should be used.
486
+ *
487
+ * $mode could be:
488
+ *
489
+ * - CRYPT_MODE_ECB
490
+ *
491
+ * - CRYPT_MODE_CBC
492
+ *
493
+ * - CRYPT_MODE_CTR
494
+ *
495
+ * - CRYPT_MODE_CFB
496
+ *
497
+ * - CRYPT_MODE_OFB
498
+ *
499
+ * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
500
+ *
501
+ * If not explicitly set, CRYPT_MODE_CBC will be used.
502
+ *
503
+ * @param int $mode
504
+ * @access public
505
+ */
506
+ function __construct($mode = CRYPT_MODE_CBC)
507
+ {
508
+ // $mode dependent settings
509
+ switch ($mode) {
510
+ case CRYPT_MODE_ECB:
511
+ $this->paddable = true;
512
+ $this->mode = CRYPT_MODE_ECB;
513
+ break;
514
+ case CRYPT_MODE_CTR:
515
+ case CRYPT_MODE_CFB:
516
+ case CRYPT_MODE_OFB:
517
+ case CRYPT_MODE_STREAM:
518
+ $this->mode = $mode;
519
+ break;
520
+ case CRYPT_MODE_CBC:
521
+ default:
522
+ $this->paddable = true;
523
+ $this->mode = CRYPT_MODE_CBC;
524
+ }
525
+
526
+ $this->_setEngine();
527
+
528
+ // Determining whether inline crypting can be used by the cipher
529
+ if ($this->use_inline_crypt !== false) {
530
+ $this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
531
+ }
532
+ }
533
+
534
+ /**
535
+ * PHP4 compatible Default Constructor.
536
+ *
537
+ * @see self::__construct()
538
+ * @param int $mode
539
+ * @access public
540
+ */
541
+ function Crypt_Base($mode = CRYPT_MODE_CBC)
542
+ {
543
+ $this->__construct($mode);
544
+ }
545
+
546
+ /**
547
+ * Sets the initialization vector. (optional)
548
+ *
549
+ * SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
550
+ * to be all zero's.
551
+ *
552
+ * @access public
553
+ * @param string $iv
554
+ * @internal Can be overwritten by a sub class, but does not have to be
555
+ */
556
+ function setIV($iv)
557
+ {
558
+ if ($this->mode == CRYPT_MODE_ECB) {
559
+ return;
560
+ }
561
+
562
+ $this->iv = $iv;
563
+ $this->changed = true;
564
+ }
565
+
566
+ /**
567
+ * Sets the key length.
568
+ *
569
+ * Keys with explicitly set lengths need to be treated accordingly
570
+ *
571
+ * @access public
572
+ * @param int $length
573
+ */
574
+ function setKeyLength($length)
575
+ {
576
+ $this->explicit_key_length = true;
577
+ $this->changed = true;
578
+ $this->_setEngine();
579
+ }
580
+
581
+ /**
582
+ * Returns the current key length in bits
583
+ *
584
+ * @access public
585
+ * @return int
586
+ */
587
+ function getKeyLength()
588
+ {
589
+ return $this->key_length << 3;
590
+ }
591
+
592
+ /**
593
+ * Returns the current block length in bits
594
+ *
595
+ * @access public
596
+ * @return int
597
+ */
598
+ function getBlockLength()
599
+ {
600
+ return $this->block_size << 3;
601
+ }
602
+
603
+ /**
604
+ * Sets the key.
605
+ *
606
+ * The min/max length(s) of the key depends on the cipher which is used.
607
+ * If the key not fits the length(s) of the cipher it will paded with null bytes
608
+ * up to the closest valid key length. If the key is more than max length,
609
+ * we trim the excess bits.
610
+ *
611
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
612
+ *
613
+ * @access public
614
+ * @param string $key
615
+ * @internal Could, but not must, extend by the child Crypt_* class
616
+ */
617
+ function setKey($key)
618
+ {
619
+ if (!$this->explicit_key_length) {
620
+ $this->setKeyLength(strlen($key) << 3);
621
+ $this->explicit_key_length = false;
622
+ }
623
+
624
+ $this->key = $key;
625
+ $this->changed = true;
626
+ $this->_setEngine();
627
+ }
628
+
629
+ /**
630
+ * Sets the password.
631
+ *
632
+ * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
633
+ * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
634
+ * $hash, $salt, $count, $dkLen
635
+ *
636
+ * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
637
+ *
638
+ * @see Crypt/Hash.php
639
+ * @param string $password
640
+ * @param string $method
641
+ * @return bool
642
+ * @access public
643
+ * @internal Could, but not must, extend by the child Crypt_* class
644
+ */
645
+ function setPassword($password, $method = 'pbkdf2')
646
+ {
647
+ $key = '';
648
+
649
+ switch ($method) {
650
+ default: // 'pbkdf2' or 'pbkdf1'
651
+ $func_args = func_get_args();
652
+
653
+ // Hash function
654
+ $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
655
+
656
+ // WPA and WPA2 use the SSID as the salt
657
+ $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
658
+
659
+ // RFC2898#section-4.2 uses 1,000 iterations by default
660
+ // WPA and WPA2 use 4,096.
661
+ $count = isset($func_args[4]) ? $func_args[4] : 1000;
662
+
663
+ // Keylength
664
+ if (isset($func_args[5])) {
665
+ $dkLen = $func_args[5];
666
+ } else {
667
+ $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
668
+ }
669
+
670
+ switch (true) {
671
+ case $method == 'pbkdf1':
672
+ if (!class_exists('Crypt_Hash')) {
673
+ include_once 'Crypt/Hash.php';
674
+ }
675
+ $hashObj = new Crypt_Hash();
676
+ $hashObj->setHash($hash);
677
+ if ($dkLen > $hashObj->getLength()) {
678
+ user_error('Derived key too long');
679
+ return false;
680
+ }
681
+ $t = $password . $salt;
682
+ for ($i = 0; $i < $count; ++$i) {
683
+ $t = $hashObj->hash($t);
684
+ }
685
+ $key = substr($t, 0, $dkLen);
686
+
687
+ $this->setKey(substr($key, 0, $dkLen >> 1));
688
+ $this->setIV(substr($key, $dkLen >> 1));
689
+
690
+ return true;
691
+ // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
692
+ case !function_exists('hash_pbkdf2'):
693
+ case !function_exists('hash_algos'):
694
+ case !in_array($hash, hash_algos()):
695
+ if (!class_exists('Crypt_Hash')) {
696
+ include_once 'Crypt/Hash.php';
697
+ }
698
+ $i = 1;
699
+ while (strlen($key) < $dkLen) {
700
+ $hmac = new Crypt_Hash();
701
+ $hmac->setHash($hash);
702
+ $hmac->setKey($password);
703
+ $f = $u = $hmac->hash($salt . pack('N', $i++));
704
+ for ($j = 2; $j <= $count; ++$j) {
705
+ $u = $hmac->hash($u);
706
+ $f^= $u;
707
+ }
708
+ $key.= $f;
709
+ }
710
+ $key = substr($key, 0, $dkLen);
711
+ break;
712
+ default:
713
+ $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
714
+ }
715
+ }
716
+
717
+ $this->setKey($key);
718
+
719
+ return true;
720
+ }
721
+
722
+ /**
723
+ * Encrypts a message.
724
+ *
725
+ * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
726
+ * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
727
+ * necessary are discussed in the following
728
+ * URL:
729
+ *
730
+ * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
731
+ *
732
+ * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
733
+ * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
734
+ * length.
735
+ *
736
+ * @see self::decrypt()
737
+ * @access public
738
+ * @param string $plaintext
739
+ * @return string $ciphertext
740
+ * @internal Could, but not must, extend by the child Crypt_* class
741
+ */
742
+ function encrypt($plaintext)
743
+ {
744
+ if ($this->paddable) {
745
+ $plaintext = $this->_pad($plaintext);
746
+ }
747
+
748
+ if ($this->engine === CRYPT_ENGINE_OPENSSL) {
749
+ if ($this->changed) {
750
+ $this->_clearBuffers();
751
+ $this->changed = false;
752
+ }
753
+ switch ($this->mode) {
754
+ case CRYPT_MODE_STREAM:
755
+ return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
756
+ case CRYPT_MODE_ECB:
757
+ $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
758
+ return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
759
+ case CRYPT_MODE_CBC:
760
+ $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
761
+ if (!defined('OPENSSL_RAW_DATA')) {
762
+ $result = substr($result, 0, -$this->block_size);
763
+ }
764
+ if ($this->continuousBuffer) {
765
+ $this->encryptIV = substr($result, -$this->block_size);
766
+ }
767
+ return $result;
768
+ case CRYPT_MODE_CTR:
769
+ return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
770
+ case CRYPT_MODE_CFB:
771
+ // cfb loosely routines inspired by openssl's:
772
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
773
+ $ciphertext = '';
774
+ if ($this->continuousBuffer) {
775
+ $iv = &$this->encryptIV;
776
+ $pos = &$this->enbuffer['pos'];
777
+ } else {
778
+ $iv = $this->encryptIV;
779
+ $pos = 0;
780
+ }
781
+ $len = strlen($plaintext);
782
+ $i = 0;
783
+ if ($pos) {
784
+ $orig_pos = $pos;
785
+ $max = $this->block_size - $pos;
786
+ if ($len >= $max) {
787
+ $i = $max;
788
+ $len-= $max;
789
+ $pos = 0;
790
+ } else {
791
+ $i = $len;
792
+ $pos+= $len;
793
+ $len = 0;
794
+ }
795
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
796
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
797
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
798
+ $plaintext = substr($plaintext, $i);
799
+ }
800
+
801
+ $overflow = $len % $this->block_size;
802
+
803
+ if ($overflow) {
804
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
805
+ $iv = $this->_string_pop($ciphertext, $this->block_size);
806
+
807
+ $size = $len - $overflow;
808
+ $block = $iv ^ substr($plaintext, -$overflow);
809
+ $iv = substr_replace($iv, $block, 0, $overflow);
810
+ $ciphertext.= $block;
811
+ $pos = $overflow;
812
+ } elseif ($len) {
813
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
814
+ $iv = substr($ciphertext, -$this->block_size);
815
+ }
816
+
817
+ return $ciphertext;
818
+ case CRYPT_MODE_OFB:
819
+ return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
820
+ }
821
+ }
822
+
823
+ if ($this->engine === CRYPT_ENGINE_MCRYPT) {
824
+ if ($this->changed) {
825
+ $this->_setupMcrypt();
826
+ $this->changed = false;
827
+ }
828
+ if ($this->enchanged) {
829
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
830
+ $this->enchanged = false;
831
+ }
832
+
833
+ // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
834
+ // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
835
+ // rewritten CFB implementation the above outputs the same thing twice.
836
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
837
+ $block_size = $this->block_size;
838
+ $iv = &$this->encryptIV;
839
+ $pos = &$this->enbuffer['pos'];
840
+ $len = strlen($plaintext);
841
+ $ciphertext = '';
842
+ $i = 0;
843
+ if ($pos) {
844
+ $orig_pos = $pos;
845
+ $max = $block_size - $pos;
846
+ if ($len >= $max) {
847
+ $i = $max;
848
+ $len-= $max;
849
+ $pos = 0;
850
+ } else {
851
+ $i = $len;
852
+ $pos+= $len;
853
+ $len = 0;
854
+ }
855
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
856
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
857
+ $this->enbuffer['enmcrypt_init'] = true;
858
+ }
859
+ if ($len >= $block_size) {
860
+ if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
861
+ if ($this->enbuffer['enmcrypt_init'] === true) {
862
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
863
+ $this->enbuffer['enmcrypt_init'] = false;
864
+ }
865
+ $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
866
+ $iv = substr($ciphertext, -$block_size);
867
+ $len%= $block_size;
868
+ } else {
869
+ while ($len >= $block_size) {
870
+ $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
871
+ $ciphertext.= $iv;
872
+ $len-= $block_size;
873
+ $i+= $block_size;
874
+ }
875
+ }
876
+ }
877
+
878
+ if ($len) {
879
+ $iv = @mcrypt_generic($this->ecb, $iv);
880
+ $block = $iv ^ substr($plaintext, -$len);
881
+ $iv = substr_replace($iv, $block, 0, $len);
882
+ $ciphertext.= $block;
883
+ $pos = $len;
884
+ }
885
+
886
+ return $ciphertext;
887
+ }
888
+
889
+ $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
890
+
891
+ if (!$this->continuousBuffer) {
892
+ @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
893
+ }
894
+
895
+ return $ciphertext;
896
+ }
897
+
898
+ if ($this->changed) {
899
+ $this->_setup();
900
+ $this->changed = false;
901
+ }
902
+ if ($this->use_inline_crypt) {
903
+ $inline = $this->inline_crypt;
904
+ return $inline('encrypt', $this, $plaintext);
905
+ }
906
+
907
+ $buffer = &$this->enbuffer;
908
+ $block_size = $this->block_size;
909
+ $ciphertext = '';
910
+ switch ($this->mode) {
911
+ case CRYPT_MODE_ECB:
912
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
913
+ $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
914
+ }
915
+ break;
916
+ case CRYPT_MODE_CBC:
917
+ $xor = $this->encryptIV;
918
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
919
+ $block = substr($plaintext, $i, $block_size);
920
+ $block = $this->_encryptBlock($block ^ $xor);
921
+ $xor = $block;
922
+ $ciphertext.= $block;
923
+ }
924
+ if ($this->continuousBuffer) {
925
+ $this->encryptIV = $xor;
926
+ }
927
+ break;
928
+ case CRYPT_MODE_CTR:
929
+ $xor = $this->encryptIV;
930
+ if (strlen($buffer['ciphertext'])) {
931
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
932
+ $block = substr($plaintext, $i, $block_size);
933
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
934
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
935
+ }
936
+ $this->_increment_str($xor);
937
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
938
+ $ciphertext.= $block ^ $key;
939
+ }
940
+ } else {
941
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
942
+ $block = substr($plaintext, $i, $block_size);
943
+ $key = $this->_encryptBlock($xor);
944
+ $this->_increment_str($xor);
945
+ $ciphertext.= $block ^ $key;
946
+ }
947
+ }
948
+ if ($this->continuousBuffer) {
949
+ $this->encryptIV = $xor;
950
+ if ($start = strlen($plaintext) % $block_size) {
951
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
952
+ }
953
+ }
954
+ break;
955
+ case CRYPT_MODE_CFB:
956
+ // cfb loosely routines inspired by openssl's:
957
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
958
+ if ($this->continuousBuffer) {
959
+ $iv = &$this->encryptIV;
960
+ $pos = &$buffer['pos'];
961
+ } else {
962
+ $iv = $this->encryptIV;
963
+ $pos = 0;
964
+ }
965
+ $len = strlen($plaintext);
966
+ $i = 0;
967
+ if ($pos) {
968
+ $orig_pos = $pos;
969
+ $max = $block_size - $pos;
970
+ if ($len >= $max) {
971
+ $i = $max;
972
+ $len-= $max;
973
+ $pos = 0;
974
+ } else {
975
+ $i = $len;
976
+ $pos+= $len;
977
+ $len = 0;
978
+ }
979
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
980
+ $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
981
+ $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
982
+ }
983
+ while ($len >= $block_size) {
984
+ $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
985
+ $ciphertext.= $iv;
986
+ $len-= $block_size;
987
+ $i+= $block_size;
988
+ }
989
+ if ($len) {
990
+ $iv = $this->_encryptBlock($iv);
991
+ $block = $iv ^ substr($plaintext, $i);
992
+ $iv = substr_replace($iv, $block, 0, $len);
993
+ $ciphertext.= $block;
994
+ $pos = $len;
995
+ }
996
+ break;
997
+ case CRYPT_MODE_OFB:
998
+ $xor = $this->encryptIV;
999
+ if (strlen($buffer['xor'])) {
1000
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1001
+ $block = substr($plaintext, $i, $block_size);
1002
+ if (strlen($block) > strlen($buffer['xor'])) {
1003
+ $xor = $this->_encryptBlock($xor);
1004
+ $buffer['xor'].= $xor;
1005
+ }
1006
+ $key = $this->_string_shift($buffer['xor'], $block_size);
1007
+ $ciphertext.= $block ^ $key;
1008
+ }
1009
+ } else {
1010
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1011
+ $xor = $this->_encryptBlock($xor);
1012
+ $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
1013
+ }
1014
+ $key = $xor;
1015
+ }
1016
+ if ($this->continuousBuffer) {
1017
+ $this->encryptIV = $xor;
1018
+ if ($start = strlen($plaintext) % $block_size) {
1019
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1020
+ }
1021
+ }
1022
+ break;
1023
+ case CRYPT_MODE_STREAM:
1024
+ $ciphertext = $this->_encryptBlock($plaintext);
1025
+ break;
1026
+ }
1027
+
1028
+ return $ciphertext;
1029
+ }
1030
+
1031
+ /**
1032
+ * Decrypts a message.
1033
+ *
1034
+ * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
1035
+ * it is.
1036
+ *
1037
+ * @see self::encrypt()
1038
+ * @access public
1039
+ * @param string $ciphertext
1040
+ * @return string $plaintext
1041
+ * @internal Could, but not must, extend by the child Crypt_* class
1042
+ */
1043
+ function decrypt($ciphertext)
1044
+ {
1045
+ if ($this->paddable) {
1046
+ // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
1047
+ // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
1048
+ $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
1049
+ }
1050
+
1051
+ if ($this->engine === CRYPT_ENGINE_OPENSSL) {
1052
+ if ($this->changed) {
1053
+ $this->_clearBuffers();
1054
+ $this->changed = false;
1055
+ }
1056
+ switch ($this->mode) {
1057
+ case CRYPT_MODE_STREAM:
1058
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1059
+ break;
1060
+ case CRYPT_MODE_ECB:
1061
+ if (!defined('OPENSSL_RAW_DATA')) {
1062
+ $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
1063
+ }
1064
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
1065
+ break;
1066
+ case CRYPT_MODE_CBC:
1067
+ if (!defined('OPENSSL_RAW_DATA')) {
1068
+ $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
1069
+ $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
1070
+ $offset = 2 * $this->block_size;
1071
+ } else {
1072
+ $offset = $this->block_size;
1073
+ }
1074
+ $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
1075
+ if ($this->continuousBuffer) {
1076
+ $this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
1077
+ }
1078
+ break;
1079
+ case CRYPT_MODE_CTR:
1080
+ $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
1081
+ break;
1082
+ case CRYPT_MODE_CFB:
1083
+ // cfb loosely routines inspired by openssl's:
1084
+ // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
1085
+ $plaintext = '';
1086
+ if ($this->continuousBuffer) {
1087
+ $iv = &$this->decryptIV;
1088
+ $pos = &$this->buffer['pos'];
1089
+ } else {
1090
+ $iv = $this->decryptIV;
1091
+ $pos = 0;
1092
+ }
1093
+ $len = strlen($ciphertext);
1094
+ $i = 0;
1095
+ if ($pos) {
1096
+ $orig_pos = $pos;
1097
+ $max = $this->block_size - $pos;
1098
+ if ($len >= $max) {
1099
+ $i = $max;
1100
+ $len-= $max;
1101
+ $pos = 0;
1102
+ } else {
1103
+ $i = $len;
1104
+ $pos+= $len;
1105
+ $len = 0;
1106
+ }
1107
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
1108
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1109
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1110
+ $ciphertext = substr($ciphertext, $i);
1111
+ }
1112
+ $overflow = $len % $this->block_size;
1113
+ if ($overflow) {
1114
+ $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1115
+ if ($len - $overflow) {
1116
+ $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
1117
+ }
1118
+ $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1119
+ $plaintext.= $iv ^ substr($ciphertext, -$overflow);
1120
+ $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
1121
+ $pos = $overflow;
1122
+ } elseif ($len) {
1123
+ $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
1124
+ $iv = substr($ciphertext, -$this->block_size);
1125
+ }
1126
+ break;
1127
+ case CRYPT_MODE_OFB:
1128
+ $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
1129
+ }
1130
+
1131
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1132
+ }
1133
+
1134
+ if ($this->engine === CRYPT_ENGINE_MCRYPT) {
1135
+ $block_size = $this->block_size;
1136
+ if ($this->changed) {
1137
+ $this->_setupMcrypt();
1138
+ $this->changed = false;
1139
+ }
1140
+ if ($this->dechanged) {
1141
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1142
+ $this->dechanged = false;
1143
+ }
1144
+
1145
+ if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) {
1146
+ $iv = &$this->decryptIV;
1147
+ $pos = &$this->debuffer['pos'];
1148
+ $len = strlen($ciphertext);
1149
+ $plaintext = '';
1150
+ $i = 0;
1151
+ if ($pos) {
1152
+ $orig_pos = $pos;
1153
+ $max = $block_size - $pos;
1154
+ if ($len >= $max) {
1155
+ $i = $max;
1156
+ $len-= $max;
1157
+ $pos = 0;
1158
+ } else {
1159
+ $i = $len;
1160
+ $pos+= $len;
1161
+ $len = 0;
1162
+ }
1163
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1164
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1165
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1166
+ }
1167
+ if ($len >= $block_size) {
1168
+ $cb = substr($ciphertext, $i, $len - $len % $block_size);
1169
+ $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
1170
+ $iv = substr($cb, -$block_size);
1171
+ $len%= $block_size;
1172
+ }
1173
+ if ($len) {
1174
+ $iv = @mcrypt_generic($this->ecb, $iv);
1175
+ $plaintext.= $iv ^ substr($ciphertext, -$len);
1176
+ $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
1177
+ $pos = $len;
1178
+ }
1179
+
1180
+ return $plaintext;
1181
+ }
1182
+
1183
+ $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
1184
+
1185
+ if (!$this->continuousBuffer) {
1186
+ @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
1187
+ }
1188
+
1189
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1190
+ }
1191
+
1192
+ if ($this->changed) {
1193
+ $this->_setup();
1194
+ $this->changed = false;
1195
+ }
1196
+ if ($this->use_inline_crypt) {
1197
+ $inline = $this->inline_crypt;
1198
+ return $inline('decrypt', $this, $ciphertext);
1199
+ }
1200
+
1201
+ $block_size = $this->block_size;
1202
+
1203
+ $buffer = &$this->debuffer;
1204
+ $plaintext = '';
1205
+ switch ($this->mode) {
1206
+ case CRYPT_MODE_ECB:
1207
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1208
+ $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
1209
+ }
1210
+ break;
1211
+ case CRYPT_MODE_CBC:
1212
+ $xor = $this->decryptIV;
1213
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1214
+ $block = substr($ciphertext, $i, $block_size);
1215
+ $plaintext.= $this->_decryptBlock($block) ^ $xor;
1216
+ $xor = $block;
1217
+ }
1218
+ if ($this->continuousBuffer) {
1219
+ $this->decryptIV = $xor;
1220
+ }
1221
+ break;
1222
+ case CRYPT_MODE_CTR:
1223
+ $xor = $this->decryptIV;
1224
+ if (strlen($buffer['ciphertext'])) {
1225
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1226
+ $block = substr($ciphertext, $i, $block_size);
1227
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
1228
+ $buffer['ciphertext'].= $this->_encryptBlock($xor);
1229
+ $this->_increment_str($xor);
1230
+ }
1231
+ $key = $this->_string_shift($buffer['ciphertext'], $block_size);
1232
+ $plaintext.= $block ^ $key;
1233
+ }
1234
+ } else {
1235
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1236
+ $block = substr($ciphertext, $i, $block_size);
1237
+ $key = $this->_encryptBlock($xor);
1238
+ $this->_increment_str($xor);
1239
+ $plaintext.= $block ^ $key;
1240
+ }
1241
+ }
1242
+ if ($this->continuousBuffer) {
1243
+ $this->decryptIV = $xor;
1244
+ if ($start = strlen($ciphertext) % $block_size) {
1245
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1246
+ }
1247
+ }
1248
+ break;
1249
+ case CRYPT_MODE_CFB:
1250
+ if ($this->continuousBuffer) {
1251
+ $iv = &$this->decryptIV;
1252
+ $pos = &$buffer['pos'];
1253
+ } else {
1254
+ $iv = $this->decryptIV;
1255
+ $pos = 0;
1256
+ }
1257
+ $len = strlen($ciphertext);
1258
+ $i = 0;
1259
+ if ($pos) {
1260
+ $orig_pos = $pos;
1261
+ $max = $block_size - $pos;
1262
+ if ($len >= $max) {
1263
+ $i = $max;
1264
+ $len-= $max;
1265
+ $pos = 0;
1266
+ } else {
1267
+ $i = $len;
1268
+ $pos+= $len;
1269
+ $len = 0;
1270
+ }
1271
+ // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
1272
+ $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
1273
+ $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
1274
+ }
1275
+ while ($len >= $block_size) {
1276
+ $iv = $this->_encryptBlock($iv);
1277
+ $cb = substr($ciphertext, $i, $block_size);
1278
+ $plaintext.= $iv ^ $cb;
1279
+ $iv = $cb;
1280
+ $len-= $block_size;
1281
+ $i+= $block_size;
1282
+ }
1283
+ if ($len) {
1284
+ $iv = $this->_encryptBlock($iv);
1285
+ $plaintext.= $iv ^ substr($ciphertext, $i);
1286
+ $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
1287
+ $pos = $len;
1288
+ }
1289
+ break;
1290
+ case CRYPT_MODE_OFB:
1291
+ $xor = $this->decryptIV;
1292
+ if (strlen($buffer['xor'])) {
1293
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1294
+ $block = substr($ciphertext, $i, $block_size);
1295
+ if (strlen($block) > strlen($buffer['xor'])) {
1296
+ $xor = $this->_encryptBlock($xor);
1297
+ $buffer['xor'].= $xor;
1298
+ }
1299
+ $key = $this->_string_shift($buffer['xor'], $block_size);
1300
+ $plaintext.= $block ^ $key;
1301
+ }
1302
+ } else {
1303
+ for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
1304
+ $xor = $this->_encryptBlock($xor);
1305
+ $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
1306
+ }
1307
+ $key = $xor;
1308
+ }
1309
+ if ($this->continuousBuffer) {
1310
+ $this->decryptIV = $xor;
1311
+ if ($start = strlen($ciphertext) % $block_size) {
1312
+ $buffer['xor'] = substr($key, $start) . $buffer['xor'];
1313
+ }
1314
+ }
1315
+ break;
1316
+ case CRYPT_MODE_STREAM:
1317
+ $plaintext = $this->_decryptBlock($ciphertext);
1318
+ break;
1319
+ }
1320
+ return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
1321
+ }
1322
+
1323
+ /**
1324
+ * OpenSSL CTR Processor
1325
+ *
1326
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1327
+ * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1328
+ * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
1329
+ * function will emulate CTR with ECB when necessary.
1330
+ *
1331
+ * @see self::encrypt()
1332
+ * @see self::decrypt()
1333
+ * @param string $plaintext
1334
+ * @param string $encryptIV
1335
+ * @param array $buffer
1336
+ * @return string
1337
+ * @access private
1338
+ */
1339
+ function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
1340
+ {
1341
+ $ciphertext = '';
1342
+
1343
+ $block_size = $this->block_size;
1344
+ $key = $this->key;
1345
+
1346
+ if ($this->openssl_emulate_ctr) {
1347
+ $xor = $encryptIV;
1348
+ if (strlen($buffer['ciphertext'])) {
1349
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1350
+ $block = substr($plaintext, $i, $block_size);
1351
+ if (strlen($block) > strlen($buffer['ciphertext'])) {
1352
+ $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1353
+ $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
1354
+ $buffer['ciphertext'].= $result;
1355
+ }
1356
+ $this->_increment_str($xor);
1357
+ $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
1358
+ $ciphertext.= $block ^ $otp;
1359
+ }
1360
+ } else {
1361
+ for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
1362
+ $block = substr($plaintext, $i, $block_size);
1363
+ $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1364
+ $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
1365
+ $this->_increment_str($xor);
1366
+ $ciphertext.= $block ^ $otp;
1367
+ }
1368
+ }
1369
+ if ($this->continuousBuffer) {
1370
+ $encryptIV = $xor;
1371
+ if ($start = strlen($plaintext) % $block_size) {
1372
+ $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
1373
+ }
1374
+ }
1375
+
1376
+ return $ciphertext;
1377
+ }
1378
+
1379
+ if (strlen($buffer['ciphertext'])) {
1380
+ $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
1381
+ $plaintext = substr($plaintext, strlen($ciphertext));
1382
+
1383
+ if (!strlen($plaintext)) {
1384
+ return $ciphertext;
1385
+ }
1386
+ }
1387
+
1388
+ $overflow = strlen($plaintext) % $block_size;
1389
+ if ($overflow) {
1390
+ $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
1391
+ $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1392
+ $temp = $this->_string_pop($encrypted, $block_size);
1393
+ $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
1394
+ if ($this->continuousBuffer) {
1395
+ $buffer['ciphertext'] = substr($temp, $overflow);
1396
+ $encryptIV = $temp;
1397
+ }
1398
+ } elseif (!strlen($buffer['ciphertext'])) {
1399
+ $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1400
+ $temp = $this->_string_pop($ciphertext, $block_size);
1401
+ if ($this->continuousBuffer) {
1402
+ $encryptIV = $temp;
1403
+ }
1404
+ }
1405
+ if ($this->continuousBuffer) {
1406
+ if (!defined('OPENSSL_RAW_DATA')) {
1407
+ $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1408
+ }
1409
+ $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
1410
+ if ($overflow) {
1411
+ $this->_increment_str($encryptIV);
1412
+ }
1413
+ }
1414
+
1415
+ return $ciphertext;
1416
+ }
1417
+
1418
+ /**
1419
+ * OpenSSL OFB Processor
1420
+ *
1421
+ * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
1422
+ * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt()
1423
+ * and Crypt_Base::decrypt().
1424
+ *
1425
+ * @see self::encrypt()
1426
+ * @see self::decrypt()
1427
+ * @param string $plaintext
1428
+ * @param string $encryptIV
1429
+ * @param array $buffer
1430
+ * @return string
1431
+ * @access private
1432
+ */
1433
+ function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
1434
+ {
1435
+ if (strlen($buffer['xor'])) {
1436
+ $ciphertext = $plaintext ^ $buffer['xor'];
1437
+ $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
1438
+ $plaintext = substr($plaintext, strlen($ciphertext));
1439
+ } else {
1440
+ $ciphertext = '';
1441
+ }
1442
+
1443
+ $block_size = $this->block_size;
1444
+
1445
+ $len = strlen($plaintext);
1446
+ $key = $this->key;
1447
+ $overflow = $len % $block_size;
1448
+
1449
+ if (strlen($plaintext)) {
1450
+ if ($overflow) {
1451
+ $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1452
+ $xor = $this->_string_pop($ciphertext, $block_size);
1453
+ if ($this->continuousBuffer) {
1454
+ $encryptIV = $xor;
1455
+ }
1456
+ $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
1457
+ if ($this->continuousBuffer) {
1458
+ $buffer['xor'] = $xor;
1459
+ }
1460
+ } else {
1461
+ $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
1462
+ if ($this->continuousBuffer) {
1463
+ $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
1464
+ }
1465
+ }
1466
+ }
1467
+
1468
+ return $ciphertext;
1469
+ }
1470
+
1471
+ /**
1472
+ * phpseclib <-> OpenSSL Mode Mapper
1473
+ *
1474
+ * May need to be overwritten by classes extending this one in some cases
1475
+ *
1476
+ * @return int
1477
+ * @access private
1478
+ */
1479
+ function _openssl_translate_mode()
1480
+ {
1481
+ switch ($this->mode) {
1482
+ case CRYPT_MODE_ECB:
1483
+ return 'ecb';
1484
+ case CRYPT_MODE_CBC:
1485
+ return 'cbc';
1486
+ case CRYPT_MODE_CTR:
1487
+ return 'ctr';
1488
+ case CRYPT_MODE_CFB:
1489
+ return 'cfb';
1490
+ case CRYPT_MODE_OFB:
1491
+ return 'ofb';
1492
+ }
1493
+ }
1494
+
1495
+ /**
1496
+ * Pad "packets".
1497
+ *
1498
+ * Block ciphers working by encrypting between their specified [$this->]block_size at a time
1499
+ * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
1500
+ * pad the input so that it is of the proper length.
1501
+ *
1502
+ * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
1503
+ * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
1504
+ * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
1505
+ * transmitted separately)
1506
+ *
1507
+ * @see self::disablePadding()
1508
+ * @access public
1509
+ */
1510
+ function enablePadding()
1511
+ {
1512
+ $this->padding = true;
1513
+ }
1514
+
1515
+ /**
1516
+ * Do not pad packets.
1517
+ *
1518
+ * @see self::enablePadding()
1519
+ * @access public
1520
+ */
1521
+ function disablePadding()
1522
+ {
1523
+ $this->padding = false;
1524
+ }
1525
+
1526
+ /**
1527
+ * Treat consecutive "packets" as if they are a continuous buffer.
1528
+ *
1529
+ * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
1530
+ * will yield different outputs:
1531
+ *
1532
+ * <code>
1533
+ * echo $rijndael->encrypt(substr($plaintext, 0, 16));
1534
+ * echo $rijndael->encrypt(substr($plaintext, 16, 16));
1535
+ * </code>
1536
+ * <code>
1537
+ * echo $rijndael->encrypt($plaintext);
1538
+ * </code>
1539
+ *
1540
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
1541
+ * another, as demonstrated with the following:
1542
+ *
1543
+ * <code>
1544
+ * $rijndael->encrypt(substr($plaintext, 0, 16));
1545
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1546
+ * </code>
1547
+ * <code>
1548
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
1549
+ * </code>
1550
+ *
1551
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
1552
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
1553
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
1554
+ *
1555
+ * Put another way, when the continuous buffer is enabled, the state of the Crypt_*() object changes after each
1556
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
1557
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
1558
+ * however, they are also less intuitive and more likely to cause you problems.
1559
+ *
1560
+ * @see self::disableContinuousBuffer()
1561
+ * @access public
1562
+ * @internal Could, but not must, extend by the child Crypt_* class
1563
+ */
1564
+ function enableContinuousBuffer()
1565
+ {
1566
+ if ($this->mode == CRYPT_MODE_ECB) {
1567
+ return;
1568
+ }
1569
+
1570
+ $this->continuousBuffer = true;
1571
+
1572
+ $this->_setEngine();
1573
+ }
1574
+
1575
+ /**
1576
+ * Treat consecutive packets as if they are a discontinuous buffer.
1577
+ *
1578
+ * The default behavior.
1579
+ *
1580
+ * @see self::enableContinuousBuffer()
1581
+ * @access public
1582
+ * @internal Could, but not must, extend by the child Crypt_* class
1583
+ */
1584
+ function disableContinuousBuffer()
1585
+ {
1586
+ if ($this->mode == CRYPT_MODE_ECB) {
1587
+ return;
1588
+ }
1589
+ if (!$this->continuousBuffer) {
1590
+ return;
1591
+ }
1592
+
1593
+ $this->continuousBuffer = false;
1594
+ $this->changed = true;
1595
+
1596
+ $this->_setEngine();
1597
+ }
1598
+
1599
+ /**
1600
+ * Test for engine validity
1601
+ *
1602
+ * @see self::Crypt_Base()
1603
+ * @param int $engine
1604
+ * @access public
1605
+ * @return bool
1606
+ */
1607
+ function isValidEngine($engine)
1608
+ {
1609
+ switch ($engine) {
1610
+ case CRYPT_ENGINE_OPENSSL:
1611
+ if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) {
1612
+ return false;
1613
+ }
1614
+ $this->openssl_emulate_ctr = false;
1615
+ $result = $this->cipher_name_openssl &&
1616
+ extension_loaded('openssl') &&
1617
+ // PHP 5.3.0 - 5.3.2 did not let you set IV's
1618
+ version_compare(PHP_VERSION, '5.3.3', '>=');
1619
+ if (!$result) {
1620
+ return false;
1621
+ }
1622
+
1623
+ // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
1624
+ // $options openssl_encrypt expected a boolean $raw_data.
1625
+ if (!defined('OPENSSL_RAW_DATA')) {
1626
+ $this->openssl_options = true;
1627
+ } else {
1628
+ $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1629
+ }
1630
+
1631
+ $methods = openssl_get_cipher_methods();
1632
+ if (in_array($this->cipher_name_openssl, $methods)) {
1633
+ return true;
1634
+ }
1635
+ // not all of openssl's symmetric cipher's support ctr. for those
1636
+ // that don't we'll emulate it
1637
+ switch ($this->mode) {
1638
+ case CRYPT_MODE_CTR:
1639
+ if (in_array($this->cipher_name_openssl_ecb, $methods)) {
1640
+ $this->openssl_emulate_ctr = true;
1641
+ return true;
1642
+ }
1643
+ }
1644
+ return false;
1645
+ case CRYPT_ENGINE_MCRYPT:
1646
+ return $this->cipher_name_mcrypt &&
1647
+ extension_loaded('mcrypt') &&
1648
+ in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
1649
+ case CRYPT_ENGINE_INTERNAL:
1650
+ return true;
1651
+ }
1652
+
1653
+ return false;
1654
+ }
1655
+
1656
+ /**
1657
+ * Sets the preferred crypt engine
1658
+ *
1659
+ * Currently, $engine could be:
1660
+ *
1661
+ * - CRYPT_ENGINE_OPENSSL [very fast]
1662
+ *
1663
+ * - CRYPT_ENGINE_MCRYPT [fast]
1664
+ *
1665
+ * - CRYPT_ENGINE_INTERNAL [slow]
1666
+ *
1667
+ * If the preferred crypt engine is not available the fastest available one will be used
1668
+ *
1669
+ * @see self::Crypt_Base()
1670
+ * @param int $engine
1671
+ * @access public
1672
+ */
1673
+ function setPreferredEngine($engine)
1674
+ {
1675
+ switch ($engine) {
1676
+ //case CRYPT_ENGINE_OPENSSL:
1677
+ case CRYPT_ENGINE_MCRYPT:
1678
+ case CRYPT_ENGINE_INTERNAL:
1679
+ $this->preferredEngine = $engine;
1680
+ break;
1681
+ default:
1682
+ $this->preferredEngine = CRYPT_ENGINE_OPENSSL;
1683
+ }
1684
+
1685
+ $this->_setEngine();
1686
+ }
1687
+
1688
+ /**
1689
+ * Returns the engine currently being utilized
1690
+ *
1691
+ * @see self::_setEngine()
1692
+ * @access public
1693
+ */
1694
+ function getEngine()
1695
+ {
1696
+ return $this->engine;
1697
+ }
1698
+
1699
+ /**
1700
+ * Sets the engine as appropriate
1701
+ *
1702
+ * @see self::Crypt_Base()
1703
+ * @access private
1704
+ */
1705
+ function _setEngine()
1706
+ {
1707
+ $this->engine = null;
1708
+
1709
+ $candidateEngines = array(
1710
+ $this->preferredEngine,
1711
+ CRYPT_ENGINE_OPENSSL,
1712
+ CRYPT_ENGINE_MCRYPT
1713
+ );
1714
+ foreach ($candidateEngines as $engine) {
1715
+ if ($this->isValidEngine($engine)) {
1716
+ $this->engine = $engine;
1717
+ break;
1718
+ }
1719
+ }
1720
+ if (!$this->engine) {
1721
+ $this->engine = CRYPT_ENGINE_INTERNAL;
1722
+ }
1723
+
1724
+ if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) {
1725
+ // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
1726
+ // (re)open them with the module named in $this->cipher_name_mcrypt
1727
+ @mcrypt_module_close($this->enmcrypt);
1728
+ @mcrypt_module_close($this->demcrypt);
1729
+ $this->enmcrypt = null;
1730
+ $this->demcrypt = null;
1731
+
1732
+ if ($this->ecb) {
1733
+ @mcrypt_module_close($this->ecb);
1734
+ $this->ecb = null;
1735
+ }
1736
+ }
1737
+
1738
+ $this->changed = true;
1739
+ }
1740
+
1741
+ /**
1742
+ * Encrypts a block
1743
+ *
1744
+ * @access private
1745
+ * @param string $in
1746
+ * @return string
1747
+ * @internal Must be extended by the child Crypt_* class
1748
+ */
1749
+ function _encryptBlock($in)
1750
+ {
1751
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1752
+ }
1753
+
1754
+ /**
1755
+ * Decrypts a block
1756
+ *
1757
+ * @access private
1758
+ * @param string $in
1759
+ * @return string
1760
+ * @internal Must be extended by the child Crypt_* class
1761
+ */
1762
+ function _decryptBlock($in)
1763
+ {
1764
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1765
+ }
1766
+
1767
+ /**
1768
+ * Setup the key (expansion)
1769
+ *
1770
+ * Only used if $engine == CRYPT_ENGINE_INTERNAL
1771
+ *
1772
+ * @see self::_setup()
1773
+ * @access private
1774
+ * @internal Must be extended by the child Crypt_* class
1775
+ */
1776
+ function _setupKey()
1777
+ {
1778
+ user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR);
1779
+ }
1780
+
1781
+ /**
1782
+ * Setup the CRYPT_ENGINE_INTERNAL $engine
1783
+ *
1784
+ * (re)init, if necessary, the internal cipher $engine and flush all $buffers
1785
+ * Used (only) if $engine == CRYPT_ENGINE_INTERNAL
1786
+ *
1787
+ * _setup() will be called each time if $changed === true
1788
+ * typically this happens when using one or more of following public methods:
1789
+ *
1790
+ * - setKey()
1791
+ *
1792
+ * - setIV()
1793
+ *
1794
+ * - disableContinuousBuffer()
1795
+ *
1796
+ * - First run of encrypt() / decrypt() with no init-settings
1797
+ *
1798
+ * @see self::setKey()
1799
+ * @see self::setIV()
1800
+ * @see self::disableContinuousBuffer()
1801
+ * @access private
1802
+ * @internal _setup() is always called before en/decryption.
1803
+ * @internal Could, but not must, extend by the child Crypt_* class
1804
+ */
1805
+ function _setup()
1806
+ {
1807
+ $this->_clearBuffers();
1808
+ $this->_setupKey();
1809
+
1810
+ if ($this->use_inline_crypt) {
1811
+ $this->_setupInlineCrypt();
1812
+ }
1813
+ }
1814
+
1815
+ /**
1816
+ * Setup the CRYPT_ENGINE_MCRYPT $engine
1817
+ *
1818
+ * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
1819
+ * Used (only) if $engine = CRYPT_ENGINE_MCRYPT
1820
+ *
1821
+ * _setupMcrypt() will be called each time if $changed === true
1822
+ * typically this happens when using one or more of following public methods:
1823
+ *
1824
+ * - setKey()
1825
+ *
1826
+ * - setIV()
1827
+ *
1828
+ * - disableContinuousBuffer()
1829
+ *
1830
+ * - First run of encrypt() / decrypt()
1831
+ *
1832
+ * @see self::setKey()
1833
+ * @see self::setIV()
1834
+ * @see self::disableContinuousBuffer()
1835
+ * @access private
1836
+ * @internal Could, but not must, extend by the child Crypt_* class
1837
+ */
1838
+ function _setupMcrypt()
1839
+ {
1840
+ $this->_clearBuffers();
1841
+ $this->enchanged = $this->dechanged = true;
1842
+
1843
+ if (!isset($this->enmcrypt)) {
1844
+ static $mcrypt_modes = array(
1845
+ CRYPT_MODE_CTR => 'ctr',
1846
+ CRYPT_MODE_ECB => MCRYPT_MODE_ECB,
1847
+ CRYPT_MODE_CBC => MCRYPT_MODE_CBC,
1848
+ CRYPT_MODE_CFB => 'ncfb',
1849
+ CRYPT_MODE_OFB => MCRYPT_MODE_NOFB,
1850
+ CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM,
1851
+ );
1852
+
1853
+ $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1854
+ $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
1855
+
1856
+ // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
1857
+ // to workaround mcrypt's broken ncfb implementation in buffered mode
1858
+ // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
1859
+ if ($this->mode == CRYPT_MODE_CFB) {
1860
+ $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
1861
+ }
1862
+ } // else should mcrypt_generic_deinit be called?
1863
+
1864
+ if ($this->mode == CRYPT_MODE_CFB) {
1865
+ @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
1866
+ }
1867
+ }
1868
+
1869
+ /**
1870
+ * Pads a string
1871
+ *
1872
+ * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
1873
+ * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
1874
+ * chr($this->block_size - (strlen($text) % $this->block_size)
1875
+ *
1876
+ * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
1877
+ * and padding will, hence forth, be enabled.
1878
+ *
1879
+ * @see self::_unpad()
1880
+ * @param string $text
1881
+ * @access private
1882
+ * @return string
1883
+ */
1884
+ function _pad($text)
1885
+ {
1886
+ $length = strlen($text);
1887
+
1888
+ if (!$this->padding) {
1889
+ if ($length % $this->block_size == 0) {
1890
+ return $text;
1891
+ } else {
1892
+ user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
1893
+ $this->padding = true;
1894
+ }
1895
+ }
1896
+
1897
+ $pad = $this->block_size - ($length % $this->block_size);
1898
+
1899
+ return str_pad($text, $length + $pad, chr($pad));
1900
+ }
1901
+
1902
+ /**
1903
+ * Unpads a string.
1904
+ *
1905
+ * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
1906
+ * and false will be returned.
1907
+ *
1908
+ * @see self::_pad()
1909
+ * @param string $text
1910
+ * @access private
1911
+ * @return string
1912
+ */
1913
+ function _unpad($text)
1914
+ {
1915
+ if (!$this->padding) {
1916
+ return $text;
1917
+ }
1918
+
1919
+ $length = ord($text[strlen($text) - 1]);
1920
+
1921
+ if (!$length || $length > $this->block_size) {
1922
+ return false;
1923
+ }
1924
+
1925
+ return substr($text, 0, -$length);
1926
+ }
1927
+
1928
+ /**
1929
+ * Clears internal buffers
1930
+ *
1931
+ * Clearing/resetting the internal buffers is done everytime
1932
+ * after disableContinuousBuffer() or on cipher $engine (re)init
1933
+ * ie after setKey() or setIV()
1934
+ *
1935
+ * @access public
1936
+ * @internal Could, but not must, extend by the child Crypt_* class
1937
+ */
1938
+ function _clearBuffers()
1939
+ {
1940
+ $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
1941
+
1942
+ // mcrypt's handling of invalid's $iv:
1943
+ // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
1944
+ $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
1945
+
1946
+ if (!$this->skip_key_adjustment) {
1947
+ $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
1948
+ }
1949
+ }
1950
+
1951
+ /**
1952
+ * String Shift
1953
+ *
1954
+ * Inspired by array_shift
1955
+ *
1956
+ * @param string $string
1957
+ * @param int $index
1958
+ * @access private
1959
+ * @return string
1960
+ */
1961
+ function _string_shift(&$string, $index = 1)
1962
+ {
1963
+ $substr = substr($string, 0, $index);
1964
+ $string = substr($string, $index);
1965
+ return $substr;
1966
+ }
1967
+
1968
+ /**
1969
+ * String Pop
1970
+ *
1971
+ * Inspired by array_pop
1972
+ *
1973
+ * @param string $string
1974
+ * @param int $index
1975
+ * @access private
1976
+ * @return string
1977
+ */
1978
+ function _string_pop(&$string, $index = 1)
1979
+ {
1980
+ $substr = substr($string, -$index);
1981
+ $string = substr($string, 0, -$index);
1982
+ return $substr;
1983
+ }
1984
+
1985
+ /**
1986
+ * Increment the current string
1987
+ *
1988
+ * @see self::decrypt()
1989
+ * @see self::encrypt()
1990
+ * @param string $var
1991
+ * @access private
1992
+ */
1993
+ function _increment_str(&$var)
1994
+ {
1995
+ for ($i = 4; $i <= strlen($var); $i+= 4) {
1996
+ $temp = substr($var, -$i, 4);
1997
+ switch ($temp) {
1998
+ case "\xFF\xFF\xFF\xFF":
1999
+ $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
2000
+ break;
2001
+ case "\x7F\xFF\xFF\xFF":
2002
+ $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
2003
+ return;
2004
+ default:
2005
+ $temp = unpack('Nnum', $temp);
2006
+ $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
2007
+ return;
2008
+ }
2009
+ }
2010
+
2011
+ $remainder = strlen($var) % 4;
2012
+
2013
+ if ($remainder == 0) {
2014
+ return;
2015
+ }
2016
+
2017
+ $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
2018
+ $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
2019
+ $var = substr_replace($var, $temp, 0, $remainder);
2020
+ }
2021
+
2022
+ /**
2023
+ * Setup the performance-optimized function for de/encrypt()
2024
+ *
2025
+ * Stores the created (or existing) callback function-name
2026
+ * in $this->inline_crypt
2027
+ *
2028
+ * Internally for phpseclib developers:
2029
+ *
2030
+ * _setupInlineCrypt() would be called only if:
2031
+ *
2032
+ * - $engine == CRYPT_ENGINE_INTERNAL and
2033
+ *
2034
+ * - $use_inline_crypt === true
2035
+ *
2036
+ * - each time on _setup(), after(!) _setupKey()
2037
+ *
2038
+ *
2039
+ * This ensures that _setupInlineCrypt() has always a
2040
+ * full ready2go initializated internal cipher $engine state
2041
+ * where, for example, the keys allready expanded,
2042
+ * keys/block_size calculated and such.
2043
+ *
2044
+ * It is, each time if called, the responsibility of _setupInlineCrypt():
2045
+ *
2046
+ * - to set $this->inline_crypt to a valid and fully working callback function
2047
+ * as a (faster) replacement for encrypt() / decrypt()
2048
+ *
2049
+ * - NOT to create unlimited callback functions (for memory reasons!)
2050
+ * no matter how often _setupInlineCrypt() would be called. At some
2051
+ * point of amount they must be generic re-useable.
2052
+ *
2053
+ * - the code of _setupInlineCrypt() it self,
2054
+ * and the generated callback code,
2055
+ * must be, in following order:
2056
+ * - 100% safe
2057
+ * - 100% compatible to encrypt()/decrypt()
2058
+ * - using only php5+ features/lang-constructs/php-extensions if
2059
+ * compatibility (down to php4) or fallback is provided
2060
+ * - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
2061
+ * - >= 10% faster than encrypt()/decrypt() [which is, by the way,
2062
+ * the reason for the existence of _setupInlineCrypt() :-)]
2063
+ * - memory-nice
2064
+ * - short (as good as possible)
2065
+ *
2066
+ * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
2067
+ * - In case of using inline crypting, _setupInlineCrypt() must extend by the child Crypt_* class.
2068
+ * - The following variable names are reserved:
2069
+ * - $_* (all variable names prefixed with an underscore)
2070
+ * - $self (object reference to it self. Do not use $this, but $self instead)
2071
+ * - $in (the content of $in has to en/decrypt by the generated code)
2072
+ * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
2073
+ *
2074
+ *
2075
+ * @see self::_setup()
2076
+ * @see self::_createInlineCryptFunction()
2077
+ * @see self::encrypt()
2078
+ * @see self::decrypt()
2079
+ * @access private
2080
+ * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
2081
+ */
2082
+ function _setupInlineCrypt()
2083
+ {
2084
+ // If, for any reason, an extending Crypt_Base() Crypt_* class
2085
+ // not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
2086
+ // ie in the class var declaration of $use_inline_crypt in general for the Crypt_* class,
2087
+ // in the constructor at object instance-time
2088
+ // or, if it's runtime-specific, at runtime
2089
+
2090
+ $this->use_inline_crypt = false;
2091
+ }
2092
+
2093
+ /**
2094
+ * Creates the performance-optimized function for en/decrypt()
2095
+ *
2096
+ * Internally for phpseclib developers:
2097
+ *
2098
+ * _createInlineCryptFunction():
2099
+ *
2100
+ * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
2101
+ * with the current [$this->]mode of operation code
2102
+ *
2103
+ * - create the $inline function, which called by encrypt() / decrypt()
2104
+ * as its replacement to speed up the en/decryption operations.
2105
+ *
2106
+ * - return the name of the created $inline callback function
2107
+ *
2108
+ * - used to speed up en/decryption
2109
+ *
2110
+ *
2111
+ *
2112
+ * The main reason why can speed up things [up to 50%] this way are:
2113
+ *
2114
+ * - using variables more effective then regular.
2115
+ * (ie no use of expensive arrays but integers $k_0, $k_1 ...
2116
+ * or even, for example, the pure $key[] values hardcoded)
2117
+ *
2118
+ * - avoiding 1000's of function calls of ie _encryptBlock()
2119
+ * but inlining the crypt operations.
2120
+ * in the mode of operation for() loop.
2121
+ *
2122
+ * - full loop unroll the (sometimes key-dependent) rounds
2123
+ * avoiding this way ++$i counters and runtime-if's etc...
2124
+ *
2125
+ * The basic code architectur of the generated $inline en/decrypt()
2126
+ * lambda function, in pseudo php, is:
2127
+ *
2128
+ * <code>
2129
+ * +----------------------------------------------------------------------------------------------+
2130
+ * | callback $inline = create_function: |
2131
+ * | lambda_function_0001_crypt_ECB($action, $text) |
2132
+ * | { |
2133
+ * | INSERT PHP CODE OF: |
2134
+ * | $cipher_code['init_crypt']; // general init code. |
2135
+ * | // ie: $sbox'es declarations used for |
2136
+ * | // encrypt and decrypt'ing. |
2137
+ * | |
2138
+ * | switch ($action) { |
2139
+ * | case 'encrypt': |
2140
+ * | INSERT PHP CODE OF: |
2141
+ * | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
2142
+ * | ie: specified $key or $box |
2143
+ * | declarations for encrypt'ing. |
2144
+ * | |
2145
+ * | foreach ($ciphertext) { |
2146
+ * | $in = $block_size of $ciphertext; |
2147
+ * | |
2148
+ * | INSERT PHP CODE OF: |
2149
+ * | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
2150
+ * | // strlen($in) == $this->block_size |
2151
+ * | // here comes the cipher algorithm in action |
2152
+ * | // for encryption. |
2153
+ * | // $cipher_code['encrypt_block'] has to |
2154
+ * | // encrypt the content of the $in variable |
2155
+ * | |
2156
+ * | $plaintext .= $in; |
2157
+ * | } |
2158
+ * | return $plaintext; |
2159
+ * | |
2160
+ * | case 'decrypt': |
2161
+ * | INSERT PHP CODE OF: |
2162
+ * | $cipher_code['init_decrypt']; // decrypt sepcific init code |
2163
+ * | ie: specified $key or $box |
2164
+ * | declarations for decrypt'ing. |
2165
+ * | foreach ($plaintext) { |
2166
+ * | $in = $block_size of $plaintext; |
2167
+ * | |
2168
+ * | INSERT PHP CODE OF: |
2169
+ * | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
2170
+ * | // strlen($in) == $this->block_size |
2171
+ * | // here comes the cipher algorithm in action |
2172
+ * | // for decryption. |
2173
+ * | // $cipher_code['decrypt_block'] has to |
2174
+ * | // decrypt the content of the $in variable |
2175
+ * | $ciphertext .= $in; |
2176
+ * | } |
2177
+ * | return $ciphertext; |
2178
+ * | } |
2179
+ * | } |
2180
+ * +----------------------------------------------------------------------------------------------+
2181
+ * </code>
2182
+ *
2183
+ * See also the Crypt_*::_setupInlineCrypt()'s for
2184
+ * productive inline $cipher_code's how they works.
2185
+ *
2186
+ * Structure of:
2187
+ * <code>
2188
+ * $cipher_code = array(
2189
+ * 'init_crypt' => (string) '', // optional
2190
+ * 'init_encrypt' => (string) '', // optional
2191
+ * 'init_decrypt' => (string) '', // optional
2192
+ * 'encrypt_block' => (string) '', // required
2193
+ * 'decrypt_block' => (string) '' // required
2194
+ * );
2195
+ * </code>
2196
+ *
2197
+ * @see self::_setupInlineCrypt()
2198
+ * @see self::encrypt()
2199
+ * @see self::decrypt()
2200
+ * @param array $cipher_code
2201
+ * @access private
2202
+ * @return string (the name of the created callback function)
2203
+ */
2204
+ function _createInlineCryptFunction($cipher_code)
2205
+ {
2206
+ $block_size = $this->block_size;
2207
+
2208
+ // optional
2209
+ $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
2210
+ $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
2211
+ $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
2212
+ // required
2213
+ $encrypt_block = $cipher_code['encrypt_block'];
2214
+ $decrypt_block = $cipher_code['decrypt_block'];
2215
+
2216
+ // Generating mode of operation inline code,
2217
+ // merged with the $cipher_code algorithm
2218
+ // for encrypt- and decryption.
2219
+ switch ($this->mode) {
2220
+ case CRYPT_MODE_ECB:
2221
+ $encrypt = $init_encrypt . '
2222
+ $_ciphertext = "";
2223
+ $_plaintext_len = strlen($_text);
2224
+
2225
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2226
+ $in = substr($_text, $_i, '.$block_size.');
2227
+ '.$encrypt_block.'
2228
+ $_ciphertext.= $in;
2229
+ }
2230
+
2231
+ return $_ciphertext;
2232
+ ';
2233
+
2234
+ $decrypt = $init_decrypt . '
2235
+ $_plaintext = "";
2236
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2237
+ $_ciphertext_len = strlen($_text);
2238
+
2239
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2240
+ $in = substr($_text, $_i, '.$block_size.');
2241
+ '.$decrypt_block.'
2242
+ $_plaintext.= $in;
2243
+ }
2244
+
2245
+ return $self->_unpad($_plaintext);
2246
+ ';
2247
+ break;
2248
+ case CRYPT_MODE_CTR:
2249
+ $encrypt = $init_encrypt . '
2250
+ $_ciphertext = "";
2251
+ $_plaintext_len = strlen($_text);
2252
+ $_xor = $self->encryptIV;
2253
+ $_buffer = &$self->enbuffer;
2254
+ if (strlen($_buffer["ciphertext"])) {
2255
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2256
+ $_block = substr($_text, $_i, '.$block_size.');
2257
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2258
+ $in = $_xor;
2259
+ '.$encrypt_block.'
2260
+ $self->_increment_str($_xor);
2261
+ $_buffer["ciphertext"].= $in;
2262
+ }
2263
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2264
+ $_ciphertext.= $_block ^ $_key;
2265
+ }
2266
+ } else {
2267
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2268
+ $_block = substr($_text, $_i, '.$block_size.');
2269
+ $in = $_xor;
2270
+ '.$encrypt_block.'
2271
+ $self->_increment_str($_xor);
2272
+ $_key = $in;
2273
+ $_ciphertext.= $_block ^ $_key;
2274
+ }
2275
+ }
2276
+ if ($self->continuousBuffer) {
2277
+ $self->encryptIV = $_xor;
2278
+ if ($_start = $_plaintext_len % '.$block_size.') {
2279
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2280
+ }
2281
+ }
2282
+
2283
+ return $_ciphertext;
2284
+ ';
2285
+
2286
+ $decrypt = $init_encrypt . '
2287
+ $_plaintext = "";
2288
+ $_ciphertext_len = strlen($_text);
2289
+ $_xor = $self->decryptIV;
2290
+ $_buffer = &$self->debuffer;
2291
+
2292
+ if (strlen($_buffer["ciphertext"])) {
2293
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2294
+ $_block = substr($_text, $_i, '.$block_size.');
2295
+ if (strlen($_block) > strlen($_buffer["ciphertext"])) {
2296
+ $in = $_xor;
2297
+ '.$encrypt_block.'
2298
+ $self->_increment_str($_xor);
2299
+ $_buffer["ciphertext"].= $in;
2300
+ }
2301
+ $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
2302
+ $_plaintext.= $_block ^ $_key;
2303
+ }
2304
+ } else {
2305
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2306
+ $_block = substr($_text, $_i, '.$block_size.');
2307
+ $in = $_xor;
2308
+ '.$encrypt_block.'
2309
+ $self->_increment_str($_xor);
2310
+ $_key = $in;
2311
+ $_plaintext.= $_block ^ $_key;
2312
+ }
2313
+ }
2314
+ if ($self->continuousBuffer) {
2315
+ $self->decryptIV = $_xor;
2316
+ if ($_start = $_ciphertext_len % '.$block_size.') {
2317
+ $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
2318
+ }
2319
+ }
2320
+
2321
+ return $_plaintext;
2322
+ ';
2323
+ break;
2324
+ case CRYPT_MODE_CFB:
2325
+ $encrypt = $init_encrypt . '
2326
+ $_ciphertext = "";
2327
+ $_buffer = &$self->enbuffer;
2328
+
2329
+ if ($self->continuousBuffer) {
2330
+ $_iv = &$self->encryptIV;
2331
+ $_pos = &$_buffer["pos"];
2332
+ } else {
2333
+ $_iv = $self->encryptIV;
2334
+ $_pos = 0;
2335
+ }
2336
+ $_len = strlen($_text);
2337
+ $_i = 0;
2338
+ if ($_pos) {
2339
+ $_orig_pos = $_pos;
2340
+ $_max = '.$block_size.' - $_pos;
2341
+ if ($_len >= $_max) {
2342
+ $_i = $_max;
2343
+ $_len-= $_max;
2344
+ $_pos = 0;
2345
+ } else {
2346
+ $_i = $_len;
2347
+ $_pos+= $_len;
2348
+ $_len = 0;
2349
+ }
2350
+ $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
2351
+ $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
2352
+ }
2353
+ while ($_len >= '.$block_size.') {
2354
+ $in = $_iv;
2355
+ '.$encrypt_block.';
2356
+ $_iv = $in ^ substr($_text, $_i, '.$block_size.');
2357
+ $_ciphertext.= $_iv;
2358
+ $_len-= '.$block_size.';
2359
+ $_i+= '.$block_size.';
2360
+ }
2361
+ if ($_len) {
2362
+ $in = $_iv;
2363
+ '.$encrypt_block.'
2364
+ $_iv = $in;
2365
+ $_block = $_iv ^ substr($_text, $_i);
2366
+ $_iv = substr_replace($_iv, $_block, 0, $_len);
2367
+ $_ciphertext.= $_block;
2368
+ $_pos = $_len;
2369
+ }
2370
+ return $_ciphertext;
2371
+ ';
2372
+
2373
+ $decrypt = $init_encrypt . '
2374
+ $_plaintext = "";
2375
+ $_buffer = &$self->debuffer;
2376
+
2377
+ if ($self->continuousBuffer) {
2378
+ $_iv = &$self->decryptIV;
2379
+ $_pos = &$_buffer["pos"];
2380
+ } else {
2381
+ $_iv = $self->decryptIV;
2382
+ $_pos = 0;
2383
+ }
2384
+ $_len = strlen($_text);
2385
+ $_i = 0;
2386
+ if ($_pos) {
2387
+ $_orig_pos = $_pos;
2388
+ $_max = '.$block_size.' - $_pos;
2389
+ if ($_len >= $_max) {
2390
+ $_i = $_max;
2391
+ $_len-= $_max;
2392
+ $_pos = 0;
2393
+ } else {
2394
+ $_i = $_len;
2395
+ $_pos+= $_len;
2396
+ $_len = 0;
2397
+ }
2398
+ $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
2399
+ $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
2400
+ }
2401
+ while ($_len >= '.$block_size.') {
2402
+ $in = $_iv;
2403
+ '.$encrypt_block.'
2404
+ $_iv = $in;
2405
+ $cb = substr($_text, $_i, '.$block_size.');
2406
+ $_plaintext.= $_iv ^ $cb;
2407
+ $_iv = $cb;
2408
+ $_len-= '.$block_size.';
2409
+ $_i+= '.$block_size.';
2410
+ }
2411
+ if ($_len) {
2412
+ $in = $_iv;
2413
+ '.$encrypt_block.'
2414
+ $_iv = $in;
2415
+ $_plaintext.= $_iv ^ substr($_text, $_i);
2416
+ $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
2417
+ $_pos = $_len;
2418
+ }
2419
+
2420
+ return $_plaintext;
2421
+ ';
2422
+ break;
2423
+ case CRYPT_MODE_OFB:
2424
+ $encrypt = $init_encrypt . '
2425
+ $_ciphertext = "";
2426
+ $_plaintext_len = strlen($_text);
2427
+ $_xor = $self->encryptIV;
2428
+ $_buffer = &$self->enbuffer;
2429
+
2430
+ if (strlen($_buffer["xor"])) {
2431
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2432
+ $_block = substr($_text, $_i, '.$block_size.');
2433
+ if (strlen($_block) > strlen($_buffer["xor"])) {
2434
+ $in = $_xor;
2435
+ '.$encrypt_block.'
2436
+ $_xor = $in;
2437
+ $_buffer["xor"].= $_xor;
2438
+ }
2439
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2440
+ $_ciphertext.= $_block ^ $_key;
2441
+ }
2442
+ } else {
2443
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2444
+ $in = $_xor;
2445
+ '.$encrypt_block.'
2446
+ $_xor = $in;
2447
+ $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2448
+ }
2449
+ $_key = $_xor;
2450
+ }
2451
+ if ($self->continuousBuffer) {
2452
+ $self->encryptIV = $_xor;
2453
+ if ($_start = $_plaintext_len % '.$block_size.') {
2454
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2455
+ }
2456
+ }
2457
+ return $_ciphertext;
2458
+ ';
2459
+
2460
+ $decrypt = $init_encrypt . '
2461
+ $_plaintext = "";
2462
+ $_ciphertext_len = strlen($_text);
2463
+ $_xor = $self->decryptIV;
2464
+ $_buffer = &$self->debuffer;
2465
+
2466
+ if (strlen($_buffer["xor"])) {
2467
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2468
+ $_block = substr($_text, $_i, '.$block_size.');
2469
+ if (strlen($_block) > strlen($_buffer["xor"])) {
2470
+ $in = $_xor;
2471
+ '.$encrypt_block.'
2472
+ $_xor = $in;
2473
+ $_buffer["xor"].= $_xor;
2474
+ }
2475
+ $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
2476
+ $_plaintext.= $_block ^ $_key;
2477
+ }
2478
+ } else {
2479
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2480
+ $in = $_xor;
2481
+ '.$encrypt_block.'
2482
+ $_xor = $in;
2483
+ $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
2484
+ }
2485
+ $_key = $_xor;
2486
+ }
2487
+ if ($self->continuousBuffer) {
2488
+ $self->decryptIV = $_xor;
2489
+ if ($_start = $_ciphertext_len % '.$block_size.') {
2490
+ $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
2491
+ }
2492
+ }
2493
+ return $_plaintext;
2494
+ ';
2495
+ break;
2496
+ case CRYPT_MODE_STREAM:
2497
+ $encrypt = $init_encrypt . '
2498
+ $_ciphertext = "";
2499
+ '.$encrypt_block.'
2500
+ return $_ciphertext;
2501
+ ';
2502
+ $decrypt = $init_decrypt . '
2503
+ $_plaintext = "";
2504
+ '.$decrypt_block.'
2505
+ return $_plaintext;
2506
+ ';
2507
+ break;
2508
+ // case CRYPT_MODE_CBC:
2509
+ default:
2510
+ $encrypt = $init_encrypt . '
2511
+ $_ciphertext = "";
2512
+ $_plaintext_len = strlen($_text);
2513
+
2514
+ $in = $self->encryptIV;
2515
+
2516
+ for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
2517
+ $in = substr($_text, $_i, '.$block_size.') ^ $in;
2518
+ '.$encrypt_block.'
2519
+ $_ciphertext.= $in;
2520
+ }
2521
+
2522
+ if ($self->continuousBuffer) {
2523
+ $self->encryptIV = $in;
2524
+ }
2525
+
2526
+ return $_ciphertext;
2527
+ ';
2528
+
2529
+ $decrypt = $init_decrypt . '
2530
+ $_plaintext = "";
2531
+ $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
2532
+ $_ciphertext_len = strlen($_text);
2533
+
2534
+ $_iv = $self->decryptIV;
2535
+
2536
+ for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
2537
+ $in = $_block = substr($_text, $_i, '.$block_size.');
2538
+ '.$decrypt_block.'
2539
+ $_plaintext.= $in ^ $_iv;
2540
+ $_iv = $_block;
2541
+ }
2542
+
2543
+ if ($self->continuousBuffer) {
2544
+ $self->decryptIV = $_iv;
2545
+ }
2546
+
2547
+ return $self->_unpad($_plaintext);
2548
+ ';
2549
+ break;
2550
+ }
2551
+
2552
+ // Create the $inline function and return its name as string. Ready to run!
2553
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
2554
+ eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
2555
+ return $func;
2556
+ }
2557
+
2558
+ return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
2559
+ }
2560
+
2561
+ /**
2562
+ * Holds the lambda_functions table (classwide)
2563
+ *
2564
+ * Each name of the lambda function, created from
2565
+ * _setupInlineCrypt() && _createInlineCryptFunction()
2566
+ * is stored, classwide (!), here for reusing.
2567
+ *
2568
+ * The string-based index of $function is a classwide
2569
+ * unique value representing, at least, the $mode of
2570
+ * operation (or more... depends of the optimizing level)
2571
+ * for which $mode the lambda function was created.
2572
+ *
2573
+ * @access private
2574
+ * @return array &$functions
2575
+ */
2576
+ function &_getLambdaFunctions()
2577
+ {
2578
+ static $functions = array();
2579
+ return $functions;
2580
+ }
2581
+
2582
+ /**
2583
+ * Generates a digest from $bytes
2584
+ *
2585
+ * @see self::_setupInlineCrypt()
2586
+ * @access private
2587
+ * @param $bytes
2588
+ * @return string
2589
+ */
2590
+ function _hashInlineCryptFunction($bytes)
2591
+ {
2592
+ if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) {
2593
+ define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos())));
2594
+ }
2595
+
2596
+ $result = '';
2597
+ $hash = $bytes;
2598
+
2599
+ switch (true) {
2600
+ case CRYPT_BASE_WHIRLPOOL_AVAILABLE:
2601
+ foreach (str_split($bytes, 64) as $t) {
2602
+ $hash = hash('whirlpool', $hash, true);
2603
+ $result .= $t ^ $hash;
2604
+ }
2605
+ return $result . hash('whirlpool', $hash, true);
2606
+ default:
2607
+ $len = strlen($bytes);
2608
+ for ($i = 0; $i < $len; $i+=20) {
2609
+ $t = substr($bytes, $i, 20);
2610
+ $hash = pack('H*', sha1($hash));
2611
+ $result .= $t ^ $hash;
2612
+ }
2613
+ return $result . pack('H*', sha1($hash));
2614
+ }
2615
+ }
2616
+ }
phpseclib/Crypt/Blowfish.php CHANGED
@@ -1,651 +1,674 @@
1
- <?php
2
-
3
- /**
4
- * Pure-PHP implementation of Blowfish.
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://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
13
- *
14
- * Here's a short example of how to use this library:
15
- * <code>
16
- * <?php
17
- * include 'Crypt/Blowfish.php';
18
- *
19
- * $blowfish = new Crypt_Blowfish();
20
- *
21
- * $blowfish->setKey('12345678901234567890123456789012');
22
- *
23
- * $plaintext = str_repeat('a', 1024);
24
- *
25
- * echo $blowfish->decrypt($blowfish->encrypt($plaintext));
26
- * ?>
27
- * </code>
28
- *
29
- * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
- * of this software and associated documentation files (the "Software"), to deal
31
- * in the Software without restriction, including without limitation the rights
32
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
- * copies of the Software, and to permit persons to whom the Software is
34
- * furnished to do so, subject to the following conditions:
35
- *
36
- * The above copyright notice and this permission notice shall be included in
37
- * all copies or substantial portions of the Software.
38
- *
39
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
- * THE SOFTWARE.
46
- *
47
- * @category Crypt
48
- * @package Crypt_Blowfish
49
- * @author Jim Wigginton <terrafrost@php.net>
50
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
- * @copyright 2007 Jim Wigginton
52
- * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
- * @link http://phpseclib.sourceforge.net
54
- */
55
-
56
- /**
57
- * Include Crypt_Base
58
- *
59
- * Base cipher class
60
- */
61
- if (!class_exists('Crypt_Base')) {
62
- include_once 'Base.php';
63
- }
64
-
65
- /**#@+
66
- * @access public
67
- * @see Crypt_Blowfish::encrypt()
68
- * @see Crypt_Blowfish::decrypt()
69
- */
70
- /**
71
- * Encrypt / decrypt using the Counter mode.
72
- *
73
- * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
- *
75
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
- */
77
- define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
78
- /**
79
- * Encrypt / decrypt using the Electronic Code Book mode.
80
- *
81
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
- */
83
- define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
84
- /**
85
- * Encrypt / decrypt using the Code Book Chaining mode.
86
- *
87
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
- */
89
- define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
90
- /**
91
- * Encrypt / decrypt using the Cipher Feedback mode.
92
- *
93
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
- */
95
- define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
96
- /**
97
- * Encrypt / decrypt using the Cipher Feedback mode.
98
- *
99
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
- */
101
- define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
102
- /**#@-*/
103
-
104
- /**
105
- * Pure-PHP implementation of Blowfish.
106
- *
107
- * @package Crypt_Blowfish
108
- * @author Jim Wigginton <terrafrost@php.net>
109
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
- * @access public
111
- */
112
- class Crypt_Blowfish extends Crypt_Base
113
- {
114
- /**
115
- * Block Length of the cipher
116
- *
117
- * @see Crypt_Base::block_size
118
- * @var Integer
119
- * @access private
120
- */
121
- var $block_size = 8;
122
-
123
- /**
124
- * The default password key_size used by setPassword()
125
- *
126
- * @see Crypt_Base::password_key_size
127
- * @see Crypt_Base::setPassword()
128
- * @var Integer
129
- * @access private
130
- */
131
- var $password_key_size = 56;
132
-
133
- /**
134
- * The namespace used by the cipher for its constants.
135
- *
136
- * @see Crypt_Base::const_namespace
137
- * @var String
138
- * @access private
139
- */
140
- var $const_namespace = 'BLOWFISH';
141
-
142
- /**
143
- * The mcrypt specific name of the cipher
144
- *
145
- * @see Crypt_Base::cipher_name_mcrypt
146
- * @var String
147
- * @access private
148
- */
149
- var $cipher_name_mcrypt = 'blowfish';
150
-
151
- /**
152
- * Optimizing value while CFB-encrypting
153
- *
154
- * @see Crypt_Base::cfb_init_len
155
- * @var Integer
156
- * @access private
157
- */
158
- var $cfb_init_len = 500;
159
-
160
- /**
161
- * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
162
- *
163
- * S-Box 0
164
- *
165
- * @access private
166
- * @var array
167
- */
168
- var $sbox0 = array (
169
- 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
170
- 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
171
- 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
172
- 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
173
- 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
174
- 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
175
- 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
176
- 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
177
- 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
178
- 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
179
- 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
180
- 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
181
- 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
182
- 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
183
- 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
184
- 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
185
- 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
186
- 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
187
- 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
188
- 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
189
- 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
190
- 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
191
- 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
192
- 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
193
- 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
194
- 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
195
- 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
196
- 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
197
- 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
198
- 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
199
- 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
200
- 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
201
- );
202
-
203
- /**
204
- * S-Box 1
205
- *
206
- * @access private
207
- * @var array
208
- */
209
- var $sbox1 = array(
210
- 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
211
- 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
212
- 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
213
- 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
214
- 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
215
- 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
216
- 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
217
- 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
218
- 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
219
- 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
220
- 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
221
- 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
222
- 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
223
- 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
224
- 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
225
- 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
226
- 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
227
- 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
228
- 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
229
- 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
230
- 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
231
- 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
232
- 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
233
- 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
234
- 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
235
- 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
236
- 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
237
- 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
238
- 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
239
- 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
240
- 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
241
- 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
242
- );
243
-
244
- /**
245
- * S-Box 2
246
- *
247
- * @access private
248
- * @var array
249
- */
250
- var $sbox2 = array(
251
- 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
252
- 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
253
- 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
254
- 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
255
- 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
256
- 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
257
- 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
258
- 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
259
- 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
260
- 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
261
- 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
262
- 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
263
- 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
264
- 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
265
- 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
266
- 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
267
- 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
268
- 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
269
- 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
270
- 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
271
- 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
272
- 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
273
- 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
274
- 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
275
- 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
276
- 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
277
- 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
278
- 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
279
- 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
280
- 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
281
- 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
282
- 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
283
- );
284
-
285
- /**
286
- * S-Box 3
287
- *
288
- * @access private
289
- * @var array
290
- */
291
- var $sbox3 = array(
292
- 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
293
- 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
294
- 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
295
- 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
296
- 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
297
- 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
298
- 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
299
- 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
300
- 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
301
- 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
302
- 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
303
- 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
304
- 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
305
- 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
306
- 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
307
- 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
308
- 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
309
- 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
310
- 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
311
- 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
312
- 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
313
- 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
314
- 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
315
- 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
316
- 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
317
- 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
318
- 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
319
- 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
320
- 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
321
- 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
322
- 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
323
- 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
324
- );
325
-
326
- /**
327
- * P-Array consists of 18 32-bit subkeys
328
- *
329
- * @var array
330
- * @access private
331
- */
332
- var $parray = array(
333
- 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
334
- 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
335
- 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
336
- );
337
-
338
- /**
339
- * The BCTX-working Array
340
- *
341
- * Holds the expanded key [p] and the key-depended s-boxes [sb]
342
- *
343
- * @var array
344
- * @access private
345
- */
346
- var $bctx;
347
-
348
- /**
349
- * Holds the last used key
350
- *
351
- * @var Array
352
- * @access private
353
- */
354
- var $kl;
355
-
356
- /**
357
- * Sets the key.
358
- *
359
- * Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long.
360
- * If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible
361
- * with mcrypt because mcrypt act this way with blowfish key's < 32 bits.
362
- *
363
- * If the key is more than 448-bits, we trim the excess bits.
364
- *
365
- * If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes.
366
- *
367
- * @access public
368
- * @see Crypt_Base::setKey()
369
- * @param String $key
370
- */
371
- function setKey($key)
372
- {
373
- $keylength = strlen($key);
374
-
375
- if (!$keylength) {
376
- $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
377
- } elseif ($keylength > 56) {
378
- $key = substr($key, 0, 56);
379
- }
380
-
381
- parent::setKey($key);
382
- }
383
-
384
- /**
385
- * Test for engine validity
386
- *
387
- * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
388
- *
389
- * @see Crypt_Base::isValidEngine()
390
- * @param Integer $engine
391
- * @access public
392
- * @return Boolean
393
- */
394
- function isValidEngine($engine)
395
- {
396
- if ($engine == CRYPT_ENGINE_OPENSSL) {
397
- if (strlen($this->key) != 16) {
398
- return false;
399
- }
400
- $this->cipher_name_openssl_ecb = 'bf-ecb';
401
- $this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
402
- }
403
-
404
- return parent::isValidEngine($engine);
405
- }
406
-
407
- /**
408
- * Setup the key (expansion)
409
- *
410
- * @see Crypt_Base::_setupKey()
411
- * @access private
412
- */
413
- function _setupKey()
414
- {
415
- if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
416
- // already expanded
417
- return;
418
- }
419
- $this->kl = array('key' => $this->key);
420
-
421
- /* key-expanding p[] and S-Box building sb[] */
422
- $this->bctx = array(
423
- 'p' => array(),
424
- 'sb' => array(
425
- $this->sbox0,
426
- $this->sbox1,
427
- $this->sbox2,
428
- $this->sbox3
429
- )
430
- );
431
-
432
- // unpack binary string in unsigned chars
433
- $key = array_values(unpack('C*', $this->key));
434
- $keyl = count($key);
435
- for ($j = 0, $i = 0; $i < 18; ++$i) {
436
- // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
437
- for ($data = 0, $k = 0; $k < 4; ++$k) {
438
- $data = ($data << 8) | $key[$j];
439
- if (++$j >= $keyl) {
440
- $j = 0;
441
- }
442
- }
443
- $this->bctx['p'][] = $this->parray[$i] ^ $data;
444
- }
445
-
446
- // encrypt the zero-string, replace P1 and P2 with the encrypted data,
447
- // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
448
- $data = "\0\0\0\0\0\0\0\0";
449
- for ($i = 0; $i < 18; $i += 2) {
450
- list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
451
- $this->bctx['p'][$i ] = $l;
452
- $this->bctx['p'][$i + 1] = $r;
453
- }
454
- for ($i = 0; $i < 4; ++$i) {
455
- for ($j = 0; $j < 256; $j += 2) {
456
- list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
457
- $this->bctx['sb'][$i][$j ] = $l;
458
- $this->bctx['sb'][$i][$j + 1] = $r;
459
- }
460
- }
461
- }
462
-
463
- /**
464
- * Encrypts a block
465
- *
466
- * @access private
467
- * @param String $in
468
- * @return String
469
- */
470
- function _encryptBlock($in)
471
- {
472
- $p = $this->bctx["p"];
473
- // extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
474
- $sb_0 = $this->bctx["sb"][0];
475
- $sb_1 = $this->bctx["sb"][1];
476
- $sb_2 = $this->bctx["sb"][2];
477
- $sb_3 = $this->bctx["sb"][3];
478
-
479
- $in = unpack("N*", $in);
480
- $l = $in[1];
481
- $r = $in[2];
482
-
483
- for ($i = 0; $i < 16; $i+= 2) {
484
- $l^= $p[$i];
485
- $r^= ($sb_0[$l >> 24 & 0xff] +
486
- $sb_1[$l >> 16 & 0xff] ^
487
- $sb_2[$l >> 8 & 0xff]) +
488
- $sb_3[$l & 0xff];
489
-
490
- $r^= $p[$i + 1];
491
- $l^= ($sb_0[$r >> 24 & 0xff] +
492
- $sb_1[$r >> 16 & 0xff] ^
493
- $sb_2[$r >> 8 & 0xff]) +
494
- $sb_3[$r & 0xff];
495
- }
496
- return pack("N*", $r ^ $p[17], $l ^ $p[16]);
497
- }
498
-
499
- /**
500
- * Decrypts a block
501
- *
502
- * @access private
503
- * @param String $in
504
- * @return String
505
- */
506
- function _decryptBlock($in)
507
- {
508
- $p = $this->bctx["p"];
509
- $sb_0 = $this->bctx["sb"][0];
510
- $sb_1 = $this->bctx["sb"][1];
511
- $sb_2 = $this->bctx["sb"][2];
512
- $sb_3 = $this->bctx["sb"][3];
513
-
514
- $in = unpack("N*", $in);
515
- $l = $in[1];
516
- $r = $in[2];
517
-
518
- for ($i = 17; $i > 2; $i-= 2) {
519
- $l^= $p[$i];
520
- $r^= ($sb_0[$l >> 24 & 0xff] +
521
- $sb_1[$l >> 16 & 0xff] ^
522
- $sb_2[$l >> 8 & 0xff]) +
523
- $sb_3[$l & 0xff];
524
-
525
- $r^= $p[$i - 1];
526
- $l^= ($sb_0[$r >> 24 & 0xff] +
527
- $sb_1[$r >> 16 & 0xff] ^
528
- $sb_2[$r >> 8 & 0xff]) +
529
- $sb_3[$r & 0xff];
530
- }
531
- return pack("N*", $r ^ $p[0], $l ^ $p[1]);
532
- }
533
-
534
- /**
535
- * Setup the performance-optimized function for de/encrypt()
536
- *
537
- * @see Crypt_Base::_setupInlineCrypt()
538
- * @access private
539
- */
540
- function _setupInlineCrypt()
541
- {
542
- $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
543
-
544
- // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
545
- // (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
546
- // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
547
- $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
548
-
549
- // Generation of a unique hash for our generated code
550
- $code_hash = "Crypt_Blowfish, {$this->mode}";
551
- if ($gen_hi_opt_code) {
552
- $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
553
- }
554
-
555
- if (!isset($lambda_functions[$code_hash])) {
556
- switch (true) {
557
- case $gen_hi_opt_code:
558
- $p = $this->bctx['p'];
559
- $init_crypt = '
560
- static $sb_0, $sb_1, $sb_2, $sb_3;
561
- if (!$sb_0) {
562
- $sb_0 = $self->bctx["sb"][0];
563
- $sb_1 = $self->bctx["sb"][1];
564
- $sb_2 = $self->bctx["sb"][2];
565
- $sb_3 = $self->bctx["sb"][3];
566
- }
567
- ';
568
- break;
569
- default:
570
- $p = array();
571
- for ($i = 0; $i < 18; ++$i) {
572
- $p[] = '$p_' . $i;
573
- }
574
- $init_crypt = '
575
- list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
576
- list(' . implode(',', $p) . ') = $self->bctx["p"];
577
-
578
- ';
579
- }
580
-
581
- // Generating encrypt code:
582
- $encrypt_block = '
583
- $in = unpack("N*", $in);
584
- $l = $in[1];
585
- $r = $in[2];
586
- ';
587
- for ($i = 0; $i < 16; $i+= 2) {
588
- $encrypt_block.= '
589
- $l^= ' . $p[$i] . ';
590
- $r^= ($sb_0[$l >> 24 & 0xff] +
591
- $sb_1[$l >> 16 & 0xff] ^
592
- $sb_2[$l >> 8 & 0xff]) +
593
- $sb_3[$l & 0xff];
594
-
595
- $r^= ' . $p[$i + 1] . ';
596
- $l^= ($sb_0[$r >> 24 & 0xff] +
597
- $sb_1[$r >> 16 & 0xff] ^
598
- $sb_2[$r >> 8 & 0xff]) +
599
- $sb_3[$r & 0xff];
600
- ';
601
- }
602
- $encrypt_block.= '
603
- $in = pack("N*",
604
- $r ^ ' . $p[17] . ',
605
- $l ^ ' . $p[16] . '
606
- );
607
- ';
608
-
609
- // Generating decrypt code:
610
- $decrypt_block = '
611
- $in = unpack("N*", $in);
612
- $l = $in[1];
613
- $r = $in[2];
614
- ';
615
-
616
- for ($i = 17; $i > 2; $i-= 2) {
617
- $decrypt_block.= '
618
- $l^= ' . $p[$i] . ';
619
- $r^= ($sb_0[$l >> 24 & 0xff] +
620
- $sb_1[$l >> 16 & 0xff] ^
621
- $sb_2[$l >> 8 & 0xff]) +
622
- $sb_3[$l & 0xff];
623
-
624
- $r^= ' . $p[$i - 1] . ';
625
- $l^= ($sb_0[$r >> 24 & 0xff] +
626
- $sb_1[$r >> 16 & 0xff] ^
627
- $sb_2[$r >> 8 & 0xff]) +
628
- $sb_3[$r & 0xff];
629
- ';
630
- }
631
-
632
- $decrypt_block.= '
633
- $in = pack("N*",
634
- $r ^ ' . $p[0] . ',
635
- $l ^ ' . $p[1] . '
636
- );
637
- ';
638
-
639
- $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
640
- array(
641
- 'init_crypt' => $init_crypt,
642
- 'init_encrypt' => '',
643
- 'init_decrypt' => '',
644
- 'encrypt_block' => $encrypt_block,
645
- 'decrypt_block' => $decrypt_block
646
- )
647
- );
648
- }
649
- $this->inline_crypt = $lambda_functions[$code_hash];
650
- }
651
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Blowfish.
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://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
13
+ *
14
+ * Here's a short example of how to use this library:
15
+ * <code>
16
+ * <?php
17
+ * include 'Crypt/Blowfish.php';
18
+ *
19
+ * $blowfish = new Crypt_Blowfish();
20
+ *
21
+ * $blowfish->setKey('12345678901234567890123456789012');
22
+ *
23
+ * $plaintext = str_repeat('a', 1024);
24
+ *
25
+ * echo $blowfish->decrypt($blowfish->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_Blowfish
49
+ * @author Jim Wigginton <terrafrost@php.net>
50
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
+ * @copyright 2007 Jim Wigginton
52
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
+ * @link http://phpseclib.sourceforge.net
54
+ */
55
+
56
+ /**
57
+ * Include Crypt_Base
58
+ *
59
+ * Base cipher class
60
+ */
61
+ if (!class_exists('Crypt_Base')) {
62
+ include_once 'Base.php';
63
+ }
64
+
65
+ /**#@+
66
+ * @access public
67
+ * @see self::encrypt()
68
+ * @see self::decrypt()
69
+ */
70
+ /**
71
+ * Encrypt / decrypt using the Counter mode.
72
+ *
73
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
+ *
75
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
+ */
77
+ define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
78
+ /**
79
+ * Encrypt / decrypt using the Electronic Code Book mode.
80
+ *
81
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
+ */
83
+ define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
84
+ /**
85
+ * Encrypt / decrypt using the Code Book Chaining mode.
86
+ *
87
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
+ */
89
+ define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
90
+ /**
91
+ * Encrypt / decrypt using the Cipher Feedback mode.
92
+ *
93
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
+ */
95
+ define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
96
+ /**
97
+ * Encrypt / decrypt using the Cipher Feedback mode.
98
+ *
99
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
+ */
101
+ define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
102
+ /**#@-*/
103
+
104
+ /**
105
+ * Pure-PHP implementation of Blowfish.
106
+ *
107
+ * @package Crypt_Blowfish
108
+ * @author Jim Wigginton <terrafrost@php.net>
109
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
+ * @access public
111
+ */
112
+ class Crypt_Blowfish extends Crypt_Base
113
+ {
114
+ /**
115
+ * Block Length of the cipher
116
+ *
117
+ * @see Crypt_Base::block_size
118
+ * @var int
119
+ * @access private
120
+ */
121
+ var $block_size = 8;
122
+
123
+ /**
124
+ * The namespace used by the cipher for its constants.
125
+ *
126
+ * @see Crypt_Base::const_namespace
127
+ * @var string
128
+ * @access private
129
+ */
130
+ var $const_namespace = 'BLOWFISH';
131
+
132
+ /**
133
+ * The mcrypt specific name of the cipher
134
+ *
135
+ * @see Crypt_Base::cipher_name_mcrypt
136
+ * @var string
137
+ * @access private
138
+ */
139
+ var $cipher_name_mcrypt = 'blowfish';
140
+
141
+ /**
142
+ * Optimizing value while CFB-encrypting
143
+ *
144
+ * @see Crypt_Base::cfb_init_len
145
+ * @var int
146
+ * @access private
147
+ */
148
+ var $cfb_init_len = 500;
149
+
150
+ /**
151
+ * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
152
+ *
153
+ * S-Box 0
154
+ *
155
+ * @access private
156
+ * @var array
157
+ */
158
+ var $sbox0 = array(
159
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
160
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
161
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
162
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
163
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
164
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
165
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
166
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
167
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
168
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
169
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
170
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
171
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
172
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
173
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
174
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
175
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
176
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
177
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
178
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
179
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
180
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
181
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
182
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
183
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
184
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
185
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
186
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
187
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
188
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
189
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
190
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
191
+ );
192
+
193
+ /**
194
+ * S-Box 1
195
+ *
196
+ * @access private
197
+ * @var array
198
+ */
199
+ var $sbox1 = array(
200
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
201
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
202
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
203
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
204
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
205
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
206
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
207
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
208
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
209
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
210
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
211
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
212
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
213
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
214
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
215
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
216
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
217
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
218
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
219
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
220
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
221
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
222
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
223
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
224
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
225
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
226
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
227
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
228
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
229
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
230
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
231
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
232
+ );
233
+
234
+ /**
235
+ * S-Box 2
236
+ *
237
+ * @access private
238
+ * @var array
239
+ */
240
+ var $sbox2 = array(
241
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
242
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
243
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
244
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
245
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
246
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
247
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
248
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
249
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
250
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
251
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
252
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
253
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
254
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
255
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
256
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
257
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
258
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
259
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
260
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
261
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
262
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
263
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
264
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
265
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
266
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
267
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
268
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
269
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
270
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
271
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
272
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
273
+ );
274
+
275
+ /**
276
+ * S-Box 3
277
+ *
278
+ * @access private
279
+ * @var array
280
+ */
281
+ var $sbox3 = array(
282
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
283
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
284
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
285
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
286
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
287
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
288
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
289
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
290
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
291
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
292
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
293
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
294
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
295
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
296
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
297
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
298
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
299
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
300
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
301
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
302
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
303
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
304
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
305
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
306
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
307
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
308
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
309
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
310
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
311
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
312
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
313
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
314
+ );
315
+
316
+ /**
317
+ * P-Array consists of 18 32-bit subkeys
318
+ *
319
+ * @var array
320
+ * @access private
321
+ */
322
+ var $parray = array(
323
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
324
+ 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
325
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
326
+ );
327
+
328
+ /**
329
+ * The BCTX-working Array
330
+ *
331
+ * Holds the expanded key [p] and the key-depended s-boxes [sb]
332
+ *
333
+ * @var array
334
+ * @access private
335
+ */
336
+ var $bctx;
337
+
338
+ /**
339
+ * Holds the last used key
340
+ *
341
+ * @var array
342
+ * @access private
343
+ */
344
+ var $kl;
345
+
346
+ /**
347
+ * The Key Length (in bytes)
348
+ *
349
+ * @see Crypt_Base::setKeyLength()
350
+ * @var int
351
+ * @access private
352
+ * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
353
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
354
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
355
+ * of that, we'll just precompute it once.
356
+ */
357
+ var $key_length = 16;
358
+
359
+ /**
360
+ * Sets the key length.
361
+ *
362
+ * Key lengths can be between 32 and 448 bits.
363
+ *
364
+ * @access public
365
+ * @param int $length
366
+ */
367
+ function setKeyLength($length)
368
+ {
369
+ if ($length < 32) {
370
+ $this->key_length = 7;
371
+ } elseif ($length > 448) {
372
+ $this->key_length = 56;
373
+ } else {
374
+ $this->key_length = $length >> 3;
375
+ }
376
+
377
+ parent::setKeyLength($length);
378
+ }
379
+
380
+ /**
381
+ * Test for engine validity
382
+ *
383
+ * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
384
+ *
385
+ * @see Crypt_Base::isValidEngine()
386
+ * @param int $engine
387
+ * @access public
388
+ * @return bool
389
+ */
390
+ function isValidEngine($engine)
391
+ {
392
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
393
+ if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
394
+ return false;
395
+ }
396
+ if ($this->key_length < 16) {
397
+ return false;
398
+ }
399
+ $this->cipher_name_openssl_ecb = 'bf-ecb';
400
+ $this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
401
+ }
402
+
403
+ return parent::isValidEngine($engine);
404
+ }
405
+
406
+ /**
407
+ * Setup the key (expansion)
408
+ *
409
+ * @see Crypt_Base::_setupKey()
410
+ * @access private
411
+ */
412
+ function _setupKey()
413
+ {
414
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
415
+ // already expanded
416
+ return;
417
+ }
418
+ $this->kl = array('key' => $this->key);
419
+
420
+ /* key-expanding p[] and S-Box building sb[] */
421
+ $this->bctx = array(
422
+ 'p' => array(),
423
+ 'sb' => array(
424
+ $this->sbox0,
425
+ $this->sbox1,
426
+ $this->sbox2,
427
+ $this->sbox3
428
+ )
429
+ );
430
+
431
+ // unpack binary string in unsigned chars
432
+ $key = array_values(unpack('C*', $this->key));
433
+ $keyl = count($key);
434
+ for ($j = 0, $i = 0; $i < 18; ++$i) {
435
+ // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
436
+ for ($data = 0, $k = 0; $k < 4; ++$k) {
437
+ $data = ($data << 8) | $key[$j];
438
+ if (++$j >= $keyl) {
439
+ $j = 0;
440
+ }
441
+ }
442
+ $this->bctx['p'][] = $this->parray[$i] ^ $data;
443
+ }
444
+
445
+ // encrypt the zero-string, replace P1 and P2 with the encrypted data,
446
+ // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
447
+ $data = "\0\0\0\0\0\0\0\0";
448
+ for ($i = 0; $i < 18; $i += 2) {
449
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
450
+ $this->bctx['p'][$i ] = $l;
451
+ $this->bctx['p'][$i + 1] = $r;
452
+ }
453
+ for ($i = 0; $i < 4; ++$i) {
454
+ for ($j = 0; $j < 256; $j += 2) {
455
+ list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
456
+ $this->bctx['sb'][$i][$j ] = $l;
457
+ $this->bctx['sb'][$i][$j + 1] = $r;
458
+ }
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Encrypts a block
464
+ *
465
+ * @access private
466
+ * @param string $in
467
+ * @return string
468
+ */
469
+ function _encryptBlock($in)
470
+ {
471
+ $p = $this->bctx["p"];
472
+ // extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
473
+ $sb_0 = $this->bctx["sb"][0];
474
+ $sb_1 = $this->bctx["sb"][1];
475
+ $sb_2 = $this->bctx["sb"][2];
476
+ $sb_3 = $this->bctx["sb"][3];
477
+
478
+ $in = unpack("N*", $in);
479
+ $l = $in[1];
480
+ $r = $in[2];
481
+
482
+ for ($i = 0; $i < 16; $i+= 2) {
483
+ $l^= $p[$i];
484
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
485
+ $sb_2[$l >> 8 & 0xff]) +
486
+ $sb_3[$l & 0xff]);
487
+
488
+ $r^= $p[$i + 1];
489
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
490
+ $sb_2[$r >> 8 & 0xff]) +
491
+ $sb_3[$r & 0xff]);
492
+ }
493
+ return pack("N*", $r ^ $p[17], $l ^ $p[16]);
494
+ }
495
+
496
+ /**
497
+ * Decrypts a block
498
+ *
499
+ * @access private
500
+ * @param string $in
501
+ * @return string
502
+ */
503
+ function _decryptBlock($in)
504
+ {
505
+ $p = $this->bctx["p"];
506
+ $sb_0 = $this->bctx["sb"][0];
507
+ $sb_1 = $this->bctx["sb"][1];
508
+ $sb_2 = $this->bctx["sb"][2];
509
+ $sb_3 = $this->bctx["sb"][3];
510
+
511
+ $in = unpack("N*", $in);
512
+ $l = $in[1];
513
+ $r = $in[2];
514
+
515
+ for ($i = 17; $i > 2; $i-= 2) {
516
+ $l^= $p[$i];
517
+ $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
518
+ $sb_2[$l >> 8 & 0xff]) +
519
+ $sb_3[$l & 0xff]);
520
+
521
+ $r^= $p[$i - 1];
522
+ $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
523
+ $sb_2[$r >> 8 & 0xff]) +
524
+ $sb_3[$r & 0xff]);
525
+ }
526
+ return pack("N*", $r ^ $p[0], $l ^ $p[1]);
527
+ }
528
+
529
+ /**
530
+ * Setup the performance-optimized function for de/encrypt()
531
+ *
532
+ * @see Crypt_Base::_setupInlineCrypt()
533
+ * @access private
534
+ */
535
+ function _setupInlineCrypt()
536
+ {
537
+ $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
538
+
539
+ // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
540
+ // (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
541
+ // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
542
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
543
+
544
+ // Generation of a unique hash for our generated code
545
+ $code_hash = "Crypt_Blowfish, {$this->mode}";
546
+ if ($gen_hi_opt_code) {
547
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
548
+ }
549
+
550
+ // on 32-bit linux systems with PHP < 5.3 float to integer conversion is bad
551
+ switch (true) {
552
+ case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
553
+ case version_compare(PHP_VERSION, '5.3.0') >= 0:
554
+ case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
555
+ $safeint = '%s';
556
+ break;
557
+ default:
558
+ $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
559
+ $safeint.= '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
560
+ }
561
+
562
+ if (!isset($lambda_functions[$code_hash])) {
563
+ switch (true) {
564
+ case $gen_hi_opt_code:
565
+ $p = $this->bctx['p'];
566
+ $init_crypt = '
567
+ static $sb_0, $sb_1, $sb_2, $sb_3;
568
+ if (!$sb_0) {
569
+ $sb_0 = $self->bctx["sb"][0];
570
+ $sb_1 = $self->bctx["sb"][1];
571
+ $sb_2 = $self->bctx["sb"][2];
572
+ $sb_3 = $self->bctx["sb"][3];
573
+ }
574
+ ';
575
+ break;
576
+ default:
577
+ $p = array();
578
+ for ($i = 0; $i < 18; ++$i) {
579
+ $p[] = '$p_' . $i;
580
+ }
581
+ $init_crypt = '
582
+ list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
583
+ list(' . implode(',', $p) . ') = $self->bctx["p"];
584
+
585
+ ';
586
+ }
587
+
588
+ // Generating encrypt code:
589
+ $encrypt_block = '
590
+ $in = unpack("N*", $in);
591
+ $l = $in[1];
592
+ $r = $in[2];
593
+ ';
594
+ for ($i = 0; $i < 16; $i+= 2) {
595
+ $encrypt_block.= '
596
+ $l^= ' . $p[$i] . ';
597
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
598
+ $sb_2[$l >> 8 & 0xff]) +
599
+ $sb_3[$l & 0xff]') . ';
600
+
601
+ $r^= ' . $p[$i + 1] . ';
602
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
603
+ $sb_2[$r >> 8 & 0xff]) +
604
+ $sb_3[$r & 0xff]') . ';
605
+ ';
606
+ }
607
+ $encrypt_block.= '
608
+ $in = pack("N*",
609
+ $r ^ ' . $p[17] . ',
610
+ $l ^ ' . $p[16] . '
611
+ );
612
+ ';
613
+
614
+ // Generating decrypt code:
615
+ $decrypt_block = '
616
+ $in = unpack("N*", $in);
617
+ $l = $in[1];
618
+ $r = $in[2];
619
+ ';
620
+
621
+ for ($i = 17; $i > 2; $i-= 2) {
622
+ $decrypt_block.= '
623
+ $l^= ' . $p[$i] . ';
624
+ $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
625
+ $sb_2[$l >> 8 & 0xff]) +
626
+ $sb_3[$l & 0xff]') . ';
627
+
628
+ $r^= ' . $p[$i - 1] . ';
629
+ $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
630
+ $sb_2[$r >> 8 & 0xff]) +
631
+ $sb_3[$r & 0xff]') . ';
632
+ ';
633
+ }
634
+
635
+ $decrypt_block.= '
636
+ $in = pack("N*",
637
+ $r ^ ' . $p[0] . ',
638
+ $l ^ ' . $p[1] . '
639
+ );
640
+ ';
641
+
642
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
643
+ array(
644
+ 'init_crypt' => $init_crypt,
645
+ 'init_encrypt' => '',
646
+ 'init_decrypt' => '',
647
+ 'encrypt_block' => $encrypt_block,
648
+ 'decrypt_block' => $decrypt_block
649
+ )
650
+ );
651
+ }
652
+ $this->inline_crypt = $lambda_functions[$code_hash];
653
+ }
654
+
655
+ /**
656
+ * Convert float to int
657
+ *
658
+ * On 32-bit Linux installs running PHP < 5.3 converting floats to ints doesn't always work
659
+ *
660
+ * @access private
661
+ * @param string $x
662
+ * @return int
663
+ */
664
+ function safe_intval($x)
665
+ {
666
+ // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
667
+ // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
668
+ if (is_int($x) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
669
+ return $x;
670
+ }
671
+ return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
672
+ ((fmod(floor($x / 0x80000000), 2) & 1) << 31);
673
+ }
674
+ }
phpseclib/Crypt/DES.php CHANGED
@@ -69,8 +69,8 @@ if (!class_exists('Crypt_Base')) {
69
 
70
  /**#@+
71
  * @access private
72
- * @see Crypt_DES::_setupKey()
73
- * @see Crypt_DES::_processBlock()
74
  */
75
  /**
76
  * Contains $keys[CRYPT_DES_ENCRYPT]
@@ -84,8 +84,8 @@ define('CRYPT_DES_DECRYPT', 1);
84
 
85
  /**#@+
86
  * @access public
87
- * @see Crypt_DES::encrypt()
88
- * @see Crypt_DES::decrypt()
89
  */
90
  /**
91
  * Encrypt / decrypt using the Counter mode.
@@ -134,36 +134,25 @@ class Crypt_DES extends Crypt_Base
134
  * Block Length of the cipher
135
  *
136
  * @see Crypt_Base::block_size
137
- * @var Integer
138
  * @access private
139
  */
140
  var $block_size = 8;
141
 
142
  /**
143
- * The Key
144
  *
145
- * @see Crypt_Base::key
146
- * @see setKey()
147
- * @var String
148
  * @access private
149
  */
150
- var $key = "\0\0\0\0\0\0\0\0";
151
-
152
- /**
153
- * The default password key_size used by setPassword()
154
- *
155
- * @see Crypt_Base::password_key_size
156
- * @see Crypt_Base::setPassword()
157
- * @var Integer
158
- * @access private
159
- */
160
- var $password_key_size = 8;
161
 
162
  /**
163
  * The namespace used by the cipher for its constants.
164
  *
165
  * @see Crypt_Base::const_namespace
166
- * @var String
167
  * @access private
168
  */
169
  var $const_namespace = 'DES';
@@ -172,7 +161,7 @@ class Crypt_DES extends Crypt_Base
172
  * The mcrypt specific name of the cipher
173
  *
174
  * @see Crypt_Base::cipher_name_mcrypt
175
- * @var String
176
  * @access private
177
  */
178
  var $cipher_name_mcrypt = 'des';
@@ -181,7 +170,7 @@ class Crypt_DES extends Crypt_Base
181
  * The OpenSSL names of the cipher / modes
182
  *
183
  * @see Crypt_Base::openssl_mode_names
184
- * @var Array
185
  * @access private
186
  */
187
  var $openssl_mode_names = array(
@@ -196,7 +185,7 @@ class Crypt_DES extends Crypt_Base
196
  * Optimizing value while CFB-encrypting
197
  *
198
  * @see Crypt_Base::cfb_init_len
199
- * @var Integer
200
  * @access private
201
  */
202
  var $cfb_init_len = 500;
@@ -206,9 +195,9 @@ class Crypt_DES extends Crypt_Base
206
  *
207
  * Used only if $engine == CRYPT_DES_MODE_INTERNAL
208
  *
209
- * @see Crypt_DES::_setupKey()
210
- * @see Crypt_DES::_processBlock()
211
- * @var Integer
212
  * @access private
213
  */
214
  var $des_rounds = 1;
@@ -216,17 +205,17 @@ class Crypt_DES extends Crypt_Base
216
  /**
217
  * max possible size of $key
218
  *
219
- * @see Crypt_DES::setKey()
220
- * @var String
221
  * @access private
222
  */
223
- var $key_size_max = 8;
224
 
225
  /**
226
  * The Key Schedule
227
  *
228
- * @see Crypt_DES::_setupKey()
229
- * @var Array
230
  * @access private
231
  */
232
  var $keys;
@@ -238,9 +227,9 @@ class Crypt_DES extends Crypt_Base
238
  * with each byte containing all bits in the same state as the
239
  * corresponding bit in the index value.
240
  *
241
- * @see Crypt_DES::_processBlock()
242
- * @see Crypt_DES::_setupKey()
243
- * @var Array
244
  * @access private
245
  */
246
  var $shuffle = array(
@@ -379,7 +368,7 @@ class Crypt_DES extends Crypt_Base
379
  *
380
  * Indexing this table with each source byte performs the initial bit permutation.
381
  *
382
- * @var Array
383
  * @access private
384
  */
385
  var $ipmap = array(
@@ -421,7 +410,7 @@ class Crypt_DES extends Crypt_Base
421
  * Inverse IP mapping helper table.
422
  * Indexing this table with a byte value reverses the bit order.
423
  *
424
- * @var Array
425
  * @access private
426
  */
427
  var $invipmap = array(
@@ -465,7 +454,7 @@ class Crypt_DES extends Crypt_Base
465
  * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
466
  * P table: concatenation can then be replaced by exclusive ORs.
467
  *
468
- * @var Array
469
  * @access private
470
  */
471
  var $sbox1 = array(
@@ -490,7 +479,7 @@ class Crypt_DES extends Crypt_Base
490
  /**
491
  * Pre-permuted S-box2
492
  *
493
- * @var Array
494
  * @access private
495
  */
496
  var $sbox2 = array(
@@ -515,7 +504,7 @@ class Crypt_DES extends Crypt_Base
515
  /**
516
  * Pre-permuted S-box3
517
  *
518
- * @var Array
519
  * @access private
520
  */
521
  var $sbox3 = array(
@@ -540,7 +529,7 @@ class Crypt_DES extends Crypt_Base
540
  /**
541
  * Pre-permuted S-box4
542
  *
543
- * @var Array
544
  * @access private
545
  */
546
  var $sbox4 = array(
@@ -565,7 +554,7 @@ class Crypt_DES extends Crypt_Base
565
  /**
566
  * Pre-permuted S-box5
567
  *
568
- * @var Array
569
  * @access private
570
  */
571
  var $sbox5 = array(
@@ -590,7 +579,7 @@ class Crypt_DES extends Crypt_Base
590
  /**
591
  * Pre-permuted S-box6
592
  *
593
- * @var Array
594
  * @access private
595
  */
596
  var $sbox6 = array(
@@ -615,7 +604,7 @@ class Crypt_DES extends Crypt_Base
615
  /**
616
  * Pre-permuted S-box7
617
  *
618
- * @var Array
619
  * @access private
620
  */
621
  var $sbox7 = array(
@@ -640,7 +629,7 @@ class Crypt_DES extends Crypt_Base
640
  /**
641
  * Pre-permuted S-box8
642
  *
643
- * @var Array
644
  * @access private
645
  */
646
  var $sbox8 = array(
@@ -668,13 +657,13 @@ class Crypt_DES extends Crypt_Base
668
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
669
  *
670
  * @see Crypt_Base::isValidEngine()
671
- * @param Integer $engine
672
  * @access public
673
- * @return Boolean
674
  */
675
  function isValidEngine($engine)
676
  {
677
- if ($this->key_size_max == 8) {
678
  if ($engine == CRYPT_ENGINE_OPENSSL) {
679
  $this->cipher_name_openssl_ecb = 'des-ecb';
680
  $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
@@ -697,14 +686,14 @@ class Crypt_DES extends Crypt_Base
697
  *
698
  * @see Crypt_Base::setKey()
699
  * @access public
700
- * @param String $key
701
  */
702
  function setKey($key)
703
  {
704
  // We check/cut here only up to max length of the key.
705
  // Key padding to the proper length will be done in _setupKey()
706
- if (strlen($key) > $this->key_size_max) {
707
- $key = substr($key, 0, $this->key_size_max);
708
  }
709
 
710
  // Sets the key
@@ -716,10 +705,10 @@ class Crypt_DES extends Crypt_Base
716
  *
717
  * @see Crypt_Base::_encryptBlock()
718
  * @see Crypt_Base::encrypt()
719
- * @see Crypt_DES::encrypt()
720
  * @access private
721
- * @param String $in
722
- * @return String
723
  */
724
  function _encryptBlock($in)
725
  {
@@ -731,10 +720,10 @@ class Crypt_DES extends Crypt_Base
731
  *
732
  * @see Crypt_Base::_decryptBlock()
733
  * @see Crypt_Base::decrypt()
734
- * @see Crypt_DES::decrypt()
735
  * @access private
736
- * @param String $in
737
- * @return String
738
  */
739
  function _decryptBlock($in)
740
  {
@@ -748,12 +737,12 @@ class Crypt_DES extends Crypt_Base
748
  * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
749
  * idea of what this function does.
750
  *
751
- * @see Crypt_DES::_encryptBlock()
752
- * @see Crypt_DES::_decryptBlock()
753
  * @access private
754
- * @param String $block
755
- * @param Integer $mode
756
- * @return String
757
  */
758
  function _processBlock($block, $mode)
759
  {
@@ -1386,7 +1375,7 @@ class Crypt_DES extends Crypt_Base
1386
  // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
1387
  $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
1388
 
1389
- // Generation of a uniqe hash for our generated code
1390
  $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
1391
  if ($gen_hi_opt_code) {
1392
  // For hi-optimized code, we create for each combination of
@@ -1449,7 +1438,6 @@ class Crypt_DES extends Crypt_Base
1449
  // Creating code for en- and decryption.
1450
  $crypt_block = array();
1451
  foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
1452
-
1453
  /* Do the initial IP permutation. */
1454
  $crypt_block[$c] = '
1455
  $in = unpack("N*", $in);
69
 
70
  /**#@+
71
  * @access private
72
+ * @see self::_setupKey()
73
+ * @see self::_processBlock()
74
  */
75
  /**
76
  * Contains $keys[CRYPT_DES_ENCRYPT]
84
 
85
  /**#@+
86
  * @access public
87
+ * @see self::encrypt()
88
+ * @see self::decrypt()
89
  */
90
  /**
91
  * Encrypt / decrypt using the Counter mode.
134
  * Block Length of the cipher
135
  *
136
  * @see Crypt_Base::block_size
137
+ * @var int
138
  * @access private
139
  */
140
  var $block_size = 8;
141
 
142
  /**
143
+ * Key Length (in bytes)
144
  *
145
+ * @see Crypt_Base::setKeyLength()
146
+ * @var int
 
147
  * @access private
148
  */
149
+ var $key_length = 8;
 
 
 
 
 
 
 
 
 
 
150
 
151
  /**
152
  * The namespace used by the cipher for its constants.
153
  *
154
  * @see Crypt_Base::const_namespace
155
+ * @var string
156
  * @access private
157
  */
158
  var $const_namespace = 'DES';
161
  * The mcrypt specific name of the cipher
162
  *
163
  * @see Crypt_Base::cipher_name_mcrypt
164
+ * @var string
165
  * @access private
166
  */
167
  var $cipher_name_mcrypt = 'des';
170
  * The OpenSSL names of the cipher / modes
171
  *
172
  * @see Crypt_Base::openssl_mode_names
173
+ * @var array
174
  * @access private
175
  */
176
  var $openssl_mode_names = array(
185
  * Optimizing value while CFB-encrypting
186
  *
187
  * @see Crypt_Base::cfb_init_len
188
+ * @var int
189
  * @access private
190
  */
191
  var $cfb_init_len = 500;
195
  *
196
  * Used only if $engine == CRYPT_DES_MODE_INTERNAL
197
  *
198
+ * @see self::_setupKey()
199
+ * @see self::_processBlock()
200
+ * @var int
201
  * @access private
202
  */
203
  var $des_rounds = 1;
205
  /**
206
  * max possible size of $key
207
  *
208
+ * @see self::setKey()
209
+ * @var string
210
  * @access private
211
  */
212
+ var $key_length_max = 8;
213
 
214
  /**
215
  * The Key Schedule
216
  *
217
+ * @see self::_setupKey()
218
+ * @var array
219
  * @access private
220
  */
221
  var $keys;
227
  * with each byte containing all bits in the same state as the
228
  * corresponding bit in the index value.
229
  *
230
+ * @see self::_processBlock()
231
+ * @see self::_setupKey()
232
+ * @var array
233
  * @access private
234
  */
235
  var $shuffle = array(
368
  *
369
  * Indexing this table with each source byte performs the initial bit permutation.
370
  *
371
+ * @var array
372
  * @access private
373
  */
374
  var $ipmap = array(
410
  * Inverse IP mapping helper table.
411
  * Indexing this table with a byte value reverses the bit order.
412
  *
413
+ * @var array
414
  * @access private
415
  */
416
  var $invipmap = array(
454
  * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
455
  * P table: concatenation can then be replaced by exclusive ORs.
456
  *
457
+ * @var array
458
  * @access private
459
  */
460
  var $sbox1 = array(
479
  /**
480
  * Pre-permuted S-box2
481
  *
482
+ * @var array
483
  * @access private
484
  */
485
  var $sbox2 = array(
504
  /**
505
  * Pre-permuted S-box3
506
  *
507
+ * @var array
508
  * @access private
509
  */
510
  var $sbox3 = array(
529
  /**
530
  * Pre-permuted S-box4
531
  *
532
+ * @var array
533
  * @access private
534
  */
535
  var $sbox4 = array(
554
  /**
555
  * Pre-permuted S-box5
556
  *
557
+ * @var array
558
  * @access private
559
  */
560
  var $sbox5 = array(
579
  /**
580
  * Pre-permuted S-box6
581
  *
582
+ * @var array
583
  * @access private
584
  */
585
  var $sbox6 = array(
604
  /**
605
  * Pre-permuted S-box7
606
  *
607
+ * @var array
608
  * @access private
609
  */
610
  var $sbox7 = array(
629
  /**
630
  * Pre-permuted S-box8
631
  *
632
+ * @var array
633
  * @access private
634
  */
635
  var $sbox8 = array(
657
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
658
  *
659
  * @see Crypt_Base::isValidEngine()
660
+ * @param int $engine
661
  * @access public
662
+ * @return bool
663
  */
664
  function isValidEngine($engine)
665
  {
666
+ if ($this->key_length_max == 8) {
667
  if ($engine == CRYPT_ENGINE_OPENSSL) {
668
  $this->cipher_name_openssl_ecb = 'des-ecb';
669
  $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
686
  *
687
  * @see Crypt_Base::setKey()
688
  * @access public
689
+ * @param string $key
690
  */
691
  function setKey($key)
692
  {
693
  // We check/cut here only up to max length of the key.
694
  // Key padding to the proper length will be done in _setupKey()
695
+ if (strlen($key) > $this->key_length_max) {
696
+ $key = substr($key, 0, $this->key_length_max);
697
  }
698
 
699
  // Sets the key
705
  *
706
  * @see Crypt_Base::_encryptBlock()
707
  * @see Crypt_Base::encrypt()
708
+ * @see self::encrypt()
709
  * @access private
710
+ * @param string $in
711
+ * @return string
712
  */
713
  function _encryptBlock($in)
714
  {
720
  *
721
  * @see Crypt_Base::_decryptBlock()
722
  * @see Crypt_Base::decrypt()
723
+ * @see self::decrypt()
724
  * @access private
725
+ * @param string $in
726
+ * @return string
727
  */
728
  function _decryptBlock($in)
729
  {
737
  * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
738
  * idea of what this function does.
739
  *
740
+ * @see self::_encryptBlock()
741
+ * @see self::_decryptBlock()
742
  * @access private
743
+ * @param string $block
744
+ * @param int $mode
745
+ * @return string
746
  */
747
  function _processBlock($block, $mode)
748
  {
1375
  // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
1376
  $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
1377
 
1378
+ // Generation of a unique hash for our generated code
1379
  $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
1380
  if ($gen_hi_opt_code) {
1381
  // For hi-optimized code, we create for each combination of
1438
  // Creating code for en- and decryption.
1439
  $crypt_block = array();
1440
  foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
 
1441
  /* Do the initial IP permutation. */
1442
  $crypt_block[$c] = '
1443
  $in = unpack("N*", $in);
phpseclib/Crypt/Hash.php CHANGED
@@ -7,7 +7,7 @@
7
  *
8
  * md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
9
  *
10
- * If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
11
  * the hash. If no valid algorithm is provided, sha1 will be used.
12
  *
13
  * PHP versions 4 and 5
@@ -56,7 +56,7 @@
56
 
57
  /**#@+
58
  * @access private
59
- * @see Crypt_Hash::Crypt_Hash()
60
  */
61
  /**
62
  * Toggles the internal implementation
@@ -84,8 +84,8 @@ class Crypt_Hash
84
  /**
85
  * Hash Parameter
86
  *
87
- * @see Crypt_Hash::setHash()
88
- * @var Integer
89
  * @access private
90
  */
91
  var $hashParam;
@@ -93,8 +93,8 @@ class Crypt_Hash
93
  /**
94
  * Byte-length of compression blocks / key (Internal HMAC)
95
  *
96
- * @see Crypt_Hash::setAlgorithm()
97
- * @var Integer
98
  * @access private
99
  */
100
  var $b;
@@ -102,8 +102,8 @@ class Crypt_Hash
102
  /**
103
  * Byte-length of hash output (Internal HMAC)
104
  *
105
- * @see Crypt_Hash::setHash()
106
- * @var Integer
107
  * @access private
108
  */
109
  var $l = false;
@@ -111,8 +111,8 @@ class Crypt_Hash
111
  /**
112
  * Hash Algorithm
113
  *
114
- * @see Crypt_Hash::setHash()
115
- * @var String
116
  * @access private
117
  */
118
  var $hash;
@@ -120,8 +120,8 @@ class Crypt_Hash
120
  /**
121
  * Key
122
  *
123
- * @see Crypt_Hash::setKey()
124
- * @var String
125
  * @access private
126
  */
127
  var $key = false;
@@ -129,8 +129,8 @@ class Crypt_Hash
129
  /**
130
  * Outer XOR (Internal HMAC)
131
  *
132
- * @see Crypt_Hash::setKey()
133
- * @var String
134
  * @access private
135
  */
136
  var $opad;
@@ -138,8 +138,8 @@ class Crypt_Hash
138
  /**
139
  * Inner XOR (Internal HMAC)
140
  *
141
- * @see Crypt_Hash::setKey()
142
- * @var String
143
  * @access private
144
  */
145
  var $ipad;
@@ -147,13 +147,13 @@ class Crypt_Hash
147
  /**
148
  * Default Constructor.
149
  *
150
- * @param optional String $hash
151
  * @return Crypt_Hash
152
  * @access public
153
  */
154
- function Crypt_Hash($hash = 'sha1')
155
  {
156
- if ( !defined('CRYPT_HASH_MODE') ) {
157
  switch (true) {
158
  case extension_loaded('hash'):
159
  define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
@@ -169,13 +169,25 @@ class Crypt_Hash
169
  $this->setHash($hash);
170
  }
171
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  /**
173
  * Sets the key for HMACs
174
  *
175
  * Keys can be of any length.
176
  *
177
  * @access public
178
- * @param optional String $key
179
  */
180
  function setKey($key = false)
181
  {
@@ -188,7 +200,7 @@ class Crypt_Hash
188
  * As set by the constructor or by the setHash() method.
189
  *
190
  * @access public
191
- * @return String
192
  */
193
  function getHash()
194
  {
@@ -199,7 +211,7 @@ class Crypt_Hash
199
  * Sets the hash function.
200
  *
201
  * @access public
202
- * @param String $hash
203
  */
204
  function setHash($hash)
205
  {
@@ -242,7 +254,7 @@ class Crypt_Hash
242
  $mode = CRYPT_HASH_MODE;
243
  }
244
 
245
- switch ( $mode ) {
246
  case CRYPT_HASH_MODE_MHASH:
247
  switch ($hash) {
248
  case 'md5':
@@ -276,26 +288,26 @@ class Crypt_Hash
276
 
277
  switch ($hash) {
278
  case 'md2':
279
- $this->b = 16;
280
- $this->hash = array($this, '_md2');
281
- break;
282
  case 'md5':
283
- $this->b = 64;
284
- $this->hash = array($this, '_md5');
285
- break;
286
  case 'sha256':
287
- $this->b = 64;
288
- $this->hash = array($this, '_sha256');
289
- break;
290
  case 'sha384':
291
  case 'sha512':
292
- $this->b = 128;
293
- $this->hash = array($this, '_sha512');
294
- break;
295
  case 'sha1':
296
  default:
297
- $this->b = 64;
298
- $this->hash = array($this, '_sha1');
299
  }
300
 
301
  $this->ipad = str_repeat(chr(0x36), $this->b);
@@ -306,15 +318,15 @@ class Crypt_Hash
306
  * Compute the HMAC.
307
  *
308
  * @access public
309
- * @param String $text
310
- * @return String
311
  */
312
  function hash($text)
313
  {
314
  $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
315
 
316
  if (!empty($this->key) || is_string($this->key)) {
317
- switch ( $mode ) {
318
  case CRYPT_HASH_MODE_MHASH:
319
  $output = mhash($this->hash, $text, $this->key);
320
  break;
@@ -337,7 +349,7 @@ class Crypt_Hash
337
  $output = call_user_func($this->hash, $output); // step 7
338
  }
339
  } else {
340
- switch ( $mode ) {
341
  case CRYPT_HASH_MODE_MHASH:
342
  $output = mhash($this->hash, $text);
343
  break;
@@ -356,7 +368,7 @@ class Crypt_Hash
356
  * Returns the hash length (in bytes)
357
  *
358
  * @access public
359
- * @return Integer
360
  */
361
  function getLength()
362
  {
@@ -367,7 +379,7 @@ class Crypt_Hash
367
  * Wrapper for MD5
368
  *
369
  * @access private
370
- * @param String $m
371
  */
372
  function _md5($m)
373
  {
@@ -378,7 +390,7 @@ class Crypt_Hash
378
  * Wrapper for SHA1
379
  *
380
  * @access private
381
- * @param String $m
382
  */
383
  function _sha1($m)
384
  {
@@ -391,7 +403,7 @@ class Crypt_Hash
391
  * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
392
  *
393
  * @access private
394
- * @param String $m
395
  */
396
  function _md2($m)
397
  {
@@ -467,7 +479,7 @@ class Crypt_Hash
467
  * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
468
  *
469
  * @access private
470
- * @param String $m
471
  */
472
  function _sha256($m)
473
  {
@@ -511,14 +523,15 @@ class Crypt_Hash
511
 
512
  // Extend the sixteen 32-bit words into sixty-four 32-bit words
513
  for ($i = 16; $i < 64; $i++) {
 
514
  $s0 = $this->_rightRotate($w[$i - 15], 7) ^
515
  $this->_rightRotate($w[$i - 15], 18) ^
516
  $this->_rightShift( $w[$i - 15], 3);
517
  $s1 = $this->_rightRotate($w[$i - 2], 17) ^
518
  $this->_rightRotate($w[$i - 2], 19) ^
519
  $this->_rightShift( $w[$i - 2], 10);
 
520
  $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
521
-
522
  }
523
 
524
  // Initialize hash value for this chunk
@@ -572,7 +585,7 @@ class Crypt_Hash
572
  * Pure-PHP implementation of SHA384 and SHA512
573
  *
574
  * @access private
575
- * @param String $m
576
  */
577
  function _sha512($m)
578
  {
@@ -755,10 +768,10 @@ class Crypt_Hash
755
  * Right Rotate
756
  *
757
  * @access private
758
- * @param Integer $int
759
- * @param Integer $amt
760
- * @see _sha256()
761
- * @return Integer
762
  */
763
  function _rightRotate($int, $amt)
764
  {
@@ -771,10 +784,10 @@ class Crypt_Hash
771
  * Right Shift
772
  *
773
  * @access private
774
- * @param Integer $int
775
- * @param Integer $amt
776
- * @see _sha256()
777
- * @return Integer
778
  */
779
  function _rightShift($int, $amt)
780
  {
@@ -786,9 +799,9 @@ class Crypt_Hash
786
  * Not
787
  *
788
  * @access private
789
- * @param Integer $int
790
- * @see _sha256()
791
- * @return Integer
792
  */
793
  function _not($int)
794
  {
@@ -801,9 +814,9 @@ class Crypt_Hash
801
  * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
802
  * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
803
  *
804
- * @param Integer $...
805
- * @return Integer
806
- * @see _sha256()
807
  * @access private
808
  */
809
  function _add()
@@ -819,7 +832,14 @@ class Crypt_Hash
819
  $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
820
  }
821
 
822
- return fmod($result, $mod);
 
 
 
 
 
 
 
823
  }
824
 
825
  /**
@@ -827,9 +847,9 @@ class Crypt_Hash
827
  *
828
  * Inspired by array_shift
829
  *
830
- * @param String $string
831
- * @param optional Integer $index
832
- * @return String
833
  * @access private
834
  */
835
  function _string_shift(&$string, $index = 1)
7
  *
8
  * md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
9
  *
10
+ * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
11
  * the hash. If no valid algorithm is provided, sha1 will be used.
12
  *
13
  * PHP versions 4 and 5
56
 
57
  /**#@+
58
  * @access private
59
+ * @see self::Crypt_Hash()
60
  */
61
  /**
62
  * Toggles the internal implementation
84
  /**
85
  * Hash Parameter
86
  *
87
+ * @see self::setHash()
88
+ * @var int
89
  * @access private
90
  */
91
  var $hashParam;
93
  /**
94
  * Byte-length of compression blocks / key (Internal HMAC)
95
  *
96
+ * @see self::setAlgorithm()
97
+ * @var int
98
  * @access private
99
  */
100
  var $b;
102
  /**
103
  * Byte-length of hash output (Internal HMAC)
104
  *
105
+ * @see self::setHash()
106
+ * @var int
107
  * @access private
108
  */
109
  var $l = false;
111
  /**
112
  * Hash Algorithm
113
  *
114
+ * @see self::setHash()
115
+ * @var string
116
  * @access private
117
  */
118
  var $hash;
120
  /**
121
  * Key
122
  *
123
+ * @see self::setKey()
124
+ * @var string
125
  * @access private
126
  */
127
  var $key = false;
129
  /**
130
  * Outer XOR (Internal HMAC)
131
  *
132
+ * @see self::setKey()
133
+ * @var string
134
  * @access private
135
  */
136
  var $opad;
138
  /**
139
  * Inner XOR (Internal HMAC)
140
  *
141
+ * @see self::setKey()
142
+ * @var string
143
  * @access private
144
  */
145
  var $ipad;
147
  /**
148
  * Default Constructor.
149
  *
150
+ * @param string $hash
151
  * @return Crypt_Hash
152
  * @access public
153
  */
154
+ function __construct($hash = 'sha1')
155
  {
156
+ if (!defined('CRYPT_HASH_MODE')) {
157
  switch (true) {
158
  case extension_loaded('hash'):
159
  define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
169
  $this->setHash($hash);
170
  }
171
 
172
+ /**
173
+ * PHP4 compatible Default Constructor.
174
+ *
175
+ * @see self::__construct()
176
+ * @param int $mode
177
+ * @access public
178
+ */
179
+ function Crypt_Hash($hash = 'sha1')
180
+ {
181
+ $this->__construct($hash);
182
+ }
183
+
184
  /**
185
  * Sets the key for HMACs
186
  *
187
  * Keys can be of any length.
188
  *
189
  * @access public
190
+ * @param string $key
191
  */
192
  function setKey($key = false)
193
  {
200
  * As set by the constructor or by the setHash() method.
201
  *
202
  * @access public
203
+ * @return string
204
  */
205
  function getHash()
206
  {
211
  * Sets the hash function.
212
  *
213
  * @access public
214
+ * @param string $hash
215
  */
216
  function setHash($hash)
217
  {
254
  $mode = CRYPT_HASH_MODE;
255
  }
256
 
257
+ switch ($mode) {
258
  case CRYPT_HASH_MODE_MHASH:
259
  switch ($hash) {
260
  case 'md5':
288
 
289
  switch ($hash) {
290
  case 'md2':
291
+ $this->b = 16;
292
+ $this->hash = array($this, '_md2');
293
+ break;
294
  case 'md5':
295
+ $this->b = 64;
296
+ $this->hash = array($this, '_md5');
297
+ break;
298
  case 'sha256':
299
+ $this->b = 64;
300
+ $this->hash = array($this, '_sha256');
301
+ break;
302
  case 'sha384':
303
  case 'sha512':
304
+ $this->b = 128;
305
+ $this->hash = array($this, '_sha512');
306
+ break;
307
  case 'sha1':
308
  default:
309
+ $this->b = 64;
310
+ $this->hash = array($this, '_sha1');
311
  }
312
 
313
  $this->ipad = str_repeat(chr(0x36), $this->b);
318
  * Compute the HMAC.
319
  *
320
  * @access public
321
+ * @param string $text
322
+ * @return string
323
  */
324
  function hash($text)
325
  {
326
  $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
327
 
328
  if (!empty($this->key) || is_string($this->key)) {
329
+ switch ($mode) {
330
  case CRYPT_HASH_MODE_MHASH:
331
  $output = mhash($this->hash, $text, $this->key);
332
  break;
349
  $output = call_user_func($this->hash, $output); // step 7
350
  }
351
  } else {
352
+ switch ($mode) {
353
  case CRYPT_HASH_MODE_MHASH:
354
  $output = mhash($this->hash, $text);
355
  break;
368
  * Returns the hash length (in bytes)
369
  *
370
  * @access public
371
+ * @return int
372
  */
373
  function getLength()
374
  {
379
  * Wrapper for MD5
380
  *
381
  * @access private
382
+ * @param string $m
383
  */
384
  function _md5($m)
385
  {
390
  * Wrapper for SHA1
391
  *
392
  * @access private
393
+ * @param string $m
394
  */
395
  function _sha1($m)
396
  {
403
  * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
404
  *
405
  * @access private
406
+ * @param string $m
407
  */
408
  function _md2($m)
409
  {
479
  * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
480
  *
481
  * @access private
482
+ * @param string $m
483
  */
484
  function _sha256($m)
485
  {
523
 
524
  // Extend the sixteen 32-bit words into sixty-four 32-bit words
525
  for ($i = 16; $i < 64; $i++) {
526
+ // @codingStandardsIgnoreStart
527
  $s0 = $this->_rightRotate($w[$i - 15], 7) ^
528
  $this->_rightRotate($w[$i - 15], 18) ^
529
  $this->_rightShift( $w[$i - 15], 3);
530
  $s1 = $this->_rightRotate($w[$i - 2], 17) ^
531
  $this->_rightRotate($w[$i - 2], 19) ^
532
  $this->_rightShift( $w[$i - 2], 10);
533
+ // @codingStandardsIgnoreEnd
534
  $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
 
535
  }
536
 
537
  // Initialize hash value for this chunk
585
  * Pure-PHP implementation of SHA384 and SHA512
586
  *
587
  * @access private
588
+ * @param string $m
589
  */
590
  function _sha512($m)
591
  {
768
  * Right Rotate
769
  *
770
  * @access private
771
+ * @param int $int
772
+ * @param int $amt
773
+ * @see self::_sha256()
774
+ * @return int
775
  */
776
  function _rightRotate($int, $amt)
777
  {
784
  * Right Shift
785
  *
786
  * @access private
787
+ * @param int $int
788
+ * @param int $amt
789
+ * @see self::_sha256()
790
+ * @return int
791
  */
792
  function _rightShift($int, $amt)
793
  {
799
  * Not
800
  *
801
  * @access private
802
+ * @param int $int
803
+ * @see self::_sha256()
804
+ * @return int
805
  */
806
  function _not($int)
807
  {
814
  * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
815
  * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
816
  *
817
+ * @param int $...
818
+ * @return int
819
+ * @see self::_sha256()
820
  * @access private
821
  */
822
  function _add()
832
  $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
833
  }
834
 
835
+ // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
836
+ // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
837
+ if (is_int($result) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') {
838
+ return fmod($result, $mod);
839
+ }
840
+
841
+ return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
842
+ ((fmod(floor($result / 0x80000000), 2) & 1) << 31);
843
  }
844
 
845
  /**
847
  *
848
  * Inspired by array_shift
849
  *
850
+ * @param string $string
851
+ * @param int $index
852
+ * @return string
853
  * @access private
854
  */
855
  function _string_shift(&$string, $index = 1)
phpseclib/Crypt/RC4.php CHANGED
@@ -71,7 +71,7 @@ if (!class_exists('Crypt_Base')) {
71
 
72
  /**#@+
73
  * @access private
74
- * @see Crypt_RC4::_crypt()
75
  */
76
  define('CRYPT_RC4_ENCRYPT', 0);
77
  define('CRYPT_RC4_DECRYPT', 1);
@@ -93,26 +93,25 @@ class Crypt_RC4 extends Crypt_Base
93
  * so we the block_size to 0
94
  *
95
  * @see Crypt_Base::block_size
96
- * @var Integer
97
  * @access private
98
  */
99
  var $block_size = 0;
100
 
101
  /**
102
- * The default password key_size used by setPassword()
103
  *
104
- * @see Crypt_Base::password_key_size
105
- * @see Crypt_Base::setPassword()
106
- * @var Integer
107
  * @access private
108
  */
109
- var $password_key_size = 128; // = 1024 bits
110
 
111
  /**
112
  * The namespace used by the cipher for its constants.
113
  *
114
  * @see Crypt_Base::const_namespace
115
- * @var String
116
  * @access private
117
  */
118
  var $const_namespace = 'RC4';
@@ -121,7 +120,7 @@ class Crypt_RC4 extends Crypt_Base
121
  * The mcrypt specific name of the cipher
122
  *
123
  * @see Crypt_Base::cipher_name_mcrypt
124
- * @var String
125
  * @access private
126
  */
127
  var $cipher_name_mcrypt = 'arcfour';
@@ -138,17 +137,17 @@ class Crypt_RC4 extends Crypt_Base
138
  /**
139
  * The Key
140
  *
141
- * @see Crypt_RC4::setKey()
142
- * @var String
143
  * @access private
144
  */
145
- var $key = "\0";
146
 
147
  /**
148
  * The Key Stream for decryption and encryption
149
  *
150
- * @see Crypt_RC4::setKey()
151
- * @var Array
152
  * @access private
153
  */
154
  var $stream;
@@ -162,9 +161,20 @@ class Crypt_RC4 extends Crypt_Base
162
  * @return Crypt_RC4
163
  * @access public
164
  */
 
 
 
 
 
 
 
 
 
 
 
165
  function Crypt_RC4()
166
  {
167
- parent::Crypt_Base(CRYPT_MODE_STREAM);
168
  }
169
 
170
  /**
@@ -173,14 +183,16 @@ class Crypt_RC4 extends Crypt_Base
173
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
174
  *
175
  * @see Crypt_Base::Crypt_Base()
176
- * @param Integer $engine
177
  * @access public
178
- * @return Boolean
179
  */
180
  function isValidEngine($engine)
181
  {
182
- switch ($engine) {
183
- case CRYPT_ENGINE_OPENSSL:
 
 
184
  switch (strlen($this->key)) {
185
  case 5:
186
  $this->cipher_name_openssl = 'rc4-40';
@@ -194,6 +206,7 @@ class Crypt_RC4 extends Crypt_Base
194
  default:
195
  return false;
196
  }
 
197
  }
198
 
199
  return parent::isValidEngine($engine);
@@ -214,8 +227,8 @@ class Crypt_RC4 extends Crypt_Base
214
  * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
215
  * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
216
  *
217
- * @param String $iv
218
- * @see Crypt_RC4::setKey()
219
  * @access public
220
  */
221
  function setIV($iv)
@@ -223,28 +236,34 @@ class Crypt_RC4 extends Crypt_Base
223
  }
224
 
225
  /**
226
- * Sets the key.
227
  *
228
- * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
229
- * be used. If no key is explicitly set, it'll be assumed to be a single null byte.
230
  *
231
  * @access public
232
- * @see Crypt_Base::setKey()
233
- * @param String $key
234
  */
235
- function setKey($key)
236
  {
237
- parent::setKey(substr($key, 0, 256));
 
 
 
 
 
 
 
 
238
  }
239
 
240
  /**
241
  * Encrypts a message.
242
  *
243
  * @see Crypt_Base::decrypt()
244
- * @see Crypt_RC4::_crypt()
245
  * @access public
246
- * @param String $plaintext
247
- * @return String $ciphertext
248
  */
249
  function encrypt($plaintext)
250
  {
@@ -261,10 +280,10 @@ class Crypt_RC4 extends Crypt_Base
261
  * At least if the continuous buffer is disabled.
262
  *
263
  * @see Crypt_Base::encrypt()
264
- * @see Crypt_RC4::_crypt()
265
  * @access public
266
- * @param String $ciphertext
267
- * @return String $plaintext
268
  */
269
  function decrypt($ciphertext)
270
  {
@@ -305,12 +324,12 @@ class Crypt_RC4 extends Crypt_Base
305
  /**
306
  * Encrypts or decrypts a message.
307
  *
308
- * @see Crypt_RC4::encrypt()
309
- * @see Crypt_RC4::decrypt()
310
  * @access private
311
- * @param String $text
312
- * @param Integer $mode
313
- * @return String $text
314
  */
315
  function _crypt($text, $mode)
316
  {
71
 
72
  /**#@+
73
  * @access private
74
+ * @see self::_crypt()
75
  */
76
  define('CRYPT_RC4_ENCRYPT', 0);
77
  define('CRYPT_RC4_DECRYPT', 1);
93
  * so we the block_size to 0
94
  *
95
  * @see Crypt_Base::block_size
96
+ * @var int
97
  * @access private
98
  */
99
  var $block_size = 0;
100
 
101
  /**
102
+ * Key Length (in bytes)
103
  *
104
+ * @see Crypt_RC4::setKeyLength()
105
+ * @var int
 
106
  * @access private
107
  */
108
+ var $key_length = 128; // = 1024 bits
109
 
110
  /**
111
  * The namespace used by the cipher for its constants.
112
  *
113
  * @see Crypt_Base::const_namespace
114
+ * @var string
115
  * @access private
116
  */
117
  var $const_namespace = 'RC4';
120
  * The mcrypt specific name of the cipher
121
  *
122
  * @see Crypt_Base::cipher_name_mcrypt
123
+ * @var string
124
  * @access private
125
  */
126
  var $cipher_name_mcrypt = 'arcfour';
137
  /**
138
  * The Key
139
  *
140
+ * @see self::setKey()
141
+ * @var string
142
  * @access private
143
  */
144
+ var $key;
145
 
146
  /**
147
  * The Key Stream for decryption and encryption
148
  *
149
+ * @see self::setKey()
150
+ * @var array
151
  * @access private
152
  */
153
  var $stream;
161
  * @return Crypt_RC4
162
  * @access public
163
  */
164
+ function __construct()
165
+ {
166
+ parent::__construct(CRYPT_MODE_STREAM);
167
+ }
168
+
169
+ /**
170
+ * PHP4 compatible Default Constructor.
171
+ *
172
+ * @see self::__construct()
173
+ * @access public
174
+ */
175
  function Crypt_RC4()
176
  {
177
+ $this->__construct();
178
  }
179
 
180
  /**
183
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
184
  *
185
  * @see Crypt_Base::Crypt_Base()
186
+ * @param int $engine
187
  * @access public
188
+ * @return bool
189
  */
190
  function isValidEngine($engine)
191
  {
192
+ if ($engine == CRYPT_ENGINE_OPENSSL) {
193
+ if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
194
+ $this->cipher_name_openssl = 'rc4-40';
195
+ } else {
196
  switch (strlen($this->key)) {
197
  case 5:
198
  $this->cipher_name_openssl = 'rc4-40';
206
  default:
207
  return false;
208
  }
209
+ }
210
  }
211
 
212
  return parent::isValidEngine($engine);
227
  * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
228
  * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
229
  *
230
+ * @param string $iv
231
+ * @see self::setKey()
232
  * @access public
233
  */
234
  function setIV($iv)
236
  }
237
 
238
  /**
239
+ * Sets the key length
240
  *
241
+ * Keys can be between 1 and 256 bytes long.
 
242
  *
243
  * @access public
244
+ * @param int $length
 
245
  */
246
+ function setKeyLength($length)
247
  {
248
+ if ($length < 8) {
249
+ $this->key_length = 1;
250
+ } elseif ($length > 2048) {
251
+ $this->key_length = 256;
252
+ } else {
253
+ $this->key_length = $length >> 3;
254
+ }
255
+
256
+ parent::setKeyLength($length);
257
  }
258
 
259
  /**
260
  * Encrypts a message.
261
  *
262
  * @see Crypt_Base::decrypt()
263
+ * @see self::_crypt()
264
  * @access public
265
+ * @param string $plaintext
266
+ * @return string $ciphertext
267
  */
268
  function encrypt($plaintext)
269
  {
280
  * At least if the continuous buffer is disabled.
281
  *
282
  * @see Crypt_Base::encrypt()
283
+ * @see self::_crypt()
284
  * @access public
285
+ * @param string $ciphertext
286
+ * @return string $plaintext
287
  */
288
  function decrypt($ciphertext)
289
  {
324
  /**
325
  * Encrypts or decrypts a message.
326
  *
327
+ * @see self::encrypt()
328
+ * @see self::decrypt()
329
  * @access private
330
+ * @param string $text
331
+ * @param int $mode
332
+ * @return string $text
333
  */
334
  function _crypt($text, $mode)
335
  {
phpseclib/Crypt/RSA.php CHANGED
@@ -87,8 +87,8 @@ if (!class_exists('Crypt_Hash')) {
87
 
88
  /**#@+
89
  * @access public
90
- * @see Crypt_RSA::encrypt()
91
- * @see Crypt_RSA::decrypt()
92
  */
93
  /**
94
  * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
@@ -96,8 +96,8 @@ if (!class_exists('Crypt_Hash')) {
96
  *
97
  * Uses sha1 by default.
98
  *
99
- * @see Crypt_RSA::setHash()
100
- * @see Crypt_RSA::setMGFHash()
101
  */
102
  define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
103
  /**
@@ -107,21 +107,28 @@ define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
107
  * compatibility with protocols (like SSH-1) written before OAEP's introduction.
108
  */
109
  define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
 
 
 
 
 
 
 
110
  /**#@-*/
111
 
112
  /**#@+
113
  * @access public
114
- * @see Crypt_RSA::sign()
115
- * @see Crypt_RSA::verify()
116
- * @see Crypt_RSA::setHash()
117
  */
118
  /**
119
  * Use the Probabilistic Signature Scheme for signing
120
  *
121
  * Uses sha1 by default.
122
  *
123
- * @see Crypt_RSA::setSaltLength()
124
- * @see Crypt_RSA::setMGFHash()
125
  */
126
  define('CRYPT_RSA_SIGNATURE_PSS', 1);
127
  /**
@@ -135,7 +142,7 @@ define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
135
 
136
  /**#@+
137
  * @access private
138
- * @see Crypt_RSA::createKey()
139
  */
140
  /**
141
  * ASN1 Integer
@@ -161,7 +168,7 @@ define('CRYPT_RSA_ASN1_SEQUENCE', 48);
161
 
162
  /**#@+
163
  * @access private
164
- * @see Crypt_RSA::Crypt_RSA()
165
  */
166
  /**
167
  * To use the pure-PHP implementation
@@ -182,8 +189,8 @@ define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf');
182
 
183
  /**#@+
184
  * @access public
185
- * @see Crypt_RSA::createKey()
186
- * @see Crypt_RSA::setPrivateKeyFormat()
187
  */
188
  /**
189
  * PKCS#1 formatted private key
@@ -202,13 +209,13 @@ define('CRYPT_RSA_PRIVATE_FORMAT_XML', 2);
202
  /**
203
  * PKCS#8 formatted private key
204
  */
205
- define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 3);
206
  /**#@-*/
207
 
208
  /**#@+
209
  * @access public
210
- * @see Crypt_RSA::createKey()
211
- * @see Crypt_RSA::setPublicKeyFormat()
212
  */
213
  /**
214
  * Raw public key
@@ -275,7 +282,7 @@ class Crypt_RSA
275
  /**
276
  * Precomputed Zero
277
  *
278
- * @var Array
279
  * @access private
280
  */
281
  var $zero;
@@ -283,7 +290,7 @@ class Crypt_RSA
283
  /**
284
  * Precomputed One
285
  *
286
- * @var Array
287
  * @access private
288
  */
289
  var $one;
@@ -291,7 +298,7 @@ class Crypt_RSA
291
  /**
292
  * Private Key Format
293
  *
294
- * @var Integer
295
  * @access private
296
  */
297
  var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1;
@@ -299,7 +306,7 @@ class Crypt_RSA
299
  /**
300
  * Public Key Format
301
  *
302
- * @var Integer
303
  * @access public
304
  */
305
  var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8;
@@ -331,7 +338,7 @@ class Crypt_RSA
331
  /**
332
  * Primes for Chinese Remainder Theorem (ie. p and q)
333
  *
334
- * @var Array
335
  * @access private
336
  */
337
  var $primes;
@@ -339,7 +346,7 @@ class Crypt_RSA
339
  /**
340
  * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
341
  *
342
- * @var Array
343
  * @access private
344
  */
345
  var $exponents;
@@ -347,7 +354,7 @@ class Crypt_RSA
347
  /**
348
  * Coefficients for Chinese Remainder Theorem (ie. qInv)
349
  *
350
- * @var Array
351
  * @access private
352
  */
353
  var $coefficients;
@@ -355,7 +362,7 @@ class Crypt_RSA
355
  /**
356
  * Hash name
357
  *
358
- * @var String
359
  * @access private
360
  */
361
  var $hashName;
@@ -371,7 +378,7 @@ class Crypt_RSA
371
  /**
372
  * Length of hash function output
373
  *
374
- * @var Integer
375
  * @access private
376
  */
377
  var $hLen;
@@ -379,7 +386,7 @@ class Crypt_RSA
379
  /**
380
  * Length of salt
381
  *
382
- * @var Integer
383
  * @access private
384
  */
385
  var $sLen;
@@ -395,7 +402,7 @@ class Crypt_RSA
395
  /**
396
  * Length of MGF hash function output
397
  *
398
- * @var Integer
399
  * @access private
400
  */
401
  var $mgfHLen;
@@ -403,7 +410,7 @@ class Crypt_RSA
403
  /**
404
  * Encryption mode
405
  *
406
- * @var Integer
407
  * @access private
408
  */
409
  var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP;
@@ -411,7 +418,7 @@ class Crypt_RSA
411
  /**
412
  * Signature mode
413
  *
414
- * @var Integer
415
  * @access private
416
  */
417
  var $signatureMode = CRYPT_RSA_SIGNATURE_PSS;
@@ -419,7 +426,7 @@ class Crypt_RSA
419
  /**
420
  * Public Exponent
421
  *
422
- * @var Mixed
423
  * @access private
424
  */
425
  var $publicExponent = false;
@@ -427,7 +434,7 @@ class Crypt_RSA
427
  /**
428
  * Password
429
  *
430
- * @var String
431
  * @access private
432
  */
433
  var $password = false;
@@ -438,8 +445,8 @@ class Crypt_RSA
438
  * For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions -
439
  * because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't.
440
  *
441
- * @see Crypt_RSA::_start_element_handler()
442
- * @var Array
443
  * @access private
444
  */
445
  var $components = array();
@@ -449,9 +456,9 @@ class Crypt_RSA
449
  *
450
  * For use with parsing XML formatted keys.
451
  *
452
- * @see Crypt_RSA::_character_handler()
453
- * @see Crypt_RSA::_stop_element_handler()
454
- * @var Mixed
455
  * @access private
456
  */
457
  var $current;
@@ -460,8 +467,8 @@ class Crypt_RSA
460
  * OpenSSL configuration file name.
461
  *
462
  * Set to null to use system configuration file.
463
- * @see Crypt_RSA::createKey()
464
- * @var Mixed
465
  * @Access public
466
  */
467
  var $configFile;
@@ -469,7 +476,7 @@ class Crypt_RSA
469
  /**
470
  * Public key comment field.
471
  *
472
- * @var String
473
  * @access private
474
  */
475
  var $comment = 'phpseclib-generated-key';
@@ -484,7 +491,7 @@ class Crypt_RSA
484
  * @return Crypt_RSA
485
  * @access public
486
  */
487
- function Crypt_RSA()
488
  {
489
  if (!class_exists('Math_BigInteger')) {
490
  include_once 'Math/BigInteger.php';
@@ -492,7 +499,7 @@ class Crypt_RSA
492
 
493
  $this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
494
 
495
- if ( !defined('CRYPT_RSA_MODE') ) {
496
  switch (true) {
497
  // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
498
  // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
@@ -532,6 +539,7 @@ class Crypt_RSA
532
  case !isset($versions['Header']):
533
  case !isset($versions['Library']):
534
  case $versions['Header'] == $versions['Library']:
 
535
  define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
536
  break;
537
  default:
@@ -554,6 +562,17 @@ class Crypt_RSA
554
  $this->mgfHLen = $this->mgfHash->getLength();
555
  }
556
 
 
 
 
 
 
 
 
 
 
 
 
557
  /**
558
  * Create public / private key pair
559
  *
@@ -564,9 +583,9 @@ class Crypt_RSA
564
  * Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing.
565
  *
566
  * @access public
567
- * @param optional Integer $bits
568
- * @param optional Integer $timeout
569
- * @param optional Math_BigInteger $p
570
  */
571
  function createKey($bits = 1024, $timeout = false, $partial = array())
572
  {
@@ -585,7 +604,7 @@ class Crypt_RSA
585
  }
586
 
587
  // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
588
- if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
589
  $config = array();
590
  if (isset($this->configFile)) {
591
  $config['config'] = $this->configFile;
@@ -599,7 +618,8 @@ class Crypt_RSA
599
  $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
600
 
601
  // clear the buffer of error strings stemming from a minimalistic openssl.cnf
602
- while (openssl_error_string() !== false);
 
603
 
604
  return array(
605
  'privatekey' => $privatekey,
@@ -743,9 +763,9 @@ class Crypt_RSA
743
  * Convert a private key to the appropriate format.
744
  *
745
  * @access private
746
- * @see setPrivateKeyFormat()
747
- * @param String $RSAPrivateKey
748
- * @return String
749
  */
750
  function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
751
  {
@@ -789,19 +809,39 @@ class Crypt_RSA
789
  $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
790
  $key.= $encryption;
791
  $key.= "\r\nComment: " . $this->comment . "\r\n";
792
- $public = pack('Na*Na*Na*',
793
- strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']
 
 
 
 
 
 
794
  );
795
- $source = pack('Na*Na*Na*Na*',
796
- strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption,
797
- strlen($this->comment), $this->comment, strlen($public), $public
 
 
 
 
 
 
 
798
  );
799
  $public = base64_encode($public);
800
  $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
801
  $key.= chunk_split($public, 64);
802
- $private = pack('Na*Na*Na*Na*',
803
- strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'],
804
- strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient']
 
 
 
 
 
 
 
805
  );
806
  if (empty($this->password) && !is_string($this->password)) {
807
  $source.= pack('Na*', strlen($private), $private);
@@ -868,8 +908,14 @@ class Crypt_RSA
868
 
869
  if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
870
  $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
871
- $RSAPrivateKey = pack('Ca*a*Ca*a*',
872
- CRYPT_RSA_ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey
 
 
 
 
 
 
873
  );
874
  $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
875
  if (!empty($this->password) || is_string($this->password)) {
@@ -883,20 +929,35 @@ class Crypt_RSA
883
  $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
884
  $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
885
 
886
- $parameters = pack('Ca*a*Ca*N',
887
- CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($salt)), $salt,
888
- CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(4), $iterationCount
 
 
 
 
 
889
  );
890
  $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
891
 
892
- $encryptionAlgorithm = pack('Ca*a*Ca*a*',
893
- CRYPT_RSA_ASN1_OBJECT, $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), $pbeWithMD5AndDES_CBC,
894
- CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($parameters)), $parameters
 
 
 
 
 
895
  );
896
 
897
- $RSAPrivateKey = pack('Ca*a*Ca*a*',
898
- CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($encryptionAlgorithm)), $encryptionAlgorithm,
899
- CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey
 
 
 
 
 
900
  );
901
 
902
  $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
@@ -943,9 +1004,9 @@ class Crypt_RSA
943
  * Convert a public key to the appropriate format
944
  *
945
  * @access private
946
- * @see setPublicKeyFormat()
947
- * @param String $RSAPrivateKey
948
- * @return String
949
  */
950
  function _convertPublicKey($n, $e)
951
  {
@@ -983,9 +1044,12 @@ class Crypt_RSA
983
  'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
984
  );
985
 
986
- $RSAPublicKey = pack('Ca*a*a*',
987
- CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
988
- $components['modulus'], $components['publicExponent']
 
 
 
989
  );
990
 
991
  if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
@@ -998,8 +1062,11 @@ class Crypt_RSA
998
  $RSAPublicKey = chr(0) . $RSAPublicKey;
999
  $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
1000
 
1001
- $RSAPublicKey = pack('Ca*a*',
1002
- CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
 
 
 
1003
  );
1004
 
1005
  $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@@ -1015,11 +1082,11 @@ class Crypt_RSA
1015
  * Break a public or private key down into its constituant components
1016
  *
1017
  * @access private
1018
- * @see _convertPublicKey()
1019
- * @see _convertPrivateKey()
1020
- * @param String $key
1021
- * @param Integer $type
1022
- * @return Array
1023
  */
1024
  function _parseKey($key, $type)
1025
  {
@@ -1435,7 +1502,7 @@ class Crypt_RSA
1435
  * More specifically, this returns the size of the modulo in bits.
1436
  *
1437
  * @access public
1438
- * @return Integer
1439
  */
1440
  function getSize()
1441
  {
@@ -1448,9 +1515,9 @@ class Crypt_RSA
1448
  * Called by xml_set_element_handler()
1449
  *
1450
  * @access private
1451
- * @param Resource $parser
1452
- * @param String $name
1453
- * @param Array $attribs
1454
  */
1455
  function _start_element_handler($parser, $name, $attribs)
1456
  {
@@ -1489,8 +1556,8 @@ class Crypt_RSA
1489
  * Called by xml_set_element_handler()
1490
  *
1491
  * @access private
1492
- * @param Resource $parser
1493
- * @param String $name
1494
  */
1495
  function _stop_element_handler($parser, $name)
1496
  {
@@ -1506,8 +1573,8 @@ class Crypt_RSA
1506
  * Called by xml_set_character_data_handler()
1507
  *
1508
  * @access private
1509
- * @param Resource $parser
1510
- * @param String $data
1511
  */
1512
  function _data_handler($parser, $data)
1513
  {
@@ -1523,8 +1590,8 @@ class Crypt_RSA
1523
  * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
1524
  *
1525
  * @access public
1526
- * @param String $key
1527
- * @param Integer $type optional
1528
  */
1529
  function loadKey($key, $type = false)
1530
  {
@@ -1589,12 +1656,20 @@ class Crypt_RSA
1589
  break;
1590
  }
1591
  }
1592
-
1593
  } else {
1594
  $components = $this->_parseKey($key, $type);
1595
  }
1596
 
1597
  if ($components === false) {
 
 
 
 
 
 
 
 
 
1598
  return false;
1599
  }
1600
 
@@ -1638,10 +1713,10 @@ class Crypt_RSA
1638
  * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
1639
  * Or rather, pass in $password such that empty($password) && !is_string($password) is true.
1640
  *
1641
- * @see createKey()
1642
- * @see loadKey()
1643
  * @access public
1644
- * @param String $password
1645
  */
1646
  function setPassword($password = false)
1647
  {
@@ -1663,11 +1738,11 @@ class Crypt_RSA
1663
  *
1664
  * Returns true on success, false on failure
1665
  *
1666
- * @see getPublicKey()
1667
  * @access public
1668
- * @param String $key optional
1669
- * @param Integer $type optional
1670
- * @return Boolean
1671
  */
1672
  function setPublicKey($key = false, $type = false)
1673
  {
@@ -1723,16 +1798,16 @@ class Crypt_RSA
1723
  *
1724
  * Returns true on success, false on failure
1725
  *
1726
- * @see getPublicKey()
1727
  * @access public
1728
- * @param String $key optional
1729
- * @param Integer $type optional
1730
- * @return Boolean
1731
  */
1732
  function setPrivateKey($key = false, $type = false)
1733
  {
1734
  if ($key === false && !empty($this->publicExponent)) {
1735
- unset($this->publicExponent);
1736
  return true;
1737
  }
1738
 
@@ -1740,7 +1815,7 @@ class Crypt_RSA
1740
  if (!$rsa->loadKey($key, $type)) {
1741
  return false;
1742
  }
1743
- unset($rsa->publicExponent);
1744
 
1745
  // don't overwrite the old key if the new key is invalid
1746
  $this->loadKey($rsa);
@@ -1754,10 +1829,10 @@ class Crypt_RSA
1754
  * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
1755
  * function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
1756
  *
1757
- * @see getPublicKey()
1758
  * @access public
1759
- * @param String $key
1760
- * @param Integer $type optional
1761
  */
1762
  function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1763
  {
@@ -1780,10 +1855,11 @@ class Crypt_RSA
1780
  * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
1781
  *
1782
  * @access public
1783
- * @param String $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
1784
  * for invalid values.
 
1785
  */
1786
- public function getPublicKeyFingerprint($algorithm = 'md5')
1787
  {
1788
  if (empty($this->modulus) || empty($this->publicExponent)) {
1789
  return false;
@@ -1794,8 +1870,7 @@ class Crypt_RSA
1794
 
1795
  $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
1796
 
1797
- switch($algorithm)
1798
- {
1799
  case 'sha256':
1800
  $hash = new Crypt_Hash('sha256');
1801
  $base = base64_encode($hash->hash($RSAPublicKey));
@@ -1805,7 +1880,6 @@ class Crypt_RSA
1805
  default:
1806
  return false;
1807
  }
1808
-
1809
  }
1810
 
1811
  /**
@@ -1813,10 +1887,11 @@ class Crypt_RSA
1813
  *
1814
  * The private key is only returned if the currently loaded key contains the constituent prime numbers.
1815
  *
1816
- * @see getPublicKey()
1817
  * @access public
1818
- * @param String $key
1819
- * @param Integer $type optional
 
1820
  */
1821
  function getPrivateKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
1822
  {
@@ -1837,10 +1912,10 @@ class Crypt_RSA
1837
  * Returns the private key without the prime number constituants. Structurally identical to a public key that
1838
  * hasn't been set as the public key
1839
  *
1840
- * @see getPrivateKey()
1841
  * @access private
1842
- * @param String $key
1843
- * @param Integer $type optional
1844
  */
1845
  function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1846
  {
@@ -1859,6 +1934,7 @@ class Crypt_RSA
1859
  * __toString() magic method
1860
  *
1861
  * @access public
 
1862
  */
1863
  function __toString()
1864
  {
@@ -1874,6 +1950,7 @@ class Crypt_RSA
1874
  * __clone() magic method
1875
  *
1876
  * @access public
 
1877
  */
1878
  function __clone()
1879
  {
@@ -1886,8 +1963,8 @@ class Crypt_RSA
1886
  * Generates the smallest and largest numbers requiring $bits bits
1887
  *
1888
  * @access private
1889
- * @param Integer $bits
1890
- * @return Array
1891
  */
1892
  function _generateMinMax($bits)
1893
  {
@@ -1915,13 +1992,13 @@ class Crypt_RSA
1915
  * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
1916
  *
1917
  * @access private
1918
- * @param String $string
1919
- * @return Integer
1920
  */
1921
  function _decodeLength(&$string)
1922
  {
1923
  $length = ord($this->_string_shift($string));
1924
- if ( $length & 0x80 ) { // definite length, long form
1925
  $length&= 0x7F;
1926
  $temp = $this->_string_shift($string, $length);
1927
  list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
@@ -1936,8 +2013,8 @@ class Crypt_RSA
1936
  * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
1937
  *
1938
  * @access private
1939
- * @param Integer $length
1940
- * @return String
1941
  */
1942
  function _encodeLength($length)
1943
  {
@@ -1954,9 +2031,9 @@ class Crypt_RSA
1954
  *
1955
  * Inspired by array_shift
1956
  *
1957
- * @param String $string
1958
- * @param optional Integer $index
1959
- * @return String
1960
  * @access private
1961
  */
1962
  function _string_shift(&$string, $index = 1)
@@ -1969,9 +2046,9 @@ class Crypt_RSA
1969
  /**
1970
  * Determines the private key format
1971
  *
1972
- * @see createKey()
1973
  * @access public
1974
- * @param Integer $format
1975
  */
1976
  function setPrivateKeyFormat($format)
1977
  {
@@ -1981,9 +2058,9 @@ class Crypt_RSA
1981
  /**
1982
  * Determines the public key format
1983
  *
1984
- * @see createKey()
1985
  * @access public
1986
- * @param Integer $format
1987
  */
1988
  function setPublicKeyFormat($format)
1989
  {
@@ -1997,7 +2074,7 @@ class Crypt_RSA
1997
  * decryption. If $hash isn't supported, sha1 is used.
1998
  *
1999
  * @access public
2000
- * @param String $hash
2001
  */
2002
  function setHash($hash)
2003
  {
@@ -2026,7 +2103,7 @@ class Crypt_RSA
2026
  * best if Hash and MGFHash are set to the same thing this is not a requirement.
2027
  *
2028
  * @access public
2029
- * @param String $hash
2030
  */
2031
  function setMGFHash($hash)
2032
  {
@@ -2055,7 +2132,7 @@ class Crypt_RSA
2055
  * of the hash function Hash) and 0.
2056
  *
2057
  * @access public
2058
- * @param Integer $format
2059
  */
2060
  function setSaltLength($sLen)
2061
  {
@@ -2069,8 +2146,8 @@ class Crypt_RSA
2069
  *
2070
  * @access private
2071
  * @param Math_BigInteger $x
2072
- * @param Integer $xLen
2073
- * @return String
2074
  */
2075
  function _i2osp($x, $xLen)
2076
  {
@@ -2088,7 +2165,7 @@ class Crypt_RSA
2088
  * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
2089
  *
2090
  * @access private
2091
- * @param String $x
2092
  * @return Math_BigInteger
2093
  */
2094
  function _os2ip($x)
@@ -2107,8 +2184,14 @@ class Crypt_RSA
2107
  */
2108
  function _exponentiate($x)
2109
  {
2110
- if (empty($this->primes) || empty($this->coefficients) || empty($this->exponents)) {
2111
- return $x->modPow($this->exponent, $this->modulus);
 
 
 
 
 
 
2112
  }
2113
 
2114
  $num_primes = count($this->primes);
@@ -2182,7 +2265,7 @@ class Crypt_RSA
2182
  * @access private
2183
  * @param Math_BigInteger $x
2184
  * @param Math_BigInteger $r
2185
- * @param Integer $i
2186
  * @return Math_BigInteger
2187
  */
2188
  function _blind($x, $r, $i)
@@ -2207,9 +2290,9 @@ class Crypt_RSA
2207
  * Thanks for the heads up singpolyma!
2208
  *
2209
  * @access private
2210
- * @param String $x
2211
- * @param String $y
2212
- * @return Boolean
2213
  */
2214
  function _equals($x, $y)
2215
  {
@@ -2303,9 +2386,9 @@ class Crypt_RSA
2303
  * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
2304
  *
2305
  * @access private
2306
- * @param String $mgfSeed
2307
- * @param Integer $mgfLen
2308
- * @return String
2309
  */
2310
  function _mgf1($mgfSeed, $maskLen)
2311
  {
@@ -2328,9 +2411,9 @@ class Crypt_RSA
2328
  * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
2329
  *
2330
  * @access private
2331
- * @param String $m
2332
- * @param String $l
2333
- * @return String
2334
  */
2335
  function _rsaes_oaep_encrypt($m, $l = '')
2336
  {
@@ -2391,9 +2474,9 @@ class Crypt_RSA
2391
  * this document.
2392
  *
2393
  * @access private
2394
- * @param String $c
2395
- * @param String $l
2396
- * @return String
2397
  */
2398
  function _rsaes_oaep_decrypt($c, $l = '')
2399
  {
@@ -2429,7 +2512,7 @@ class Crypt_RSA
2429
  $db = $maskedDB ^ $dbMask;
2430
  $lHash2 = substr($db, 0, $this->hLen);
2431
  $m = substr($db, $this->hLen);
2432
- if ($lHash != $lHash2) {
2433
  user_error('Decryption error');
2434
  return false;
2435
  }
@@ -2444,14 +2527,30 @@ class Crypt_RSA
2444
  return substr($m, 1);
2445
  }
2446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2447
  /**
2448
  * RSAES-PKCS1-V1_5-ENCRYPT
2449
  *
2450
  * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
2451
  *
2452
  * @access private
2453
- * @param String $m
2454
- * @return String
2455
  */
2456
  function _rsaes_pkcs1_v1_5_encrypt($m)
2457
  {
@@ -2509,8 +2608,8 @@ class Crypt_RSA
2509
  * not private key encrypted ciphertext's.
2510
  *
2511
  * @access private
2512
- * @param String $c
2513
- * @return String
2514
  */
2515
  function _rsaes_pkcs1_v1_5_decrypt($c)
2516
  {
@@ -2558,8 +2657,8 @@ class Crypt_RSA
2558
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
2559
  *
2560
  * @access private
2561
- * @param String $m
2562
- * @param Integer $emBits
2563
  */
2564
  function _emsa_pss_encode($m, $emBits)
2565
  {
@@ -2567,7 +2666,7 @@ class Crypt_RSA
2567
  // be output.
2568
 
2569
  $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
2570
- $sLen = $this->sLen === false ? $this->hLen : $this->sLen;
2571
 
2572
  $mHash = $this->hash->hash($m);
2573
  if ($emLen < $this->hLen + $sLen + 2) {
@@ -2594,10 +2693,10 @@ class Crypt_RSA
2594
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
2595
  *
2596
  * @access private
2597
- * @param String $m
2598
- * @param String $em
2599
- * @param Integer $emBits
2600
- * @return String
2601
  */
2602
  function _emsa_pss_verify($m, $em, $emBits)
2603
  {
@@ -2605,7 +2704,7 @@ class Crypt_RSA
2605
  // be output.
2606
 
2607
  $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
2608
- $sLen = $this->sLen === false ? $this->hLen : $this->sLen;
2609
 
2610
  $mHash = $this->hash->hash($m);
2611
  if ($emLen < $this->hLen + $sLen + 2) {
@@ -2641,8 +2740,8 @@ class Crypt_RSA
2641
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
2642
  *
2643
  * @access private
2644
- * @param String $m
2645
- * @return String
2646
  */
2647
  function _rsassa_pss_sign($m)
2648
  {
@@ -2667,9 +2766,9 @@ class Crypt_RSA
2667
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
2668
  *
2669
  * @access private
2670
- * @param String $m
2671
- * @param String $s
2672
- * @return String
2673
  */
2674
  function _rsassa_pss_verify($m, $s)
2675
  {
@@ -2707,9 +2806,9 @@ class Crypt_RSA
2707
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
2708
  *
2709
  * @access private
2710
- * @param String $m
2711
- * @param Integer $emLen
2712
- * @return String
2713
  */
2714
  function _emsa_pkcs1_v1_5_encode($m, $emLen)
2715
  {
@@ -2759,8 +2858,8 @@ class Crypt_RSA
2759
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
2760
  *
2761
  * @access private
2762
- * @param String $m
2763
- * @return String
2764
  */
2765
  function _rsassa_pkcs1_v1_5_sign($m)
2766
  {
@@ -2789,8 +2888,8 @@ class Crypt_RSA
2789
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
2790
  *
2791
  * @access private
2792
- * @param String $m
2793
- * @return String
2794
  */
2795
  function _rsassa_pkcs1_v1_5_verify($m, $s)
2796
  {
@@ -2833,7 +2932,7 @@ class Crypt_RSA
2833
  * Valid values include CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1.
2834
  *
2835
  * @access public
2836
- * @param Integer $mode
2837
  */
2838
  function setEncryptionMode($mode)
2839
  {
@@ -2846,7 +2945,7 @@ class Crypt_RSA
2846
  * Valid values include CRYPT_RSA_SIGNATURE_PSS and CRYPT_RSA_SIGNATURE_PKCS1
2847
  *
2848
  * @access public
2849
- * @param Integer $mode
2850
  */
2851
  function setSignatureMode($mode)
2852
  {
@@ -2857,7 +2956,7 @@ class Crypt_RSA
2857
  * Set public key comment.
2858
  *
2859
  * @access public
2860
- * @param String $comment
2861
  */
2862
  function setComment($comment)
2863
  {
@@ -2868,7 +2967,7 @@ class Crypt_RSA
2868
  * Get public key comment.
2869
  *
2870
  * @access public
2871
- * @return String
2872
  */
2873
  function getComment()
2874
  {
@@ -2882,14 +2981,21 @@ class Crypt_RSA
2882
  * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
2883
  * be concatenated together.
2884
  *
2885
- * @see decrypt()
2886
  * @access public
2887
- * @param String $plaintext
2888
- * @return String
2889
  */
2890
  function encrypt($plaintext)
2891
  {
2892
  switch ($this->encryptionMode) {
 
 
 
 
 
 
 
2893
  case CRYPT_RSA_ENCRYPTION_PKCS1:
2894
  $length = $this->k - 11;
2895
  if ($length <= 0) {
@@ -2921,10 +3027,10 @@ class Crypt_RSA
2921
  /**
2922
  * Decryption
2923
  *
2924
- * @see encrypt()
2925
  * @access public
2926
- * @param String $plaintext
2927
- * @return String
2928
  */
2929
  function decrypt($ciphertext)
2930
  {
@@ -2938,6 +3044,9 @@ class Crypt_RSA
2938
  $plaintext = '';
2939
 
2940
  switch ($this->encryptionMode) {
 
 
 
2941
  case CRYPT_RSA_ENCRYPTION_PKCS1:
2942
  $decrypt = '_rsaes_pkcs1_v1_5_decrypt';
2943
  break;
@@ -2960,10 +3069,10 @@ class Crypt_RSA
2960
  /**
2961
  * Create a signature
2962
  *
2963
- * @see verify()
2964
  * @access public
2965
- * @param String $message
2966
- * @return String
2967
  */
2968
  function sign($message)
2969
  {
@@ -2983,11 +3092,11 @@ class Crypt_RSA
2983
  /**
2984
  * Verifies a signature
2985
  *
2986
- * @see sign()
2987
  * @access public
2988
- * @param String $message
2989
- * @param String $signature
2990
- * @return Boolean
2991
  */
2992
  function verify($message, $signature)
2993
  {
@@ -3008,8 +3117,8 @@ class Crypt_RSA
3008
  * Extract raw BER from Base64 encoding
3009
  *
3010
  * @access private
3011
- * @param String $str
3012
- * @return String
3013
  */
3014
  function _extractBER($str)
3015
  {
@@ -3022,7 +3131,7 @@ class Crypt_RSA
3022
  * subject=/O=organization/OU=org unit/CN=common name
3023
  * issuer=/O=organization/CN=common name
3024
  */
3025
- $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1);
3026
  // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
3027
  $temp = preg_replace('#-+[^-]+-+#', '', $temp);
3028
  // remove new lines
87
 
88
  /**#@+
89
  * @access public
90
+ * @see self::encrypt()
91
+ * @see self::decrypt()
92
  */
93
  /**
94
  * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
96
  *
97
  * Uses sha1 by default.
98
  *
99
+ * @see self::setHash()
100
+ * @see self::setMGFHash()
101
  */
102
  define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
103
  /**
107
  * compatibility with protocols (like SSH-1) written before OAEP's introduction.
108
  */
109
  define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
110
+ /**
111
+ * Do not use any padding
112
+ *
113
+ * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
114
+ * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
115
+ */
116
+ define('CRYPT_RSA_ENCRYPTION_NONE', 3);
117
  /**#@-*/
118
 
119
  /**#@+
120
  * @access public
121
+ * @see self::sign()
122
+ * @see self::verify()
123
+ * @see self::setHash()
124
  */
125
  /**
126
  * Use the Probabilistic Signature Scheme for signing
127
  *
128
  * Uses sha1 by default.
129
  *
130
+ * @see self::setSaltLength()
131
+ * @see self::setMGFHash()
132
  */
133
  define('CRYPT_RSA_SIGNATURE_PSS', 1);
134
  /**
142
 
143
  /**#@+
144
  * @access private
145
+ * @see self::createKey()
146
  */
147
  /**
148
  * ASN1 Integer
168
 
169
  /**#@+
170
  * @access private
171
+ * @see self::Crypt_RSA()
172
  */
173
  /**
174
  * To use the pure-PHP implementation
189
 
190
  /**#@+
191
  * @access public
192
+ * @see self::createKey()
193
+ * @see self::setPrivateKeyFormat()
194
  */
195
  /**
196
  * PKCS#1 formatted private key
209
  /**
210
  * PKCS#8 formatted private key
211
  */
212
+ define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 8);
213
  /**#@-*/
214
 
215
  /**#@+
216
  * @access public
217
+ * @see self::createKey()
218
+ * @see self::setPublicKeyFormat()
219
  */
220
  /**
221
  * Raw public key
282
  /**
283
  * Precomputed Zero
284
  *
285
+ * @var Math_BigInteger
286
  * @access private
287
  */
288
  var $zero;
290
  /**
291
  * Precomputed One
292
  *
293
+ * @var Math_BigInteger
294
  * @access private
295
  */
296
  var $one;
298
  /**
299
  * Private Key Format
300
  *
301
+ * @var int
302
  * @access private
303
  */
304
  var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1;
306
  /**
307
  * Public Key Format
308
  *
309
+ * @var int
310
  * @access public
311
  */
312
  var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8;
338
  /**
339
  * Primes for Chinese Remainder Theorem (ie. p and q)
340
  *
341
+ * @var array
342
  * @access private
343
  */
344
  var $primes;
346
  /**
347
  * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
348
  *
349
+ * @var array
350
  * @access private
351
  */
352
  var $exponents;
354
  /**
355
  * Coefficients for Chinese Remainder Theorem (ie. qInv)
356
  *
357
+ * @var array
358
  * @access private
359
  */
360
  var $coefficients;
362
  /**
363
  * Hash name
364
  *
365
+ * @var string
366
  * @access private
367
  */
368
  var $hashName;
378
  /**
379
  * Length of hash function output
380
  *
381
+ * @var int
382
  * @access private
383
  */
384
  var $hLen;
386
  /**
387
  * Length of salt
388
  *
389
+ * @var int
390
  * @access private
391
  */
392
  var $sLen;
402
  /**
403
  * Length of MGF hash function output
404
  *
405
+ * @var int
406
  * @access private
407
  */
408
  var $mgfHLen;
410
  /**
411
  * Encryption mode
412
  *
413
+ * @var int
414
  * @access private
415
  */
416
  var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP;
418
  /**
419
  * Signature mode
420
  *
421
+ * @var int
422
  * @access private
423
  */
424
  var $signatureMode = CRYPT_RSA_SIGNATURE_PSS;
426
  /**
427
  * Public Exponent
428
  *
429
+ * @var mixed
430
  * @access private
431
  */
432
  var $publicExponent = false;
434
  /**
435
  * Password
436
  *
437
+ * @var string
438
  * @access private
439
  */
440
  var $password = false;
445
  * For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions -
446
  * because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't.
447
  *
448
+ * @see self::_start_element_handler()
449
+ * @var array
450
  * @access private
451
  */
452
  var $components = array();
456
  *
457
  * For use with parsing XML formatted keys.
458
  *
459
+ * @see self::_character_handler()
460
+ * @see self::_stop_element_handler()
461
+ * @var mixed
462
  * @access private
463
  */
464
  var $current;
467
  * OpenSSL configuration file name.
468
  *
469
  * Set to null to use system configuration file.
470
+ * @see self::createKey()
471
+ * @var mixed
472
  * @Access public
473
  */
474
  var $configFile;
476
  /**
477
  * Public key comment field.
478
  *
479
+ * @var string
480
  * @access private
481
  */
482
  var $comment = 'phpseclib-generated-key';
491
  * @return Crypt_RSA
492
  * @access public
493
  */
494
+ function __construct()
495
  {
496
  if (!class_exists('Math_BigInteger')) {
497
  include_once 'Math/BigInteger.php';
499
 
500
  $this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
501
 
502
+ if (!defined('CRYPT_RSA_MODE')) {
503
  switch (true) {
504
  // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
505
  // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
539
  case !isset($versions['Header']):
540
  case !isset($versions['Library']):
541
  case $versions['Header'] == $versions['Library']:
542
+ case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
543
  define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
544
  break;
545
  default:
562
  $this->mgfHLen = $this->mgfHash->getLength();
563
  }
564
 
565
+ /**
566
+ * PHP4 compatible Default Constructor.
567
+ *
568
+ * @see self::__construct()
569
+ * @access public
570
+ */
571
+ function Crypt_RSA()
572
+ {
573
+ $this->__construct();
574
+ }
575
+
576
  /**
577
  * Create public / private key pair
578
  *
583
  * Will need to be passed back to Crypt_RSA::createKey() as the third parameter for further processing.
584
  *
585
  * @access public
586
+ * @param int $bits
587
+ * @param int $timeout
588
+ * @param Math_BigInteger $p
589
  */
590
  function createKey($bits = 1024, $timeout = false, $partial = array())
591
  {
604
  }
605
 
606
  // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
607
+ if (CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
608
  $config = array();
609
  if (isset($this->configFile)) {
610
  $config['config'] = $this->configFile;
618
  $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
619
 
620
  // clear the buffer of error strings stemming from a minimalistic openssl.cnf
621
+ while (openssl_error_string() !== false) {
622
+ }
623
 
624
  return array(
625
  'privatekey' => $privatekey,
763
  * Convert a private key to the appropriate format.
764
  *
765
  * @access private
766
+ * @see self::setPrivateKeyFormat()
767
+ * @param string $RSAPrivateKey
768
+ * @return string
769
  */
770
  function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
771
  {
809
  $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
810
  $key.= $encryption;
811
  $key.= "\r\nComment: " . $this->comment . "\r\n";
812
+ $public = pack(
813
+ 'Na*Na*Na*',
814
+ strlen('ssh-rsa'),
815
+ 'ssh-rsa',
816
+ strlen($raw['publicExponent']),
817
+ $raw['publicExponent'],
818
+ strlen($raw['modulus']),
819
+ $raw['modulus']
820
  );
821
+ $source = pack(
822
+ 'Na*Na*Na*Na*',
823
+ strlen('ssh-rsa'),
824
+ 'ssh-rsa',
825
+ strlen($encryption),
826
+ $encryption,
827
+ strlen($this->comment),
828
+ $this->comment,
829
+ strlen($public),
830
+ $public
831
  );
832
  $public = base64_encode($public);
833
  $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
834
  $key.= chunk_split($public, 64);
835
+ $private = pack(
836
+ 'Na*Na*Na*Na*',
837
+ strlen($raw['privateExponent']),
838
+ $raw['privateExponent'],
839
+ strlen($raw['prime1']),
840
+ $raw['prime1'],
841
+ strlen($raw['prime2']),
842
+ $raw['prime2'],
843
+ strlen($raw['coefficient']),
844
+ $raw['coefficient']
845
  );
846
  if (empty($this->password) && !is_string($this->password)) {
847
  $source.= pack('Na*', strlen($private), $private);
908
 
909
  if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
910
  $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
911
+ $RSAPrivateKey = pack(
912
+ 'Ca*a*Ca*a*',
913
+ CRYPT_RSA_ASN1_INTEGER,
914
+ "\01\00",
915
+ $rsaOID,
916
+ 4,
917
+ $this->_encodeLength(strlen($RSAPrivateKey)),
918
+ $RSAPrivateKey
919
  );
920
  $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
921
  if (!empty($this->password) || is_string($this->password)) {
929
  $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
930
  $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
931
 
932
+ $parameters = pack(
933
+ 'Ca*a*Ca*N',
934
+ CRYPT_RSA_ASN1_OCTETSTRING,
935
+ $this->_encodeLength(strlen($salt)),
936
+ $salt,
937
+ CRYPT_RSA_ASN1_INTEGER,
938
+ $this->_encodeLength(4),
939
+ $iterationCount
940
  );
941
  $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
942
 
943
+ $encryptionAlgorithm = pack(
944
+ 'Ca*a*Ca*a*',
945
+ CRYPT_RSA_ASN1_OBJECT,
946
+ $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
947
+ $pbeWithMD5AndDES_CBC,
948
+ CRYPT_RSA_ASN1_SEQUENCE,
949
+ $this->_encodeLength(strlen($parameters)),
950
+ $parameters
951
  );
952
 
953
+ $RSAPrivateKey = pack(
954
+ 'Ca*a*Ca*a*',
955
+ CRYPT_RSA_ASN1_SEQUENCE,
956
+ $this->_encodeLength(strlen($encryptionAlgorithm)),
957
+ $encryptionAlgorithm,
958
+ CRYPT_RSA_ASN1_OCTETSTRING,
959
+ $this->_encodeLength(strlen($RSAPrivateKey)),
960
+ $RSAPrivateKey
961
  );
962
 
963
  $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
1004
  * Convert a public key to the appropriate format
1005
  *
1006
  * @access private
1007
+ * @see self::setPublicKeyFormat()
1008
+ * @param string $RSAPrivateKey
1009
+ * @return string
1010
  */
1011
  function _convertPublicKey($n, $e)
1012
  {
1044
  'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
1045
  );
1046
 
1047
+ $RSAPublicKey = pack(
1048
+ 'Ca*a*a*',
1049
+ CRYPT_RSA_ASN1_SEQUENCE,
1050
+ $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
1051
+ $components['modulus'],
1052
+ $components['publicExponent']
1053
  );
1054
 
1055
  if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
1062
  $RSAPublicKey = chr(0) . $RSAPublicKey;
1063
  $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
1064
 
1065
+ $RSAPublicKey = pack(
1066
+ 'Ca*a*',
1067
+ CRYPT_RSA_ASN1_SEQUENCE,
1068
+ $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)),
1069
+ $rsaOID . $RSAPublicKey
1070
  );
1071
 
1072
  $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
1082
  * Break a public or private key down into its constituant components
1083
  *
1084
  * @access private
1085
+ * @see self::_convertPublicKey()
1086
+ * @see self::_convertPrivateKey()
1087
+ * @param string $key
1088
+ * @param int $type
1089
+ * @return array
1090
  */
1091
  function _parseKey($key, $type)
1092
  {
1502
  * More specifically, this returns the size of the modulo in bits.
1503
  *
1504
  * @access public
1505
+ * @return int
1506
  */
1507
  function getSize()
1508
  {
1515
  * Called by xml_set_element_handler()
1516
  *
1517
  * @access private
1518
+ * @param resource $parser
1519
+ * @param string $name
1520
+ * @param array $attribs
1521
  */
1522
  function _start_element_handler($parser, $name, $attribs)
1523
  {
1556
  * Called by xml_set_element_handler()
1557
  *
1558
  * @access private
1559
+ * @param resource $parser
1560
+ * @param string $name
1561
  */
1562
  function _stop_element_handler($parser, $name)
1563
  {
1573
  * Called by xml_set_character_data_handler()
1574
  *
1575
  * @access private
1576
+ * @param resource $parser
1577
+ * @param string $data
1578
  */
1579
  function _data_handler($parser, $data)
1580
  {
1590
  * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
1591
  *
1592
  * @access public
1593
+ * @param string $key
1594
+ * @param int $type optional
1595
  */
1596
  function loadKey($key, $type = false)
1597
  {
1656
  break;
1657
  }
1658
  }
 
1659
  } else {
1660
  $components = $this->_parseKey($key, $type);
1661
  }
1662
 
1663
  if ($components === false) {
1664
+ $this->comment = null;
1665
+ $this->modulus = null;
1666
+ $this->k = null;
1667
+ $this->exponent = null;
1668
+ $this->primes = null;
1669
+ $this->exponents = null;
1670
+ $this->coefficients = null;
1671
+ $this->publicExponent = null;
1672
+
1673
  return false;
1674
  }
1675
 
1713
  * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false.
1714
  * Or rather, pass in $password such that empty($password) && !is_string($password) is true.
1715
  *
1716
+ * @see self::createKey()
1717
+ * @see self::loadKey()
1718
  * @access public
1719
+ * @param string $password
1720
  */
1721
  function setPassword($password = false)
1722
  {
1738
  *
1739
  * Returns true on success, false on failure
1740
  *
1741
+ * @see self::getPublicKey()
1742
  * @access public
1743
+ * @param string $key optional
1744
+ * @param int $type optional
1745
+ * @return bool
1746
  */
1747
  function setPublicKey($key = false, $type = false)
1748
  {
1798
  *
1799
  * Returns true on success, false on failure
1800
  *
1801
+ * @see self::getPublicKey()
1802
  * @access public
1803
+ * @param string $key optional
1804
+ * @param int $type optional
1805
+ * @return bool
1806
  */
1807
  function setPrivateKey($key = false, $type = false)
1808
  {
1809
  if ($key === false && !empty($this->publicExponent)) {
1810
+ $this->publicExponent = false;
1811
  return true;
1812
  }
1813
 
1815
  if (!$rsa->loadKey($key, $type)) {
1816
  return false;
1817
  }
1818
+ $rsa->publicExponent = false;
1819
 
1820
  // don't overwrite the old key if the new key is invalid
1821
  $this->loadKey($rsa);
1829
  * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this
1830
  * function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
1831
  *
1832
+ * @see self::getPublicKey()
1833
  * @access public
1834
+ * @param string $key
1835
+ * @param int $type optional
1836
  */
1837
  function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1838
  {
1855
  * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
1856
  *
1857
  * @access public
1858
+ * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
1859
  * for invalid values.
1860
+ * @return mixed
1861
  */
1862
+ function getPublicKeyFingerprint($algorithm = 'md5')
1863
  {
1864
  if (empty($this->modulus) || empty($this->publicExponent)) {
1865
  return false;
1870
 
1871
  $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
1872
 
1873
+ switch ($algorithm) {
 
1874
  case 'sha256':
1875
  $hash = new Crypt_Hash('sha256');
1876
  $base = base64_encode($hash->hash($RSAPublicKey));
1880
  default:
1881
  return false;
1882
  }
 
1883
  }
1884
 
1885
  /**
1887
  *
1888
  * The private key is only returned if the currently loaded key contains the constituent prime numbers.
1889
  *
1890
+ * @see self::getPublicKey()
1891
  * @access public
1892
+ * @param string $key
1893
+ * @param int $type optional
1894
+ * @return mixed
1895
  */
1896
  function getPrivateKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
1897
  {
1912
  * Returns the private key without the prime number constituants. Structurally identical to a public key that
1913
  * hasn't been set as the public key
1914
  *
1915
+ * @see self::getPrivateKey()
1916
  * @access private
1917
+ * @param string $key
1918
+ * @param int $type optional
1919
  */
1920
  function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
1921
  {
1934
  * __toString() magic method
1935
  *
1936
  * @access public
1937
+ * @return string
1938
  */
1939
  function __toString()
1940
  {
1950
  * __clone() magic method
1951
  *
1952
  * @access public
1953
+ * @return Crypt_RSA
1954
  */
1955
  function __clone()
1956
  {
1963
  * Generates the smallest and largest numbers requiring $bits bits
1964
  *
1965
  * @access private
1966
+ * @param int $bits
1967
+ * @return array
1968
  */
1969
  function _generateMinMax($bits)
1970
  {
1992
  * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
1993
  *
1994
  * @access private
1995
+ * @param string $string
1996
+ * @return int
1997
  */
1998
  function _decodeLength(&$string)
1999
  {
2000
  $length = ord($this->_string_shift($string));
2001
+ if ($length & 0x80) { // definite length, long form
2002
  $length&= 0x7F;
2003
  $temp = $this->_string_shift($string, $length);
2004
  list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
2013
  * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
2014
  *
2015
  * @access private
2016
+ * @param int $length
2017
+ * @return string
2018
  */
2019
  function _encodeLength($length)
2020
  {
2031
  *
2032
  * Inspired by array_shift
2033
  *
2034
+ * @param string $string
2035
+ * @param int $index
2036
+ * @return string
2037
  * @access private
2038
  */
2039
  function _string_shift(&$string, $index = 1)
2046
  /**
2047
  * Determines the private key format
2048
  *
2049
+ * @see self::createKey()
2050
  * @access public
2051
+ * @param int $format
2052
  */
2053
  function setPrivateKeyFormat($format)
2054
  {
2058
  /**
2059
  * Determines the public key format
2060
  *
2061
+ * @see self::createKey()
2062
  * @access public
2063
+ * @param int $format
2064
  */
2065
  function setPublicKeyFormat($format)
2066
  {
2074
  * decryption. If $hash isn't supported, sha1 is used.
2075
  *
2076
  * @access public
2077
+ * @param string $hash
2078
  */
2079
  function setHash($hash)
2080
  {
2103
  * best if Hash and MGFHash are set to the same thing this is not a requirement.
2104
  *
2105
  * @access public
2106
+ * @param string $hash
2107
  */
2108
  function setMGFHash($hash)
2109
  {
2132
  * of the hash function Hash) and 0.
2133
  *
2134
  * @access public
2135
+ * @param int $format
2136
  */
2137
  function setSaltLength($sLen)
2138
  {
2146
  *
2147
  * @access private
2148
  * @param Math_BigInteger $x
2149
+ * @param int $xLen
2150
+ * @return string
2151
  */
2152
  function _i2osp($x, $xLen)
2153
  {
2165
  * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
2166
  *
2167
  * @access private
2168
+ * @param string $x
2169
  * @return Math_BigInteger
2170
  */
2171
  function _os2ip($x)
2184
  */
2185
  function _exponentiate($x)
2186
  {
2187
+ switch (true) {
2188
+ case empty($this->primes):
2189
+ case $this->primes[1]->equals($this->zero):
2190
+ case empty($this->coefficients):
2191
+ case $this->coefficients[2]->equals($this->zero):
2192
+ case empty($this->exponents):
2193
+ case $this->exponents[1]->equals($this->zero):
2194
+ return $x->modPow($this->exponent, $this->modulus);
2195
  }
2196
 
2197
  $num_primes = count($this->primes);
2265
  * @access private
2266
  * @param Math_BigInteger $x
2267
  * @param Math_BigInteger $r
2268
+ * @param int $i
2269
  * @return Math_BigInteger
2270
  */
2271
  function _blind($x, $r, $i)
2290
  * Thanks for the heads up singpolyma!
2291
  *
2292
  * @access private
2293
+ * @param string $x
2294
+ * @param string $y
2295
+ * @return bool
2296
  */
2297
  function _equals($x, $y)
2298
  {
2386
  * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
2387
  *
2388
  * @access private
2389
+ * @param string $mgfSeed
2390
+ * @param int $mgfLen
2391
+ * @return string
2392
  */
2393
  function _mgf1($mgfSeed, $maskLen)
2394
  {
2411
  * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
2412
  *
2413
  * @access private
2414
+ * @param string $m
2415
+ * @param string $l
2416
+ * @return string
2417
  */
2418
  function _rsaes_oaep_encrypt($m, $l = '')
2419
  {
2474
  * this document.
2475
  *
2476
  * @access private
2477
+ * @param string $c
2478
+ * @param string $l
2479
+ * @return string
2480
  */
2481
  function _rsaes_oaep_decrypt($c, $l = '')
2482
  {
2512
  $db = $maskedDB ^ $dbMask;
2513
  $lHash2 = substr($db, 0, $this->hLen);
2514
  $m = substr($db, $this->hLen);
2515
+ if (!$this->_equals($lHash, $lHash2)) {
2516
  user_error('Decryption error');
2517
  return false;
2518
  }
2527
  return substr($m, 1);
2528
  }
2529
 
2530
+ /**
2531
+ * Raw Encryption / Decryption
2532
+ *
2533
+ * Doesn't use padding and is not recommended.
2534
+ *
2535
+ * @access private
2536
+ * @param string $m
2537
+ * @return string
2538
+ */
2539
+ function _raw_encrypt($m)
2540
+ {
2541
+ $temp = $this->_os2ip($m);
2542
+ $temp = $this->_rsaep($temp);
2543
+ return $this->_i2osp($temp, $this->k);
2544
+ }
2545
+
2546
  /**
2547
  * RSAES-PKCS1-V1_5-ENCRYPT
2548
  *
2549
  * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
2550
  *
2551
  * @access private
2552
+ * @param string $m
2553
+ * @return string
2554
  */
2555
  function _rsaes_pkcs1_v1_5_encrypt($m)
2556
  {
2608
  * not private key encrypted ciphertext's.
2609
  *
2610
  * @access private
2611
+ * @param string $c
2612
+ * @return string
2613
  */
2614
  function _rsaes_pkcs1_v1_5_decrypt($c)
2615
  {
2657
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
2658
  *
2659
  * @access private
2660
+ * @param string $m
2661
+ * @param int $emBits
2662
  */
2663
  function _emsa_pss_encode($m, $emBits)
2664
  {
2666
  // be output.
2667
 
2668
  $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
2669
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
2670
 
2671
  $mHash = $this->hash->hash($m);
2672
  if ($emLen < $this->hLen + $sLen + 2) {
2693
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
2694
  *
2695
  * @access private
2696
+ * @param string $m
2697
+ * @param string $em
2698
+ * @param int $emBits
2699
+ * @return string
2700
  */
2701
  function _emsa_pss_verify($m, $em, $emBits)
2702
  {
2704
  // be output.
2705
 
2706
  $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
2707
+ $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
2708
 
2709
  $mHash = $this->hash->hash($m);
2710
  if ($emLen < $this->hLen + $sLen + 2) {
2740
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
2741
  *
2742
  * @access private
2743
+ * @param string $m
2744
+ * @return string
2745
  */
2746
  function _rsassa_pss_sign($m)
2747
  {
2766
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
2767
  *
2768
  * @access private
2769
+ * @param string $m
2770
+ * @param string $s
2771
+ * @return string
2772
  */
2773
  function _rsassa_pss_verify($m, $s)
2774
  {
2806
  * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
2807
  *
2808
  * @access private
2809
+ * @param string $m
2810
+ * @param int $emLen
2811
+ * @return string
2812
  */
2813
  function _emsa_pkcs1_v1_5_encode($m, $emLen)
2814
  {
2858
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
2859
  *
2860
  * @access private
2861
+ * @param string $m
2862
+ * @return string
2863
  */
2864
  function _rsassa_pkcs1_v1_5_sign($m)
2865
  {
2888
  * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
2889
  *
2890
  * @access private
2891
+ * @param string $m
2892
+ * @return string
2893
  */
2894
  function _rsassa_pkcs1_v1_5_verify($m, $s)
2895
  {
2932
  * Valid values include CRYPT_RSA_ENCRYPTION_OAEP and CRYPT_RSA_ENCRYPTION_PKCS1.
2933
  *
2934
  * @access public
2935
+ * @param int $mode
2936
  */
2937
  function setEncryptionMode($mode)
2938
  {
2945
  * Valid values include CRYPT_RSA_SIGNATURE_PSS and CRYPT_RSA_SIGNATURE_PKCS1
2946
  *
2947
  * @access public
2948
+ * @param int $mode
2949
  */
2950
  function setSignatureMode($mode)
2951
  {
2956
  * Set public key comment.
2957
  *
2958
  * @access public
2959
+ * @param string $comment
2960
  */
2961
  function setComment($comment)
2962
  {
2967
  * Get public key comment.
2968
  *
2969
  * @access public
2970
+ * @return string
2971
  */
2972
  function getComment()
2973
  {
2981
  * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
2982
  * be concatenated together.
2983
  *
2984
+ * @see self::decrypt()
2985
  * @access public
2986
+ * @param string $plaintext
2987
+ * @return string
2988
  */
2989
  function encrypt($plaintext)
2990
  {
2991
  switch ($this->encryptionMode) {
2992
+ case CRYPT_RSA_ENCRYPTION_NONE:
2993
+ $plaintext = str_split($plaintext, $this->k);
2994
+ $ciphertext = '';
2995
+ foreach ($plaintext as $m) {
2996
+ $ciphertext.= $this->_raw_encrypt($m);
2997
+ }
2998
+ return $ciphertext;
2999
  case CRYPT_RSA_ENCRYPTION_PKCS1:
3000
  $length = $this->k - 11;
3001
  if ($length <= 0) {
3027
  /**
3028
  * Decryption
3029
  *
3030
+ * @see self::encrypt()
3031
  * @access public
3032
+ * @param string $plaintext
3033
+ * @return string
3034
  */
3035
  function decrypt($ciphertext)
3036
  {
3044
  $plaintext = '';
3045
 
3046
  switch ($this->encryptionMode) {
3047
+ case CRYPT_RSA_ENCRYPTION_NONE:
3048
+ $decrypt = '_raw_encrypt';
3049
+ break;
3050
  case CRYPT_RSA_ENCRYPTION_PKCS1:
3051
  $decrypt = '_rsaes_pkcs1_v1_5_decrypt';
3052
  break;
3069
  /**
3070
  * Create a signature
3071
  *
3072
+ * @see self::verify()
3073
  * @access public
3074
+ * @param string $message
3075
+ * @return string
3076
  */
3077
  function sign($message)
3078
  {
3092
  /**
3093
  * Verifies a signature
3094
  *
3095
+ * @see self::sign()
3096
  * @access public
3097
+ * @param string $message
3098
+ * @param string $signature
3099
+ * @return bool
3100
  */
3101
  function verify($message, $signature)
3102
  {
3117
  * Extract raw BER from Base64 encoding
3118
  *
3119
  * @access private
3120
+ * @param string $str
3121
+ * @return string
3122
  */
3123
  function _extractBER($str)
3124
  {
3131
  * subject=/O=organization/OU=org unit/CN=common name
3132
  * issuer=/O=organization/CN=common name
3133
  */
3134
+ $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
3135
  // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
3136
  $temp = preg_replace('#-+[^-]+-+#', '', $temp);
3137
  // remove new lines
phpseclib/Crypt/Random.php CHANGED
@@ -61,17 +61,16 @@ if (!function_exists('crypt_random_string')) {
61
  * microoptimizations because this function has the potential of being called a huge number of times.
62
  * eg. for RSA key generation.
63
  *
64
- * @param Integer $length
65
- * @return String
66
  * @access public
67
  */
68
  function crypt_random_string($length)
69
  {
70
  if (CRYPT_RANDOM_IS_WINDOWS) {
71
- // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
72
- // ie. class_alias is a function that was introduced in PHP 5.3
73
- if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
74
- return mcrypt_create_iv($length);
75
  }
76
  // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
77
  // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
@@ -86,12 +85,12 @@ if (!function_exists('crypt_random_string')) {
86
  // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
87
  //
88
  // we're calling it, all the same, in the off chance that the mcrypt extension is not available
89
- if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
90
  return openssl_random_pseudo_bytes($length);
91
  }
92
  } else {
93
  // method 1. the fastest
94
- if (function_exists('openssl_random_pseudo_bytes')) {
95
  return openssl_random_pseudo_bytes($length);
96
  }
97
  // method 2
@@ -109,8 +108,8 @@ if (!function_exists('crypt_random_string')) {
109
  // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
110
  // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
111
  // restrictions or some such
112
- if (function_exists('mcrypt_create_iv')) {
113
- return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
114
  }
115
  }
116
  // at this point we have no choice but to use a pure-PHP CSPRNG
@@ -149,13 +148,13 @@ if (!function_exists('crypt_random_string')) {
149
  session_start();
150
 
151
  $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
152
- serialize($_SERVER) .
153
- serialize($_POST) .
154
- serialize($_GET) .
155
- serialize($_COOKIE) .
156
- serialize($GLOBALS) .
157
- serialize($_SESSION) .
158
- serialize($_OLD_SESSION)
159
  ));
160
  if (!isset($_SESSION['count'])) {
161
  $_SESSION['count'] = 0;
@@ -171,9 +170,9 @@ if (!function_exists('crypt_random_string')) {
171
  ini_set('session.use_cookies', $old_use_cookies);
172
  session_cache_limiter($old_session_cache_limiter);
173
  } else {
174
- if ($_OLD_SESSION !== false) {
175
- $_SESSION = $_OLD_SESSION;
176
- unset($_OLD_SESSION);
177
  } else {
178
  unset($_SESSION);
179
  }
@@ -261,6 +260,41 @@ if (!function_exists('crypt_random_string')) {
261
  }
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  if (!function_exists('phpseclib_resolve_include_path')) {
265
  /**
266
  * Resolve filename against the include path.
@@ -269,7 +303,7 @@ if (!function_exists('phpseclib_resolve_include_path')) {
269
  * PHP 5.3.2) with fallback implementation for earlier PHP versions.
270
  *
271
  * @param string $filename
272
- * @return mixed Filename (string) on success, false otherwise.
273
  * @access public
274
  */
275
  function phpseclib_resolve_include_path($filename)
61
  * microoptimizations because this function has the potential of being called a huge number of times.
62
  * eg. for RSA key generation.
63
  *
64
+ * @param int $length
65
+ * @return string
66
  * @access public
67
  */
68
  function crypt_random_string($length)
69
  {
70
  if (CRYPT_RANDOM_IS_WINDOWS) {
71
+ // method 1. prior to PHP 5.3, mcrypt_create_iv() would call rand() on windows
72
+ if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
73
+ return @mcrypt_create_iv($length);
 
74
  }
75
  // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
76
  // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
85
  // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
86
  //
87
  // we're calling it, all the same, in the off chance that the mcrypt extension is not available
88
+ if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
89
  return openssl_random_pseudo_bytes($length);
90
  }
91
  } else {
92
  // method 1. the fastest
93
+ if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) {
94
  return openssl_random_pseudo_bytes($length);
95
  }
96
  // method 2
108
  // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
109
  // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
110
  // restrictions or some such
111
+ if (extension_loaded('mcrypt')) {
112
+ return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
113
  }
114
  }
115
  // at this point we have no choice but to use a pure-PHP CSPRNG
148
  session_start();
149
 
150
  $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
151
+ (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') .
152
+ (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') .
153
+ (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') .
154
+ (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') .
155
+ phpseclib_safe_serialize($GLOBALS) .
156
+ phpseclib_safe_serialize($_SESSION) .
157
+ phpseclib_safe_serialize($_OLD_SESSION)
158
  ));
159
  if (!isset($_SESSION['count'])) {
160
  $_SESSION['count'] = 0;
170
  ini_set('session.use_cookies', $old_use_cookies);
171
  session_cache_limiter($old_session_cache_limiter);
172
  } else {
173
+ if ($_OLD_SESSION !== false) {
174
+ $_SESSION = $_OLD_SESSION;
175
+ unset($_OLD_SESSION);
176
  } else {
177
  unset($_SESSION);
178
  }
260
  }
261
  }
262
 
263
+ if (!function_exists('phpseclib_safe_serialize')) {
264
+ /**
265
+ * Safely serialize variables
266
+ *
267
+ * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier.
268
+ * PHP 5.3 will emit a warning.
269
+ *
270
+ * @param mixed $arr
271
+ * @access public
272
+ */
273
+ function phpseclib_safe_serialize(&$arr)
274
+ {
275
+ if (is_object($arr)) {
276
+ return '';
277
+ }
278
+ if (!is_array($arr)) {
279
+ return serialize($arr);
280
+ }
281
+ // prevent circular array recursion
282
+ if (isset($arr['__phpseclib_marker'])) {
283
+ return '';
284
+ }
285
+ $safearr = array();
286
+ $arr['__phpseclib_marker'] = true;
287
+ foreach (array_keys($arr) as $key) {
288
+ // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
289
+ if ($key !== '__phpseclib_marker') {
290
+ $safearr[$key] = phpseclib_safe_serialize($arr[$key]);
291
+ }
292
+ }
293
+ unset($arr['__phpseclib_marker']);
294
+ return serialize($safearr);
295
+ }
296
+ }
297
+
298
  if (!function_exists('phpseclib_resolve_include_path')) {
299
  /**
300
  * Resolve filename against the include path.
303
  * PHP 5.3.2) with fallback implementation for earlier PHP versions.
304
  *
305
  * @param string $filename
306
+ * @return string|false
307
  * @access public
308
  */
309
  function phpseclib_resolve_include_path($filename)
phpseclib/Crypt/Rijndael.php CHANGED
@@ -7,11 +7,11 @@
7
  *
8
  * PHP versions 4 and 5
9
  *
10
- * If {@link Crypt_Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
11
- * {@link Crypt_Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12
- * {@link Crypt_Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
13
  * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14
- * {@link Crypt_Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated.
15
  *
16
  * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
17
  * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
@@ -81,8 +81,8 @@ if (!class_exists('Crypt_Base')) {
81
 
82
  /**#@+
83
  * @access public
84
- * @see Crypt_Rijndael::encrypt()
85
- * @see Crypt_Rijndael::decrypt()
86
  */
87
  /**
88
  * Encrypt / decrypt using the Counter mode.
@@ -127,21 +127,11 @@ define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
127
  */
128
  class Crypt_Rijndael extends Crypt_Base
129
  {
130
- /**
131
- * The default password key_size used by setPassword()
132
- *
133
- * @see Crypt_Base::password_key_size
134
- * @see Crypt_Base::setPassword()
135
- * @var Integer
136
- * @access private
137
- */
138
- var $password_key_size = 16;
139
-
140
  /**
141
  * The namespace used by the cipher for its constants.
142
  *
143
  * @see Crypt_Base::const_namespace
144
- * @var String
145
  * @access private
146
  */
147
  var $const_namespace = 'RIJNDAEL';
@@ -149,15 +139,15 @@ class Crypt_Rijndael extends Crypt_Base
149
  /**
150
  * The mcrypt specific name of the cipher
151
  *
152
- * Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not.
153
  * Crypt_Rijndael determines automatically whether mcrypt is useable
154
- * or not for the current $block_size/$key_size.
155
  * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
156
  *
157
  * @see Crypt_Base::cipher_name_mcrypt
158
  * @see Crypt_Base::engine
159
- * @see isValidEngine()
160
- * @var String
161
  * @access private
162
  */
163
  var $cipher_name_mcrypt = 'rijndael-128';
@@ -167,25 +157,16 @@ class Crypt_Rijndael extends Crypt_Base
167
  *
168
  * @see Crypt_Base::password_default_salt
169
  * @see Crypt_Base::setPassword()
170
- * @var String
171
  * @access private
172
  */
173
  var $password_default_salt = 'phpseclib';
174
 
175
- /**
176
- * Has the key length explicitly been set or should it be derived from the key, itself?
177
- *
178
- * @see setKeyLength()
179
- * @var Boolean
180
- * @access private
181
- */
182
- var $explicit_key_length = false;
183
-
184
  /**
185
  * The Key Schedule
186
  *
187
- * @see _setup()
188
- * @var Array
189
  * @access private
190
  */
191
  var $w;
@@ -193,8 +174,8 @@ class Crypt_Rijndael extends Crypt_Base
193
  /**
194
  * The Inverse Key Schedule
195
  *
196
- * @see _setup()
197
- * @var Array
198
  * @access private
199
  */
200
  var $dw;
@@ -202,8 +183,8 @@ class Crypt_Rijndael extends Crypt_Base
202
  /**
203
  * The Block Length divided by 32
204
  *
205
- * @see setBlockLength()
206
- * @var Integer
207
  * @access private
208
  * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
209
  * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
@@ -213,23 +194,23 @@ class Crypt_Rijndael extends Crypt_Base
213
  var $Nb = 4;
214
 
215
  /**
216
- * The Key Length
217
  *
218
- * @see setKeyLength()
219
- * @var Integer
220
  * @access private
221
  * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
222
- * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
223
- * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
224
  * of that, we'll just precompute it once.
225
  */
226
- var $key_size = 16;
227
 
228
  /**
229
  * The Key Length divided by 32
230
  *
231
- * @see setKeyLength()
232
- * @var Integer
233
  * @access private
234
  * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
235
  */
@@ -238,7 +219,7 @@ class Crypt_Rijndael extends Crypt_Base
238
  /**
239
  * The Number of Rounds
240
  *
241
- * @var Integer
242
  * @access private
243
  * @internal The max value is 14, the min value is 10.
244
  */
@@ -247,7 +228,7 @@ class Crypt_Rijndael extends Crypt_Base
247
  /**
248
  * Shift offsets
249
  *
250
- * @var Array
251
  * @access private
252
  */
253
  var $c;
@@ -255,39 +236,11 @@ class Crypt_Rijndael extends Crypt_Base
255
  /**
256
  * Holds the last used key- and block_size information
257
  *
258
- * @var Array
259
  * @access private
260
  */
261
  var $kl;
262
 
263
- /**
264
- * Default Constructor.
265
- *
266
- * Determines whether or not the mcrypt extension should be used.
267
- *
268
- * $mode could be:
269
- *
270
- * - CRYPT_RIJNDAEL_MODE_ECB
271
- *
272
- * - CRYPT_RIJNDAEL_MODE_CBC
273
- *
274
- * - CRYPT_RIJNDAEL_MODE_CTR
275
- *
276
- * - CRYPT_RIJNDAEL_MODE_CFB
277
- *
278
- * - CRYPT_RIJNDAEL_MODE_OFB
279
- *
280
- * If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
281
- *
282
- * @see Crypt_Base::Crypt_Base()
283
- * @param optional Integer $mode
284
- * @access public
285
- */
286
- function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)
287
- {
288
- parent::Crypt_Base($mode);
289
- }
290
-
291
  /**
292
  * Sets the key.
293
  *
@@ -301,9 +254,9 @@ class Crypt_Rijndael extends Crypt_Base
301
  * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
302
  *
303
  * @see Crypt_Base:setKey()
304
- * @see setKeyLength()
305
  * @access public
306
- * @param String $key
307
  */
308
  function setKey($key)
309
  {
@@ -347,30 +300,28 @@ class Crypt_Rijndael extends Crypt_Base
347
  * This results then in slower encryption.
348
  *
349
  * @access public
350
- * @param Integer $length
351
  */
352
  function setKeyLength($length)
353
  {
354
  switch (true) {
355
- case $length == 160:
356
- $this->key_size = 20;
357
- break;
358
- case $length == 224:
359
- $this->key_size = 28;
360
- break;
361
  case $length <= 128:
362
- $this->key_size = 16;
 
 
 
363
  break;
364
  case $length <= 192:
365
- $this->key_size = 24;
 
 
 
366
  break;
367
  default:
368
- $this->key_size = 32;
369
  }
370
 
371
- $this->explicit_key_length = true;
372
- $this->changed = true;
373
- $this->_setEngine();
374
  }
375
 
376
  /**
@@ -380,14 +331,14 @@ class Crypt_Rijndael extends Crypt_Base
380
  * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
381
  *
382
  * @access public
383
- * @param Integer $length
384
  */
385
  function setBlockLength($length)
386
  {
387
  $length >>= 5;
388
  if ($length > 8) {
389
  $length = 8;
390
- } else if ($length < 4) {
391
  $length = 4;
392
  }
393
  $this->Nb = $length;
@@ -402,9 +353,9 @@ class Crypt_Rijndael extends Crypt_Base
402
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
403
  *
404
  * @see Crypt_Base::Crypt_Base()
405
- * @param Integer $engine
406
  * @access public
407
- * @return Boolean
408
  */
409
  function isValidEngine($engine)
410
  {
@@ -413,12 +364,12 @@ class Crypt_Rijndael extends Crypt_Base
413
  if ($this->block_size != 16) {
414
  return false;
415
  }
416
- $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_size << 3) . '-ecb';
417
- $this->cipher_name_openssl = 'aes-' . ($this->key_size << 3) . '-' . $this->_openssl_translate_mode();
418
  break;
419
  case CRYPT_ENGINE_MCRYPT:
420
  $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
421
- if ($this->key_size % 8) { // is it a 160/224-bit key?
422
  // mcrypt is not usable for them, only for 128/192/256-bit keys
423
  return false;
424
  }
@@ -427,24 +378,12 @@ class Crypt_Rijndael extends Crypt_Base
427
  return parent::isValidEngine($engine);
428
  }
429
 
430
- /**
431
- * Setup the CRYPT_ENGINE_MCRYPT $engine
432
- *
433
- * @see Crypt_Base::_setupMcrypt()
434
- * @access private
435
- */
436
- function _setupMcrypt()
437
- {
438
- $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
439
- parent::_setupMcrypt();
440
- }
441
-
442
  /**
443
  * Encrypts a block
444
  *
445
  * @access private
446
- * @param String $in
447
- * @return String
448
  */
449
  function _encryptBlock($in)
450
  {
@@ -544,8 +483,8 @@ class Crypt_Rijndael extends Crypt_Base
544
  * Decrypts a block
545
  *
546
  * @access private
547
- * @param String $in
548
- * @return String
549
  */
550
  function _decryptBlock($in)
551
  {
@@ -649,15 +588,13 @@ class Crypt_Rijndael extends Crypt_Base
649
  0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
650
  );
651
 
652
- $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
653
-
654
- if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
655
  // already expanded
656
  return;
657
  }
658
- $this->kl = array('key' => $this->key, 'key_size' => $this->key_size, 'block_size' => $this->block_size);
659
 
660
- $this->Nk = $this->key_size >> 2;
661
  // see Rijndael-ammended.pdf#page=44
662
  $this->Nr = max($this->Nk, $this->Nb) + 6;
663
 
@@ -690,7 +627,7 @@ class Crypt_Rijndael extends Crypt_Base
690
  // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
691
  $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
692
  $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
693
- } else if ($this->Nk > 6 && $i % $this->Nk == 4) {
694
  $temp = $this->_subWord($temp);
695
  }
696
  $w[$i] = $w[$i - $this->Nk] ^ $temp;
@@ -749,13 +686,13 @@ class Crypt_Rijndael extends Crypt_Base
749
  * Performs S-Box substitutions
750
  *
751
  * @access private
752
- * @param Integer $word
753
  */
754
  function _subWord($word)
755
  {
756
  static $sbox;
757
  if (empty($sbox)) {
758
- list(,,,, $sbox) = $this->_getTables();
759
  }
760
 
761
  return $sbox[$word & 0x000000FF] |
@@ -771,7 +708,7 @@ class Crypt_Rijndael extends Crypt_Base
771
  * @see Crypt_Rijndael:_setupInlineCrypt()
772
  * @see Crypt_Rijndael:_subWord()
773
  * @access private
774
- * @return Array &$tables
775
  */
776
  function &_getTables()
777
  {
@@ -860,7 +797,7 @@ class Crypt_Rijndael extends Crypt_Base
860
  * @see Crypt_Rijndael:_setupInlineCrypt()
861
  * @see Crypt_Rijndael:_setupKey()
862
  * @access private
863
- * @return Array &$tables
864
  */
865
  function &_getInvTables()
866
  {
@@ -954,7 +891,7 @@ class Crypt_Rijndael extends Crypt_Base
954
  // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
955
  // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
956
  // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
957
- $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
958
 
959
  // Generation of a uniqe hash for our generated code
960
  $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
7
  *
8
  * PHP versions 4 and 5
9
  *
10
+ * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If
11
+ * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
12
+ * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's
13
  * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
14
+ * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
15
  *
16
  * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example,
17
  * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
81
 
82
  /**#@+
83
  * @access public
84
+ * @see self::encrypt()
85
+ * @see self::decrypt()
86
  */
87
  /**
88
  * Encrypt / decrypt using the Counter mode.
127
  */
128
  class Crypt_Rijndael extends Crypt_Base
129
  {
 
 
 
 
 
 
 
 
 
 
130
  /**
131
  * The namespace used by the cipher for its constants.
132
  *
133
  * @see Crypt_Base::const_namespace
134
+ * @var string
135
  * @access private
136
  */
137
  var $const_namespace = 'RIJNDAEL';
139
  /**
140
  * The mcrypt specific name of the cipher
141
  *
142
+ * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
143
  * Crypt_Rijndael determines automatically whether mcrypt is useable
144
+ * or not for the current $block_size/$key_length.
145
  * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
146
  *
147
  * @see Crypt_Base::cipher_name_mcrypt
148
  * @see Crypt_Base::engine
149
+ * @see self::isValidEngine()
150
+ * @var string
151
  * @access private
152
  */
153
  var $cipher_name_mcrypt = 'rijndael-128';
157
  *
158
  * @see Crypt_Base::password_default_salt
159
  * @see Crypt_Base::setPassword()
160
+ * @var string
161
  * @access private
162
  */
163
  var $password_default_salt = 'phpseclib';
164
 
 
 
 
 
 
 
 
 
 
165
  /**
166
  * The Key Schedule
167
  *
168
+ * @see self::_setup()
169
+ * @var array
170
  * @access private
171
  */
172
  var $w;
174
  /**
175
  * The Inverse Key Schedule
176
  *
177
+ * @see self::_setup()
178
+ * @var array
179
  * @access private
180
  */
181
  var $dw;
183
  /**
184
  * The Block Length divided by 32
185
  *
186
+ * @see self::setBlockLength()
187
+ * @var int
188
  * @access private
189
  * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
190
  * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
194
  var $Nb = 4;
195
 
196
  /**
197
+ * The Key Length (in bytes)
198
  *
199
+ * @see self::setKeyLength()
200
+ * @var int
201
  * @access private
202
  * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
203
+ * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
204
+ * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
205
  * of that, we'll just precompute it once.
206
  */
207
+ var $key_length = 16;
208
 
209
  /**
210
  * The Key Length divided by 32
211
  *
212
+ * @see self::setKeyLength()
213
+ * @var int
214
  * @access private
215
  * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
216
  */
219
  /**
220
  * The Number of Rounds
221
  *
222
+ * @var int
223
  * @access private
224
  * @internal The max value is 14, the min value is 10.
225
  */
228
  /**
229
  * Shift offsets
230
  *
231
+ * @var array
232
  * @access private
233
  */
234
  var $c;
236
  /**
237
  * Holds the last used key- and block_size information
238
  *
239
+ * @var array
240
  * @access private
241
  */
242
  var $kl;
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  /**
245
  * Sets the key.
246
  *
254
  * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
255
  *
256
  * @see Crypt_Base:setKey()
257
+ * @see self::setKeyLength()
258
  * @access public
259
+ * @param string $key
260
  */
261
  function setKey($key)
262
  {
300
  * This results then in slower encryption.
301
  *
302
  * @access public
303
+ * @param int $length
304
  */
305
  function setKeyLength($length)
306
  {
307
  switch (true) {
 
 
 
 
 
 
308
  case $length <= 128:
309
+ $this->key_length = 16;
310
+ break;
311
+ case $length <= 160:
312
+ $this->key_length = 20;
313
  break;
314
  case $length <= 192:
315
+ $this->key_length = 24;
316
+ break;
317
+ case $length <= 224:
318
+ $this->key_length = 28;
319
  break;
320
  default:
321
+ $this->key_length = 32;
322
  }
323
 
324
+ parent::setKeyLength($length);
 
 
325
  }
326
 
327
  /**
331
  * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
332
  *
333
  * @access public
334
+ * @param int $length
335
  */
336
  function setBlockLength($length)
337
  {
338
  $length >>= 5;
339
  if ($length > 8) {
340
  $length = 8;
341
+ } elseif ($length < 4) {
342
  $length = 4;
343
  }
344
  $this->Nb = $length;
353
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
354
  *
355
  * @see Crypt_Base::Crypt_Base()
356
+ * @param int $engine
357
  * @access public
358
+ * @return bool
359
  */
360
  function isValidEngine($engine)
361
  {
364
  if ($this->block_size != 16) {
365
  return false;
366
  }
367
+ $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
368
+ $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
369
  break;
370
  case CRYPT_ENGINE_MCRYPT:
371
  $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
372
+ if ($this->key_length % 8) { // is it a 160/224-bit key?
373
  // mcrypt is not usable for them, only for 128/192/256-bit keys
374
  return false;
375
  }
378
  return parent::isValidEngine($engine);
379
  }
380
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  /**
382
  * Encrypts a block
383
  *
384
  * @access private
385
+ * @param string $in
386
+ * @return string
387
  */
388
  function _encryptBlock($in)
389
  {
483
  * Decrypts a block
484
  *
485
  * @access private
486
+ * @param string $in
487
+ * @return string
488
  */
489
  function _decryptBlock($in)
490
  {
588
  0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
589
  );
590
 
591
+ if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
 
 
592
  // already expanded
593
  return;
594
  }
595
+ $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
596
 
597
+ $this->Nk = $this->key_length >> 2;
598
  // see Rijndael-ammended.pdf#page=44
599
  $this->Nr = max($this->Nk, $this->Nb) + 6;
600
 
627
  // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
628
  $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
629
  $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
630
+ } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
631
  $temp = $this->_subWord($temp);
632
  }
633
  $w[$i] = $w[$i - $this->Nk] ^ $temp;
686
  * Performs S-Box substitutions
687
  *
688
  * @access private
689
+ * @param int $word
690
  */
691
  function _subWord($word)
692
  {
693
  static $sbox;
694
  if (empty($sbox)) {
695
+ list(, , , , $sbox) = $this->_getTables();
696
  }
697
 
698
  return $sbox[$word & 0x000000FF] |
708
  * @see Crypt_Rijndael:_setupInlineCrypt()
709
  * @see Crypt_Rijndael:_subWord()
710
  * @access private
711
+ * @return array &$tables
712
  */
713
  function &_getTables()
714
  {
797
  * @see Crypt_Rijndael:_setupInlineCrypt()
798
  * @see Crypt_Rijndael:_setupKey()
799
  * @access private
800
+ * @return array &$tables
801
  */
802
  function &_getInvTables()
803
  {
891
  // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
892
  // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
893
  // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
894
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
895
 
896
  // Generation of a uniqe hash for our generated code
897
  $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
phpseclib/Crypt/TripleDES.php CHANGED
@@ -61,7 +61,7 @@ if (!class_exists('Crypt_DES')) {
61
 
62
  /**#@+
63
  * @access public
64
- * @see Crypt_TripleDES::Crypt_TripleDES()
65
  */
66
  /**
67
  * Encrypt / decrypt using inner chaining
@@ -95,22 +95,20 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
95
  class Crypt_TripleDES extends Crypt_DES
96
  {
97
  /**
98
- * The default password key_size used by setPassword()
99
  *
100
- * @see Crypt_DES::password_key_size
101
- * @see Crypt_Base::password_key_size
102
- * @see Crypt_Base::setPassword()
103
- * @var Integer
104
  * @access private
105
  */
106
- var $password_key_size = 24;
107
 
108
  /**
109
  * The default salt used by setPassword()
110
  *
111
  * @see Crypt_Base::password_default_salt
112
  * @see Crypt_Base::setPassword()
113
- * @var String
114
  * @access private
115
  */
116
  var $password_default_salt = 'phpseclib';
@@ -120,7 +118,7 @@ class Crypt_TripleDES extends Crypt_DES
120
  *
121
  * @see Crypt_DES::const_namespace
122
  * @see Crypt_Base::const_namespace
123
- * @var String
124
  * @access private
125
  */
126
  var $const_namespace = 'DES';
@@ -130,7 +128,7 @@ class Crypt_TripleDES extends Crypt_DES
130
  *
131
  * @see Crypt_DES::cipher_name_mcrypt
132
  * @see Crypt_Base::cipher_name_mcrypt
133
- * @var String
134
  * @access private
135
  */
136
  var $cipher_name_mcrypt = 'tripledes';
@@ -139,7 +137,7 @@ class Crypt_TripleDES extends Crypt_DES
139
  * Optimizing value while CFB-encrypting
140
  *
141
  * @see Crypt_Base::cfb_init_len
142
- * @var Integer
143
  * @access private
144
  */
145
  var $cfb_init_len = 750;
@@ -147,17 +145,17 @@ class Crypt_TripleDES extends Crypt_DES
147
  /**
148
  * max possible size of $key
149
  *
150
- * @see Crypt_TripleDES::setKey()
151
  * @see Crypt_DES::setKey()
152
- * @var String
153
  * @access private
154
  */
155
- var $key_size_max = 24;
156
 
157
  /**
158
  * Internal flag whether using CRYPT_DES_MODE_3CBC or not
159
  *
160
- * @var Boolean
161
  * @access private
162
  */
163
  var $mode_3cbc;
@@ -167,7 +165,7 @@ class Crypt_TripleDES extends Crypt_DES
167
  *
168
  * Used only if $mode_3cbc === true
169
  *
170
- * @var Array
171
  * @access private
172
  */
173
  var $des;
@@ -195,10 +193,10 @@ class Crypt_TripleDES extends Crypt_DES
195
  *
196
  * @see Crypt_DES::Crypt_DES()
197
  * @see Crypt_Base::Crypt_Base()
198
- * @param optional Integer $mode
199
  * @access public
200
  */
201
- function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
202
  {
203
  switch ($mode) {
204
  // In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
@@ -221,19 +219,31 @@ class Crypt_TripleDES extends Crypt_DES
221
  break;
222
  // If not 3CBC, we init as usual
223
  default:
224
- parent::Crypt_Base($mode);
225
  }
226
  }
227
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  /**
229
  * Test for engine validity
230
  *
231
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
232
  *
233
  * @see Crypt_Base::Crypt_Base()
234
- * @param Integer $engine
235
  * @access public
236
- * @return Boolean
237
  */
238
  function isValidEngine($engine)
239
  {
@@ -254,7 +264,7 @@ class Crypt_TripleDES extends Crypt_DES
254
  *
255
  * @see Crypt_Base::setIV()
256
  * @access public
257
- * @param String $iv
258
  */
259
  function setIV($iv)
260
  {
@@ -266,6 +276,32 @@ class Crypt_TripleDES extends Crypt_DES
266
  }
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  /**
270
  * Sets the key.
271
  *
@@ -279,11 +315,11 @@ class Crypt_TripleDES extends Crypt_DES
279
  * @access public
280
  * @see Crypt_DES::setKey()
281
  * @see Crypt_Base::setKey()
282
- * @param String $key
283
  */
284
  function setKey($key)
285
  {
286
- $length = strlen($key);
287
  if ($length > 8) {
288
  $key = str_pad(substr($key, 0, 24), 24, chr(0));
289
  // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
@@ -310,8 +346,8 @@ class Crypt_TripleDES extends Crypt_DES
310
  *
311
  * @see Crypt_Base::encrypt()
312
  * @access public
313
- * @param String $plaintext
314
- * @return String $cipertext
315
  */
316
  function encrypt($plaintext)
317
  {
@@ -337,8 +373,8 @@ class Crypt_TripleDES extends Crypt_DES
337
  *
338
  * @see Crypt_Base::decrypt()
339
  * @access public
340
- * @param String $ciphertext
341
- * @return String $plaintext
342
  */
343
  function decrypt($ciphertext)
344
  {
@@ -392,7 +428,7 @@ class Crypt_TripleDES extends Crypt_DES
392
  * however, they are also less intuitive and more likely to cause you problems.
393
  *
394
  * @see Crypt_Base::enableContinuousBuffer()
395
- * @see Crypt_TripleDES::disableContinuousBuffer()
396
  * @access public
397
  */
398
  function enableContinuousBuffer()
@@ -411,7 +447,7 @@ class Crypt_TripleDES extends Crypt_DES
411
  * The default behavior.
412
  *
413
  * @see Crypt_Base::disableContinuousBuffer()
414
- * @see Crypt_TripleDES::enableContinuousBuffer()
415
  * @access public
416
  */
417
  function disableContinuousBuffer()
@@ -464,9 +500,9 @@ class Crypt_TripleDES extends Crypt_DES
464
  *
465
  * @see Crypt_Base::Crypt_Base()
466
  * @see Crypt_Base::setPreferredEngine()
467
- * @param Integer $engine
468
  * @access public
469
- * @return Integer
470
  */
471
  function setPreferredEngine($engine)
472
  {
61
 
62
  /**#@+
63
  * @access public
64
+ * @see self::Crypt_TripleDES()
65
  */
66
  /**
67
  * Encrypt / decrypt using inner chaining
95
  class Crypt_TripleDES extends Crypt_DES
96
  {
97
  /**
98
+ * Key Length (in bytes)
99
  *
100
+ * @see Crypt_TripleDES::setKeyLength()
101
+ * @var int
 
 
102
  * @access private
103
  */
104
+ var $key_length = 24;
105
 
106
  /**
107
  * The default salt used by setPassword()
108
  *
109
  * @see Crypt_Base::password_default_salt
110
  * @see Crypt_Base::setPassword()
111
+ * @var string
112
  * @access private
113
  */
114
  var $password_default_salt = 'phpseclib';
118
  *
119
  * @see Crypt_DES::const_namespace
120
  * @see Crypt_Base::const_namespace
121
+ * @var string
122
  * @access private
123
  */
124
  var $const_namespace = 'DES';
128
  *
129
  * @see Crypt_DES::cipher_name_mcrypt
130
  * @see Crypt_Base::cipher_name_mcrypt
131
+ * @var string
132
  * @access private
133
  */
134
  var $cipher_name_mcrypt = 'tripledes';
137
  * Optimizing value while CFB-encrypting
138
  *
139
  * @see Crypt_Base::cfb_init_len
140
+ * @var int
141
  * @access private
142
  */
143
  var $cfb_init_len = 750;
145
  /**
146
  * max possible size of $key
147
  *
148
+ * @see self::setKey()
149
  * @see Crypt_DES::setKey()
150
+ * @var string
151
  * @access private
152
  */
153
+ var $key_length_max = 24;
154
 
155
  /**
156
  * Internal flag whether using CRYPT_DES_MODE_3CBC or not
157
  *
158
+ * @var bool
159
  * @access private
160
  */
161
  var $mode_3cbc;
165
  *
166
  * Used only if $mode_3cbc === true
167
  *
168
+ * @var array
169
  * @access private
170
  */
171
  var $des;
193
  *
194
  * @see Crypt_DES::Crypt_DES()
195
  * @see Crypt_Base::Crypt_Base()
196
+ * @param int $mode
197
  * @access public
198
  */
199
+ function __construct($mode = CRYPT_MODE_CBC)
200
  {
201
  switch ($mode) {
202
  // In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
219
  break;
220
  // If not 3CBC, we init as usual
221
  default:
222
+ parent::__construct($mode);
223
  }
224
  }
225
 
226
+ /**
227
+ * PHP4 compatible Default Constructor.
228
+ *
229
+ * @see self::__construct()
230
+ * @param int $mode
231
+ * @access public
232
+ */
233
+ function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
234
+ {
235
+ $this->__construct($mode);
236
+ }
237
+
238
  /**
239
  * Test for engine validity
240
  *
241
  * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
242
  *
243
  * @see Crypt_Base::Crypt_Base()
244
+ * @param int $engine
245
  * @access public
246
+ * @return bool
247
  */
248
  function isValidEngine($engine)
249
  {
264
  *
265
  * @see Crypt_Base::setIV()
266
  * @access public
267
+ * @param string $iv
268
  */
269
  function setIV($iv)
270
  {
276
  }
277
  }
278
 
279
+ /**
280
+ * Sets the key length.
281
+ *
282
+ * Valid key lengths are 64, 128 and 192
283
+ *
284
+ * @see Crypt_Base:setKeyLength()
285
+ * @access public
286
+ * @param int $length
287
+ */
288
+ function setKeyLength($length)
289
+ {
290
+ $length >>= 3;
291
+ switch (true) {
292
+ case $length <= 8:
293
+ $this->key_length = 8;
294
+ break;
295
+ case $length <= 16:
296
+ $this->key_length = 16;
297
+ break;
298
+ default:
299
+ $this->key_length = 24;
300
+ }
301
+
302
+ parent::setKeyLength($length);
303
+ }
304
+
305
  /**
306
  * Sets the key.
307
  *
315
  * @access public
316
  * @see Crypt_DES::setKey()
317
  * @see Crypt_Base::setKey()
318
+ * @param string $key
319
  */
320
  function setKey($key)
321
  {
322
+ $length = $this->explicit_key_length ? $this->key_length : strlen($key);
323
  if ($length > 8) {
324
  $key = str_pad(substr($key, 0, 24), 24, chr(0));
325
  // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
346
  *
347
  * @see Crypt_Base::encrypt()
348
  * @access public
349
+ * @param string $plaintext
350
+ * @return string $cipertext
351
  */
352
  function encrypt($plaintext)
353
  {
373
  *
374
  * @see Crypt_Base::decrypt()
375
  * @access public
376
+ * @param string $ciphertext
377
+ * @return string $plaintext
378
  */
379
  function decrypt($ciphertext)
380
  {
428
  * however, they are also less intuitive and more likely to cause you problems.
429
  *
430
  * @see Crypt_Base::enableContinuousBuffer()
431
+ * @see self::disableContinuousBuffer()
432
  * @access public
433
  */
434
  function enableContinuousBuffer()
447
  * The default behavior.
448
  *
449
  * @see Crypt_Base::disableContinuousBuffer()
450
+ * @see self::enableContinuousBuffer()
451
  * @access public
452
  */
453
  function disableContinuousBuffer()
500
  *
501
  * @see Crypt_Base::Crypt_Base()
502
  * @see Crypt_Base::setPreferredEngine()
503
+ * @param int $engine
504
  * @access public
505
+ * @return int
506
  */
507
  function setPreferredEngine($engine)
508
  {
phpseclib/Crypt/Twofish.php CHANGED
@@ -1,878 +1,881 @@
1
- <?php
2
-
3
- /**
4
- * Pure-PHP implementation of Twofish.
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://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
13
- *
14
- * Here's a short example of how to use this library:
15
- * <code>
16
- * <?php
17
- * include 'Crypt/Twofish.php';
18
- *
19
- * $twofish = new Crypt_Twofish();
20
- *
21
- * $twofish->setKey('12345678901234567890123456789012');
22
- *
23
- * $plaintext = str_repeat('a', 1024);
24
- *
25
- * echo $twofish->decrypt($twofish->encrypt($plaintext));
26
- * ?>
27
- * </code>
28
- *
29
- * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
- * of this software and associated documentation files (the "Software"), to deal
31
- * in the Software without restriction, including without limitation the rights
32
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
- * copies of the Software, and to permit persons to whom the Software is
34
- * furnished to do so, subject to the following conditions:
35
- *
36
- * The above copyright notice and this permission notice shall be included in
37
- * all copies or substantial portions of the Software.
38
- *
39
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
- * THE SOFTWARE.
46
- *
47
- * @category Crypt
48
- * @package Crypt_Twofish
49
- * @author Jim Wigginton <terrafrost@php.net>
50
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
- * @copyright 2007 Jim Wigginton
52
- * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
- * @link http://phpseclib.sourceforge.net
54
- */
55
-
56
- /**
57
- * Include Crypt_Base
58
- *
59
- * Base cipher class
60
- */
61
- if (!class_exists('Crypt_Base')) {
62
- include_once 'Base.php';
63
- }
64
-
65
- /**#@+
66
- * @access public
67
- * @see Crypt_Twofish::encrypt()
68
- * @see Crypt_Twofish::decrypt()
69
- */
70
- /**
71
- * Encrypt / decrypt using the Counter mode.
72
- *
73
- * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
- *
75
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
- */
77
- define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
78
- /**
79
- * Encrypt / decrypt using the Electronic Code Book mode.
80
- *
81
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
- */
83
- define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
84
- /**
85
- * Encrypt / decrypt using the Code Book Chaining mode.
86
- *
87
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
- */
89
- define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
90
- /**
91
- * Encrypt / decrypt using the Cipher Feedback mode.
92
- *
93
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
- */
95
- define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
96
- /**
97
- * Encrypt / decrypt using the Cipher Feedback mode.
98
- *
99
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
- */
101
- define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
102
- /**#@-*/
103
-
104
- /**
105
- * Pure-PHP implementation of Twofish.
106
- *
107
- * @package Crypt_Twofish
108
- * @author Jim Wigginton <terrafrost@php.net>
109
- * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
- * @access public
111
- */
112
- class Crypt_Twofish extends Crypt_Base
113
- {
114
- /**
115
- * The namespace used by the cipher for its constants.
116
- *
117
- * @see Crypt_Base::const_namespace
118
- * @var String
119
- * @access private
120
- */
121
- var $const_namespace = 'TWOFISH';
122
-
123
- /**
124
- * The mcrypt specific name of the cipher
125
- *
126
- * @see Crypt_Base::cipher_name_mcrypt
127
- * @var String
128
- * @access private
129
- */
130
- var $cipher_name_mcrypt = 'twofish';
131
-
132
- /**
133
- * Optimizing value while CFB-encrypting
134
- *
135
- * @see Crypt_Base::cfb_init_len
136
- * @var Integer
137
- * @access private
138
- */
139
- var $cfb_init_len = 800;
140
-
141
- /**
142
- * Q-Table
143
- *
144
- * @var Array
145
- * @access private
146
- */
147
- var $q0 = array (
148
- 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
149
- 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
150
- 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
151
- 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
152
- 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
153
- 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
154
- 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
155
- 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
156
- 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
157
- 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
158
- 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
159
- 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
160
- 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
161
- 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
162
- 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
163
- 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
164
- 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
165
- 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
166
- 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
167
- 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
168
- 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
169
- 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
170
- 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
171
- 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
172
- 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
173
- 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
174
- 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
175
- 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
176
- 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
177
- 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
178
- 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
179
- 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
180
- );
181
-
182
- /**
183
- * Q-Table
184
- *
185
- * @var Array
186
- * @access private
187
- */
188
- var $q1 = array (
189
- 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
190
- 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
191
- 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
192
- 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
193
- 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
194
- 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
195
- 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
196
- 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
197
- 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
198
- 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
199
- 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
200
- 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
201
- 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
202
- 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
203
- 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
204
- 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
205
- 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
206
- 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
207
- 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
208
- 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
209
- 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
210
- 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
211
- 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
212
- 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
213
- 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
214
- 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
215
- 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
216
- 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
217
- 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
218
- 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
219
- 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
220
- 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
221
- );
222
-
223
- /**
224
- * M-Table
225
- *
226
- * @var Array
227
- * @access private
228
- */
229
- var $m0 = array (
230
- 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
231
- 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
232
- 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
233
- 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
234
- 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
235
- 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
236
- 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
237
- 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
238
- 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
239
- 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
240
- 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
241
- 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
242
- 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
243
- 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
244
- 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
245
- 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
246
- 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
247
- 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
248
- 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
249
- 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
250
- 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
251
- 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
252
- 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
253
- 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
254
- 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
255
- 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
256
- 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
257
- 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
258
- 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
259
- 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
260
- 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
261
- 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
262
- );
263
-
264
- /**
265
- * M-Table
266
- *
267
- * @var Array
268
- * @access private
269
- */
270
- var $m1 = array (
271
- 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
272
- 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
273
- 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
274
- 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
275
- 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
276
- 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
277
- 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
278
- 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
279
- 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
280
- 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
281
- 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
282
- 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
283
- 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
284
- 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
285
- 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
286
- 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
287
- 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
288
- 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
289
- 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
290
- 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
291
- 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
292
- 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
293
- 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
294
- 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
295
- 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
296
- 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
297
- 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
298
- 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
299
- 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
300
- 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
301
- 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
302
- 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
303
- );
304
-
305
- /**
306
- * M-Table
307
- *
308
- * @var Array
309
- * @access private
310
- */
311
- var $m2 = array (
312
- 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
313
- 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
314
- 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
315
- 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
316
- 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
317
- 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
318
- 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
319
- 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
320
- 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
321
- 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
322
- 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
323
- 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
324
- 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
325
- 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
326
- 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
327
- 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
328
- 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
329
- 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
330
- 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
331
- 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
332
- 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
333
- 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
334
- 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
335
- 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
336
- 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
337
- 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
338
- 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
339
- 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
340
- 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
341
- 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
342
- 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
343
- 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
344
- );
345
-
346
- /**
347
- * M-Table
348
- *
349
- * @var Array
350
- * @access private
351
- */
352
- var $m3 = array (
353
- 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
354
- 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
355
- 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
356
- 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
357
- 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
358
- 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
359
- 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
360
- 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
361
- 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
362
- 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
363
- 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
364
- 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
365
- 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
366
- 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
367
- 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
368
- 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
369
- 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
370
- 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
371
- 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
372
- 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
373
- 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
374
- 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
375
- 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
376
- 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
377
- 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
378
- 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
379
- 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
380
- 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
381
- 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
382
- 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
383
- 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
384
- 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
385
- );
386
-
387
- /**
388
- * The Key Schedule Array
389
- *
390
- * @var Array
391
- * @access private
392
- */
393
- var $K = array();
394
-
395
- /**
396
- * The Key depended S-Table 0
397
- *
398
- * @var Array
399
- * @access private
400
- */
401
- var $S0 = array();
402
-
403
- /**
404
- * The Key depended S-Table 1
405
- *
406
- * @var Array
407
- * @access private
408
- */
409
- var $S1 = array();
410
-
411
- /**
412
- * The Key depended S-Table 2
413
- *
414
- * @var Array
415
- * @access private
416
- */
417
- var $S2 = array();
418
-
419
- /**
420
- * The Key depended S-Table 3
421
- *
422
- * @var Array
423
- * @access private
424
- */
425
- var $S3 = array();
426
-
427
- /**
428
- * Holds the last used key
429
- *
430
- * @var Array
431
- * @access private
432
- */
433
- var $kl;
434
-
435
- /**
436
- * Sets the key.
437
- *
438
- * Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long.
439
- * If the key is less than 256-bits we round the length up to the closest valid key length,
440
- * padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits.
441
- *
442
- * If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes.
443
- *
444
- * @access public
445
- * @see Crypt_Base::setKey()
446
- * @param String $key
447
- */
448
- function setKey($key)
449
- {
450
- $keylength = strlen($key);
451
- switch (true) {
452
- case $keylength <= 16:
453
- $key = str_pad($key, 16, "\0");
454
- break;
455
- case $keylength <= 24:
456
- $key = str_pad($key, 24, "\0");
457
- break;
458
- case $keylength < 32:
459
- $key = str_pad($key, 32, "\0");
460
- break;
461
- case $keylength > 32:
462
- $key = substr($key, 0, 32);
463
- }
464
- parent::setKey($key);
465
- }
466
-
467
- /**
468
- * Setup the key (expansion)
469
- *
470
- * @see Crypt_Base::_setupKey()
471
- * @access private
472
- */
473
- function _setupKey()
474
- {
475
- if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
476
- // already expanded
477
- return;
478
- }
479
- $this->kl = array('key' => $this->key);
480
-
481
- /* Key expanding and generating the key-depended s-boxes */
482
- $le_longs = unpack('V*', $this->key);
483
- $key = unpack('C*', $this->key);
484
- $m0 = $this->m0;
485
- $m1 = $this->m1;
486
- $m2 = $this->m2;
487
- $m3 = $this->m3;
488
- $q0 = $this->q0;
489
- $q1 = $this->q1;
490
-
491
- $K = $S0 = $S1 = $S2 = $S3 = array();
492
-
493
- switch (strlen($this->key)) {
494
- case 16:
495
- list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
496
- list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
497
- for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) {
498
- $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
499
- $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
500
- $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
501
- $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
502
- $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
503
- $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
504
- $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
505
- $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
506
- $B = ($B << 8) | ($B >> 24 & 0xff);
507
- $K[] = $A+= $B;
508
- $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
509
- }
510
- for ($i = 0; $i < 256; ++$i) {
511
- $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
512
- $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
513
- $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
514
- $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
515
- }
516
- break;
517
- case 24:
518
- list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
519
- list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
520
- list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
521
- for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
522
- $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
523
- $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
524
- $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
525
- $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
526
- $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
527
- $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
528
- $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
529
- $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
530
- $B = ($B << 8) | ($B >> 24 & 0xff);
531
- $K[] = $A+= $B;
532
- $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
533
- }
534
- for ($i = 0; $i < 256; ++$i) {
535
- $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
536
- $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
537
- $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
538
- $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
539
- }
540
- break;
541
- default: // 32
542
- list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
543
- list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
544
- list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
545
- list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
546
- for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
547
- $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
548
- $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
549
- $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
550
- $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
551
- $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
552
- $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
553
- $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
554
- $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
555
- $B = ($B << 8) | ($B >> 24 & 0xff);
556
- $K[] = $A+= $B;
557
- $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
558
- }
559
- for ($i = 0; $i < 256; ++$i) {
560
- $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
561
- $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
562
- $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
563
- $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
564
- }
565
- }
566
-
567
- $this->K = $K;
568
- $this->S0 = $S0;
569
- $this->S1 = $S1;
570
- $this->S2 = $S2;
571
- $this->S3 = $S3;
572
- }
573
-
574
- /**
575
- * _mdsrem function using by the twofish cipher algorithm
576
- *
577
- * @access private
578
- * @param String $A
579
- * @param String $B
580
- * @return Array
581
- */
582
- function _mdsrem($A, $B)
583
- {
584
- // No gain by unrolling this loop.
585
- for ($i = 0; $i < 8; ++$i) {
586
- // Get most significant coefficient.
587
- $t = 0xff & ($B >> 24);
588
-
589
- // Shift the others up.
590
- $B = ($B << 8) | (0xff & ($A >> 24));
591
- $A<<= 8;
592
-
593
- $u = $t << 1;
594
-
595
- // Subtract the modular polynomial on overflow.
596
- if ($t & 0x80) {
597
- $u^= 0x14d;
598
- }
599
-
600
- // Remove t * (a * x^2 + 1).
601
- $B ^= $t ^ ($u << 16);
602
-
603
- // Form u = a*t + t/a = t*(a + 1/a).
604
- $u^= 0x7fffffff & ($t >> 1);
605
-
606
- // Add the modular polynomial on underflow.
607
- if ($t & 0x01) $u^= 0xa6 ;
608
-
609
- // Remove t * (a + 1/a) * (x^3 + x).
610
- $B^= ($u << 24) | ($u << 8);
611
- }
612
-
613
- return array(
614
- 0xff & $B >> 24,
615
- 0xff & $B >> 16,
616
- 0xff & $B >> 8,
617
- 0xff & $B);
618
- }
619
-
620
- /**
621
- * Encrypts a block
622
- *
623
- * @access private
624
- * @param String $in
625
- * @return String
626
- */
627
- function _encryptBlock($in)
628
- {
629
- $S0 = $this->S0;
630
- $S1 = $this->S1;
631
- $S2 = $this->S2;
632
- $S3 = $this->S3;
633
- $K = $this->K;
634
-
635
- $in = unpack("V4", $in);
636
- $R0 = $K[0] ^ $in[1];
637
- $R1 = $K[1] ^ $in[2];
638
- $R2 = $K[2] ^ $in[3];
639
- $R3 = $K[3] ^ $in[4];
640
-
641
- $ki = 7;
642
- while ($ki < 39) {
643
- $t0 = $S0[ $R0 & 0xff] ^
644
- $S1[($R0 >> 8) & 0xff] ^
645
- $S2[($R0 >> 16) & 0xff] ^
646
- $S3[($R0 >> 24) & 0xff];
647
- $t1 = $S0[($R1 >> 24) & 0xff] ^
648
- $S1[ $R1 & 0xff] ^
649
- $S2[($R1 >> 8) & 0xff] ^
650
- $S3[($R1 >> 16) & 0xff];
651
- $R2^= $t0 + $t1 + $K[++$ki];
652
- $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
653
- $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
654
-
655
- $t0 = $S0[ $R2 & 0xff] ^
656
- $S1[($R2 >> 8) & 0xff] ^
657
- $S2[($R2 >> 16) & 0xff] ^
658
- $S3[($R2 >> 24) & 0xff];
659
- $t1 = $S0[($R3 >> 24) & 0xff] ^
660
- $S1[ $R3 & 0xff] ^
661
- $S2[($R3 >> 8) & 0xff] ^
662
- $S3[($R3 >> 16) & 0xff];
663
- $R0^= ($t0 + $t1 + $K[++$ki]);
664
- $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
665
- $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
666
- }
667
-
668
- // @codingStandardsIgnoreStart
669
- return pack("V4", $K[4] ^ $R2,
670
- $K[5] ^ $R3,
671
- $K[6] ^ $R0,
672
- $K[7] ^ $R1);
673
- // @codingStandardsIgnoreEnd
674
- }
675
-
676
- /**
677
- * Decrypts a block
678
- *
679
- * @access private
680
- * @param String $in
681
- * @return String
682
- */
683
- function _decryptBlock($in)
684
- {
685
- $S0 = $this->S0;
686
- $S1 = $this->S1;
687
- $S2 = $this->S2;
688
- $S3 = $this->S3;
689
- $K = $this->K;
690
-
691
- $in = unpack("V4", $in);
692
- $R0 = $K[4] ^ $in[1];
693
- $R1 = $K[5] ^ $in[2];
694
- $R2 = $K[6] ^ $in[3];
695
- $R3 = $K[7] ^ $in[4];
696
-
697
- $ki = 40;
698
- while ($ki > 8) {
699
- $t0 = $S0[$R0 & 0xff] ^
700
- $S1[$R0 >> 8 & 0xff] ^
701
- $S2[$R0 >> 16 & 0xff] ^
702
- $S3[$R0 >> 24 & 0xff];
703
- $t1 = $S0[$R1 >> 24 & 0xff] ^
704
- $S1[$R1 & 0xff] ^
705
- $S2[$R1 >> 8 & 0xff] ^
706
- $S3[$R1 >> 16 & 0xff];
707
- $R3^= $t0 + ($t1 << 1) + $K[--$ki];
708
- $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
709
- $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
710
-
711
- $t0 = $S0[$R2 & 0xff] ^
712
- $S1[$R2 >> 8 & 0xff] ^
713
- $S2[$R2 >> 16 & 0xff] ^
714
- $S3[$R2 >> 24 & 0xff];
715
- $t1 = $S0[$R3 >> 24 & 0xff] ^
716
- $S1[$R3 & 0xff] ^
717
- $S2[$R3 >> 8 & 0xff] ^
718
- $S3[$R3 >> 16 & 0xff];
719
- $R1^= $t0 + ($t1 << 1) + $K[--$ki];
720
- $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
721
- $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
722
- }
723
-
724
- // @codingStandardsIgnoreStart
725
- return pack("V4", $K[0] ^ $R2,
726
- $K[1] ^ $R3,
727
- $K[2] ^ $R0,
728
- $K[3] ^ $R1);
729
- // @codingStandardsIgnoreEnd
730
- }
731
-
732
- /**
733
- * Setup the performance-optimized function for de/encrypt()
734
- *
735
- * @see Crypt_Base::_setupInlineCrypt()
736
- * @access private
737
- */
738
- function _setupInlineCrypt()
739
- {
740
- $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
741
-
742
- // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
743
- // (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
744
- $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
745
-
746
- // Generation of a uniqe hash for our generated code
747
- $code_hash = "Crypt_Twofish, {$this->mode}";
748
- if ($gen_hi_opt_code) {
749
- $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
750
- }
751
-
752
- if (!isset($lambda_functions[$code_hash])) {
753
- switch (true) {
754
- case $gen_hi_opt_code:
755
- $K = $this->K;
756
- $init_crypt = '
757
- static $S0, $S1, $S2, $S3;
758
- if (!$S0) {
759
- for ($i = 0; $i < 256; ++$i) {
760
- $S0[] = (int)$self->S0[$i];
761
- $S1[] = (int)$self->S1[$i];
762
- $S2[] = (int)$self->S2[$i];
763
- $S3[] = (int)$self->S3[$i];
764
- }
765
- }
766
- ';
767
- break;
768
- default:
769
- $K = array();
770
- for ($i = 0; $i < 40; ++$i) {
771
- $K[] = '$K_' . $i;
772
- }
773
- $init_crypt = '
774
- $S0 = $self->S0;
775
- $S1 = $self->S1;
776
- $S2 = $self->S2;
777
- $S3 = $self->S3;
778
- list(' . implode(',', $K) . ') = $self->K;
779
- ';
780
- }
781
-
782
- // Generating encrypt code:
783
- $encrypt_block = '
784
- $in = unpack("V4", $in);
785
- $R0 = '.$K[0].' ^ $in[1];
786
- $R1 = '.$K[1].' ^ $in[2];
787
- $R2 = '.$K[2].' ^ $in[3];
788
- $R3 = '.$K[3].' ^ $in[4];
789
- ';
790
- for ($ki = 7, $i = 0; $i < 8; ++$i) {
791
- $encrypt_block.= '
792
- $t0 = $S0[ $R0 & 0xff] ^
793
- $S1[($R0 >> 8) & 0xff] ^
794
- $S2[($R0 >> 16) & 0xff] ^
795
- $S3[($R0 >> 24) & 0xff];
796
- $t1 = $S0[($R1 >> 24) & 0xff] ^
797
- $S1[ $R1 & 0xff] ^
798
- $S2[($R1 >> 8) & 0xff] ^
799
- $S3[($R1 >> 16) & 0xff];
800
- $R2^= ($t0 + $t1 + '.$K[++$ki].');
801
- $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
802
- $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
803
-
804
- $t0 = $S0[ $R2 & 0xff] ^
805
- $S1[($R2 >> 8) & 0xff] ^
806
- $S2[($R2 >> 16) & 0xff] ^
807
- $S3[($R2 >> 24) & 0xff];
808
- $t1 = $S0[($R3 >> 24) & 0xff] ^
809
- $S1[ $R3 & 0xff] ^
810
- $S2[($R3 >> 8) & 0xff] ^
811
- $S3[($R3 >> 16) & 0xff];
812
- $R0^= ($t0 + $t1 + '.$K[++$ki].');
813
- $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
814
- $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
815
- ';
816
- }
817
- $encrypt_block.= '
818
- $in = pack("V4", '.$K[4].' ^ $R2,
819
- '.$K[5].' ^ $R3,
820
- '.$K[6].' ^ $R0,
821
- '.$K[7].' ^ $R1);
822
- ';
823
-
824
- // Generating decrypt code:
825
- $decrypt_block = '
826
- $in = unpack("V4", $in);
827
- $R0 = '.$K[4].' ^ $in[1];
828
- $R1 = '.$K[5].' ^ $in[2];
829
- $R2 = '.$K[6].' ^ $in[3];
830
- $R3 = '.$K[7].' ^ $in[4];
831
- ';
832
- for ($ki = 40, $i = 0; $i < 8; ++$i) {
833
- $decrypt_block.= '
834
- $t0 = $S0[$R0 & 0xff] ^
835
- $S1[$R0 >> 8 & 0xff] ^
836
- $S2[$R0 >> 16 & 0xff] ^
837
- $S3[$R0 >> 24 & 0xff];
838
- $t1 = $S0[$R1 >> 24 & 0xff] ^
839
- $S1[$R1 & 0xff] ^
840
- $S2[$R1 >> 8 & 0xff] ^
841
- $S3[$R1 >> 16 & 0xff];
842
- $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
843
- $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
844
- $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
845
-
846
- $t0 = $S0[$R2 & 0xff] ^
847
- $S1[$R2 >> 8 & 0xff] ^
848
- $S2[$R2 >> 16 & 0xff] ^
849
- $S3[$R2 >> 24 & 0xff];
850
- $t1 = $S0[$R3 >> 24 & 0xff] ^
851
- $S1[$R3 & 0xff] ^
852
- $S2[$R3 >> 8 & 0xff] ^
853
- $S3[$R3 >> 16 & 0xff];
854
- $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
855
- $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
856
- $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
857
- ';
858
- }
859
- $decrypt_block.= '
860
- $in = pack("V4", '.$K[0].' ^ $R2,
861
- '.$K[1].' ^ $R3,
862
- '.$K[2].' ^ $R0,
863
- '.$K[3].' ^ $R1);
864
- ';
865
-
866
- $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
867
- array(
868
- 'init_crypt' => $init_crypt,
869
- 'init_encrypt' => '',
870
- 'init_decrypt' => '',
871
- 'encrypt_block' => $encrypt_block,
872
- 'decrypt_block' => $decrypt_block
873
- )
874
- );
875
- }
876
- $this->inline_crypt = $lambda_functions[$code_hash];
877
- }
878
- }
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pure-PHP implementation of Twofish.
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://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
13
+ *
14
+ * Here's a short example of how to use this library:
15
+ * <code>
16
+ * <?php
17
+ * include 'Crypt/Twofish.php';
18
+ *
19
+ * $twofish = new Crypt_Twofish();
20
+ *
21
+ * $twofish->setKey('12345678901234567890123456789012');
22
+ *
23
+ * $plaintext = str_repeat('a', 1024);
24
+ *
25
+ * echo $twofish->decrypt($twofish->encrypt($plaintext));
26
+ * ?>
27
+ * </code>
28
+ *
29
+ * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ * of this software and associated documentation files (the "Software"), to deal
31
+ * in the Software without restriction, including without limitation the rights
32
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ * copies of the Software, and to permit persons to whom the Software is
34
+ * furnished to do so, subject to the following conditions:
35
+ *
36
+ * The above copyright notice and this permission notice shall be included in
37
+ * all copies or substantial portions of the Software.
38
+ *
39
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ * THE SOFTWARE.
46
+ *
47
+ * @category Crypt
48
+ * @package Crypt_Twofish
49
+ * @author Jim Wigginton <terrafrost@php.net>
50
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
51
+ * @copyright 2007 Jim Wigginton
52
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
53
+ * @link http://phpseclib.sourceforge.net
54
+ */
55
+
56
+ /**
57
+ * Include Crypt_Base
58
+ *
59
+ * Base cipher class
60
+ */
61
+ if (!class_exists('Crypt_Base')) {
62
+ include_once 'Base.php';
63
+ }
64
+
65
+ /**#@+
66
+ * @access public
67
+ * @see self::encrypt()
68
+ * @see self::decrypt()
69
+ */
70
+ /**
71
+ * Encrypt / decrypt using the Counter mode.
72
+ *
73
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
74
+ *
75
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
76
+ */
77
+ define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
78
+ /**
79
+ * Encrypt / decrypt using the Electronic Code Book mode.
80
+ *
81
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
82
+ */
83
+ define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
84
+ /**
85
+ * Encrypt / decrypt using the Code Book Chaining mode.
86
+ *
87
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
88
+ */
89
+ define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
90
+ /**
91
+ * Encrypt / decrypt using the Cipher Feedback mode.
92
+ *
93
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
94
+ */
95
+ define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
96
+ /**
97
+ * Encrypt / decrypt using the Cipher Feedback mode.
98
+ *
99
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
100
+ */
101
+ define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
102
+ /**#@-*/
103
+
104
+ /**
105
+ * Pure-PHP implementation of Twofish.
106
+ *
107
+ * @package Crypt_Twofish
108
+ * @author Jim Wigginton <terrafrost@php.net>
109
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
110
+ * @access public
111
+ */
112
+ class Crypt_Twofish extends Crypt_Base
113
+ {
114
+ /**
115
+ * The namespace used by the cipher for its constants.
116
+ *
117
+ * @see Crypt_Base::const_namespace
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $const_namespace = 'TWOFISH';
122
+
123
+ /**
124
+ * The mcrypt specific name of the cipher
125
+ *
126
+ * @see Crypt_Base::cipher_name_mcrypt
127
+ * @var string
128
+ * @access private
129
+ */
130
+ var $cipher_name_mcrypt = 'twofish';
131
+
132
+ /**
133
+ * Optimizing value while CFB-encrypting
134
+ *
135
+ * @see Crypt_Base::cfb_init_len
136
+ * @var int
137
+ * @access private
138
+ */
139
+ var $cfb_init_len = 800;
140
+
141
+ /**
142
+ * Q-Table
143
+ *
144
+ * @var array
145
+ * @access private
146
+ */
147
+ var $q0 = array(
148
+ 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
149
+ 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
150
+ 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
151
+ 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
152
+ 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
153
+ 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
154
+ 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
155
+ 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
156
+ 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
157
+ 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
158
+ 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
159
+ 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
160
+ 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
161
+ 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
162
+ 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
163
+ 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
164
+ 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
165
+ 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
166
+ 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
167
+ 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
168
+ 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
169
+ 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
170
+ 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
171
+ 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
172
+ 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
173
+ 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
174
+ 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
175
+ 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
176
+ 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
177
+ 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
178
+ 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
179
+ 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
180
+ );
181
+
182
+ /**
183
+ * Q-Table
184
+ *
185
+ * @var array
186
+ * @access private
187
+ */
188
+ var $q1 = array(
189
+ 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
190
+ 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
191
+ 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
192
+ 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
193
+ 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
194
+ 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
195
+ 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
196
+ 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
197
+ 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
198
+ 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
199
+ 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
200
+ 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
201
+ 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
202
+ 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
203
+ 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
204
+ 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
205
+ 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
206
+ 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
207
+ 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
208
+ 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
209
+ 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
210
+ 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
211
+ 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
212
+ 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
213
+ 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
214
+ 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
215
+ 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
216
+ 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
217
+ 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
218
+ 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
219
+ 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
220
+ 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
221
+ );
222
+
223
+ /**
224
+ * M-Table
225
+ *
226
+ * @var array
227
+ * @access private
228
+ */
229
+ var $m0 = array(
230
+ 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
231
+ 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
232
+ 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
233
+ 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
234
+ 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
235
+ 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
236
+ 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
237
+ 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
238
+ 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
239
+ 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
240
+ 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
241
+ 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
242
+ 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
243
+ 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
244
+ 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
245
+ 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
246
+ 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
247
+ 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
248
+ 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
249
+ 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
250
+ 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
251
+ 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
252
+ 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
253
+ 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
254
+ 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
255
+ 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
256
+ 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
257
+ 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
258
+ 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
259
+ 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
260
+ 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
261
+ 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
262
+ );
263
+
264
+ /**
265
+ * M-Table
266
+ *
267
+ * @var array
268
+ * @access private
269
+ */
270
+ var $m1 = array(
271
+ 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
272
+ 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
273
+ 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
274
+ 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
275
+ 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
276
+ 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
277
+ 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
278
+ 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
279
+ 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
280
+ 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
281
+ 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
282
+ 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
283
+ 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
284
+ 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
285
+ 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
286
+ 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
287
+ 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
288
+ 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
289
+ 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
290
+ 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
291
+ 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
292
+ 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
293
+ 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
294
+ 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
295
+ 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
296
+ 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
297
+ 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
298
+ 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
299
+ 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
300
+ 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
301
+ 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
302
+ 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
303
+ );
304
+
305
+ /**
306
+ * M-Table
307
+ *
308
+ * @var array
309
+ * @access private
310
+ */
311
+ var $m2 = array(
312
+ 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
313
+ 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
314
+ 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
315
+ 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
316
+ 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
317
+ 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
318
+ 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
319
+ 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
320
+ 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
321
+ 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
322
+ 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
323
+ 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
324
+ 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
325
+ 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
326
+ 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
327
+ 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
328
+ 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
329
+ 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
330
+ 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
331
+ 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
332
+ 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
333
+ 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
334
+ 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
335
+ 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
336
+ 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
337
+ 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
338
+ 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
339
+ 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
340
+ 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
341
+ 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
342
+ 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
343
+ 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
344
+ );
345
+
346
+ /**
347
+ * M-Table
348
+ *
349
+ * @var array
350
+ * @access private
351
+ */
352
+ var $m3 = array(
353
+ 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
354
+ 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
355
+ 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
356
+ 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
357
+ 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
358
+ 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
359
+ 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
360
+ 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
361
+ 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
362
+ 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
363
+ 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
364
+ 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
365
+ 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
366
+ 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
367
+ 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
368
+ 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
369
+ 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
370
+ 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
371
+ 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
372
+ 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
373
+ 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
374
+ 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
375
+ 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
376
+ 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
377
+ 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
378
+ 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
379
+ 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
380
+ 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
381
+ 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
382
+ 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
383
+ 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
384
+ 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
385
+ );
386
+
387
+ /**
388
+ * The Key Schedule Array
389
+ *
390
+ * @var array
391
+ * @access private
392
+ */
393
+ var $K = array();
394
+
395
+ /**
396
+ * The Key depended S-Table 0
397
+ *
398
+ * @var array
399
+ * @access private
400
+ */
401
+ var $S0 = array();
402
+
403
+ /**
404
+ * The Key depended S-Table 1
405
+ *
406
+ * @var array
407
+ * @access private
408
+ */
409
+ var $S1 = array();
410
+
411
+ /**
412
+ * The Key depended S-Table 2
413
+ *
414
+ * @var array
415
+ * @access private
416
+ */
417
+ var $S2 = array();
418
+
419
+ /**
420
+ * The Key depended S-Table 3
421
+ *
422
+ * @var array
423
+ * @access private
424
+ */
425
+ var $S3 = array();
426
+
427
+ /**
428
+ * Holds the last used key
429
+ *
430
+ * @var array
431
+ * @access private
432
+ */
433
+ var $kl;
434
+
435
+ /**
436
+ * The Key Length (in bytes)
437
+ *
438
+ * @see Crypt_Twofish::setKeyLength()
439
+ * @var int
440
+ * @access private
441
+ */
442
+ var $key_length = 16;
443
+
444
+ /**
445
+ * Sets the key length.
446
+ *
447
+ * Valid key lengths are 128, 192 or 256 bits
448
+ *
449
+ * @access public
450
+ * @param int $length
451
+ */
452
+ function setKeyLength($length)
453
+ {
454
+ switch (true) {
455
+ case $length <= 128:
456
+ $this->key_length = 16;
457
+ break;
458
+ case $length <= 192:
459
+ $this->key_length = 24;
460
+ break;
461
+ default:
462
+ $this->key_length = 32;
463
+ }
464
+
465
+ parent::setKeyLength($length);
466
+ }
467
+
468
+ /**
469
+ * Setup the key (expansion)
470
+ *
471
+ * @see Crypt_Base::_setupKey()
472
+ * @access private
473
+ */
474
+ function _setupKey()
475
+ {
476
+ if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
477
+ // already expanded
478
+ return;
479
+ }
480
+ $this->kl = array('key' => $this->key);
481
+
482
+ /* Key expanding and generating the key-depended s-boxes */
483
+ $le_longs = unpack('V*', $this->key);
484
+ $key = unpack('C*', $this->key);
485
+ $m0 = $this->m0;
486
+ $m1 = $this->m1;
487
+ $m2 = $this->m2;
488
+ $m3 = $this->m3;
489
+ $q0 = $this->q0;
490
+ $q1 = $this->q1;
491
+
492
+ $K = $S0 = $S1 = $S2 = $S3 = array();
493
+
494
+ switch (strlen($this->key)) {
495
+ case 16:
496
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
497
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
498
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
499
+ $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
500
+ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
501
+ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
502
+ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
503
+ $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
504
+ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
505
+ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
506
+ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
507
+ $B = ($B << 8) | ($B >> 24 & 0xff);
508
+ $K[] = $A+= $B;
509
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
510
+ }
511
+ for ($i = 0; $i < 256; ++$i) {
512
+ $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
513
+ $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
514
+ $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
515
+ $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
516
+ }
517
+ break;
518
+ case 24:
519
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
520
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
521
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
522
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
523
+ $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
524
+ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
525
+ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
526
+ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
527
+ $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
528
+ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
529
+ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
530
+ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
531
+ $B = ($B << 8) | ($B >> 24 & 0xff);
532
+ $K[] = $A+= $B;
533
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
534
+ }
535
+ for ($i = 0; $i < 256; ++$i) {
536
+ $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
537
+ $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
538
+ $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
539
+ $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
540
+ }
541
+ break;
542
+ default: // 32
543
+ list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
544
+ list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
545
+ list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
546
+ list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
547
+ for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
548
+ $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
549
+ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
550
+ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
551
+ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
552
+ $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
553
+ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
554
+ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
555
+ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
556
+ $B = ($B << 8) | ($B >> 24 & 0xff);
557
+ $K[] = $A+= $B;
558
+ $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
559
+ }
560
+ for ($i = 0; $i < 256; ++$i) {
561
+ $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
562
+ $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
563
+ $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
564
+ $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
565
+ }
566
+ }
567
+
568
+ $this->K = $K;
569
+ $this->S0 = $S0;
570
+ $this->S1 = $S1;
571
+ $this->S2 = $S2;
572
+ $this->S3 = $S3;
573
+ }
574
+
575
+ /**
576
+ * _mdsrem function using by the twofish cipher algorithm
577
+ *
578
+ * @access private
579
+ * @param string $A
580
+ * @param string $B
581
+ * @return array
582
+ */
583
+ function _mdsrem($A, $B)
584
+ {
585
+ // No gain by unrolling this loop.
586
+ for ($i = 0; $i < 8; ++$i) {
587
+ // Get most significant coefficient.
588
+ $t = 0xff & ($B >> 24);
589
+
590
+ // Shift the others up.
591
+ $B = ($B << 8) | (0xff & ($A >> 24));
592
+ $A<<= 8;
593
+
594
+ $u = $t << 1;
595
+
596
+ // Subtract the modular polynomial on overflow.
597
+ if ($t & 0x80) {
598
+ $u^= 0x14d;
599
+ }
600
+
601
+ // Remove t * (a * x^2 + 1).
602
+ $B ^= $t ^ ($u << 16);
603
+
604
+ // Form u = a*t + t/a = t*(a + 1/a).
605
+ $u^= 0x7fffffff & ($t >> 1);
606
+
607
+ // Add the modular polynomial on underflow.
608
+ if ($t & 0x01) {
609
+ $u^= 0xa6 ;
610
+ }
611
+
612
+ // Remove t * (a + 1/a) * (x^3 + x).
613
+ $B^= ($u << 24) | ($u << 8);
614
+ }
615
+
616
+ return array(
617
+ 0xff & $B >> 24,
618
+ 0xff & $B >> 16,
619
+ 0xff & $B >> 8,
620
+ 0xff & $B);
621
+ }
622
+
623
+ /**
624
+ * Encrypts a block
625
+ *
626
+ * @access private
627
+ * @param string $in
628
+ * @return string
629
+ */
630
+ function _encryptBlock($in)
631
+ {
632
+ $S0 = $this->S0;
633
+ $S1 = $this->S1;
634
+ $S2 = $this->S2;
635
+ $S3 = $this->S3;
636
+ $K = $this->K;
637
+
638
+ $in = unpack("V4", $in);
639
+ $R0 = $K[0] ^ $in[1];
640
+ $R1 = $K[1] ^ $in[2];
641
+ $R2 = $K[2] ^ $in[3];
642
+ $R3 = $K[3] ^ $in[4];
643
+
644
+ $ki = 7;
645
+ while ($ki < 39) {
646
+ $t0 = $S0[ $R0 & 0xff] ^
647
+ $S1[($R0 >> 8) & 0xff] ^
648
+ $S2[($R0 >> 16) & 0xff] ^
649
+ $S3[($R0 >> 24) & 0xff];
650
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
651
+ $S1[ $R1 & 0xff] ^
652
+ $S2[($R1 >> 8) & 0xff] ^
653
+ $S3[($R1 >> 16) & 0xff];
654
+ $R2^= $t0 + $t1 + $K[++$ki];
655
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
656
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
657
+
658
+ $t0 = $S0[ $R2 & 0xff] ^
659
+ $S1[($R2 >> 8) & 0xff] ^
660
+ $S2[($R2 >> 16) & 0xff] ^
661
+ $S3[($R2 >> 24) & 0xff];
662
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
663
+ $S1[ $R3 & 0xff] ^
664
+ $S2[($R3 >> 8) & 0xff] ^
665
+ $S3[($R3 >> 16) & 0xff];
666
+ $R0^= ($t0 + $t1 + $K[++$ki]);
667
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
668
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
669
+ }
670
+
671
+ // @codingStandardsIgnoreStart
672
+ return pack("V4", $K[4] ^ $R2,
673
+ $K[5] ^ $R3,
674
+ $K[6] ^ $R0,
675
+ $K[7] ^ $R1);
676
+ // @codingStandardsIgnoreEnd
677
+ }
678
+
679
+ /**
680
+ * Decrypts a block
681
+ *
682
+ * @access private
683
+ * @param string $in
684
+ * @return string
685
+ */
686
+ function _decryptBlock($in)
687
+ {
688
+ $S0 = $this->S0;
689
+ $S1 = $this->S1;
690
+ $S2 = $this->S2;
691
+ $S3 = $this->S3;
692
+ $K = $this->K;
693
+
694
+ $in = unpack("V4", $in);
695
+ $R0 = $K[4] ^ $in[1];
696
+ $R1 = $K[5] ^ $in[2];
697
+ $R2 = $K[6] ^ $in[3];
698
+ $R3 = $K[7] ^ $in[4];
699
+
700
+ $ki = 40;
701
+ while ($ki > 8) {
702
+ $t0 = $S0[$R0 & 0xff] ^
703
+ $S1[$R0 >> 8 & 0xff] ^
704
+ $S2[$R0 >> 16 & 0xff] ^
705
+ $S3[$R0 >> 24 & 0xff];
706
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
707
+ $S1[$R1 & 0xff] ^
708
+ $S2[$R1 >> 8 & 0xff] ^
709
+ $S3[$R1 >> 16 & 0xff];
710
+ $R3^= $t0 + ($t1 << 1) + $K[--$ki];
711
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
712
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
713
+
714
+ $t0 = $S0[$R2 & 0xff] ^
715
+ $S1[$R2 >> 8 & 0xff] ^
716
+ $S2[$R2 >> 16 & 0xff] ^
717
+ $S3[$R2 >> 24 & 0xff];
718
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
719
+ $S1[$R3 & 0xff] ^
720
+ $S2[$R3 >> 8 & 0xff] ^
721
+ $S3[$R3 >> 16 & 0xff];
722
+ $R1^= $t0 + ($t1 << 1) + $K[--$ki];
723
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
724
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
725
+ }
726
+
727
+ // @codingStandardsIgnoreStart
728
+ return pack("V4", $K[0] ^ $R2,
729
+ $K[1] ^ $R3,
730
+ $K[2] ^ $R0,
731
+ $K[3] ^ $R1);
732
+ // @codingStandardsIgnoreEnd
733
+ }
734
+
735
+ /**
736
+ * Setup the performance-optimized function for de/encrypt()
737
+ *
738
+ * @see Crypt_Base::_setupInlineCrypt()
739
+ * @access private
740
+ */
741
+ function _setupInlineCrypt()
742
+ {
743
+ $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
744
+
745
+ // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
746
+ // (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
747
+ $gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
748
+
749
+ // Generation of a unique hash for our generated code
750
+ $code_hash = "Crypt_Twofish, {$this->mode}";
751
+ if ($gen_hi_opt_code) {
752
+ $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
753
+ }
754
+
755
+ if (!isset($lambda_functions[$code_hash])) {
756
+ switch (true) {
757
+ case $gen_hi_opt_code:
758
+ $K = $this->K;
759
+ $init_crypt = '
760
+ static $S0, $S1, $S2, $S3;
761
+ if (!$S0) {
762
+ for ($i = 0; $i < 256; ++$i) {
763
+ $S0[] = (int)$self->S0[$i];
764
+ $S1[] = (int)$self->S1[$i];
765
+ $S2[] = (int)$self->S2[$i];
766
+ $S3[] = (int)$self->S3[$i];
767
+ }
768
+ }
769
+ ';
770
+ break;
771
+ default:
772
+ $K = array();
773
+ for ($i = 0; $i < 40; ++$i) {
774
+ $K[] = '$K_' . $i;
775
+ }
776
+ $init_crypt = '
777
+ $S0 = $self->S0;
778
+ $S1 = $self->S1;
779
+ $S2 = $self->S2;
780
+ $S3 = $self->S3;
781
+ list(' . implode(',', $K) . ') = $self->K;
782
+ ';
783
+ }
784
+
785
+ // Generating encrypt code:
786
+ $encrypt_block = '
787
+ $in = unpack("V4", $in);
788
+ $R0 = '.$K[0].' ^ $in[1];
789
+ $R1 = '.$K[1].' ^ $in[2];
790
+ $R2 = '.$K[2].' ^ $in[3];
791
+ $R3 = '.$K[3].' ^ $in[4];
792
+ ';
793
+ for ($ki = 7, $i = 0; $i < 8; ++$i) {
794
+ $encrypt_block.= '
795
+ $t0 = $S0[ $R0 & 0xff] ^
796
+ $S1[($R0 >> 8) & 0xff] ^
797
+ $S2[($R0 >> 16) & 0xff] ^
798
+ $S3[($R0 >> 24) & 0xff];
799
+ $t1 = $S0[($R1 >> 24) & 0xff] ^
800
+ $S1[ $R1 & 0xff] ^
801
+ $S2[($R1 >> 8) & 0xff] ^
802
+ $S3[($R1 >> 16) & 0xff];
803
+ $R2^= ($t0 + $t1 + '.$K[++$ki].');
804
+ $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
805
+ $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
806
+
807
+ $t0 = $S0[ $R2 & 0xff] ^
808
+ $S1[($R2 >> 8) & 0xff] ^
809
+ $S2[($R2 >> 16) & 0xff] ^
810
+ $S3[($R2 >> 24) & 0xff];
811
+ $t1 = $S0[($R3 >> 24) & 0xff] ^
812
+ $S1[ $R3 & 0xff] ^
813
+ $S2[($R3 >> 8) & 0xff] ^
814
+ $S3[($R3 >> 16) & 0xff];
815
+ $R0^= ($t0 + $t1 + '.$K[++$ki].');
816
+ $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
817
+ $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
818
+ ';
819
+ }
820
+ $encrypt_block.= '
821
+ $in = pack("V4", '.$K[4].' ^ $R2,
822
+ '.$K[5].' ^ $R3,
823
+ '.$K[6].' ^ $R0,
824
+ '.$K[7].' ^ $R1);
825
+ ';
826
+
827
+ // Generating decrypt code:
828
+ $decrypt_block = '
829
+ $in = unpack("V4", $in);
830
+ $R0 = '.$K[4].' ^ $in[1];
831
+ $R1 = '.$K[5].' ^ $in[2];
832
+ $R2 = '.$K[6].' ^ $in[3];
833
+ $R3 = '.$K[7].' ^ $in[4];
834
+ ';
835
+ for ($ki = 40, $i = 0; $i < 8; ++$i) {
836
+ $decrypt_block.= '
837
+ $t0 = $S0[$R0 & 0xff] ^
838
+ $S1[$R0 >> 8 & 0xff] ^
839
+ $S2[$R0 >> 16 & 0xff] ^
840
+ $S3[$R0 >> 24 & 0xff];
841
+ $t1 = $S0[$R1 >> 24 & 0xff] ^
842
+ $S1[$R1 & 0xff] ^
843
+ $S2[$R1 >> 8 & 0xff] ^
844
+ $S3[$R1 >> 16 & 0xff];
845
+ $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
846
+ $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
847
+ $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
848
+
849
+ $t0 = $S0[$R2 & 0xff] ^
850
+ $S1[$R2 >> 8 & 0xff] ^
851
+ $S2[$R2 >> 16 & 0xff] ^
852
+ $S3[$R2 >> 24 & 0xff];
853
+ $t1 = $S0[$R3 >> 24 & 0xff] ^
854
+ $S1[$R3 & 0xff] ^
855
+ $S2[$R3 >> 8 & 0xff] ^
856
+ $S3[$R3 >> 16 & 0xff];
857
+ $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
858
+ $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
859
+ $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
860
+ ';
861
+ }
862
+ $decrypt_block.= '
863
+ $in = pack("V4", '.$K[0].' ^ $R2,
864
+ '.$K[1].' ^ $R3,
865
+ '.$K[2].' ^ $R0,
866
+ '.$K[3].' ^ $R1);
867
+ ';
868
+
869
+ $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
870
+ array(
871
+ 'init_crypt' => $init_crypt,
872
+ 'init_encrypt' => '',
873
+ 'init_decrypt' => '',
874
+ 'encrypt_block' => $encrypt_block,
875
+ 'decrypt_block' => $decrypt_block
876
+ )
877
+ );
878
+ }
879
+ $this->inline_crypt = $lambda_functions[$code_hash];
880
+ }
881
+ }
phpseclib/Math/BigInteger.php CHANGED
@@ -72,27 +72,27 @@
72
  * Reduction constants
73
  *
74
  * @access private
75
- * @see Math_BigInteger::_reduce()
76
  */
77
  /**
78
- * @see Math_BigInteger::_montgomery()
79
- * @see Math_BigInteger::_prepMontgomery()
80
  */
81
  define('MATH_BIGINTEGER_MONTGOMERY', 0);
82
  /**
83
- * @see Math_BigInteger::_barrett()
84
  */
85
  define('MATH_BIGINTEGER_BARRETT', 1);
86
  /**
87
- * @see Math_BigInteger::_mod2()
88
  */
89
  define('MATH_BIGINTEGER_POWEROF2', 2);
90
  /**
91
- * @see Math_BigInteger::_remainder()
92
  */
93
  define('MATH_BIGINTEGER_CLASSIC', 3);
94
  /**
95
- * @see Math_BigInteger::__clone()
96
  */
97
  define('MATH_BIGINTEGER_NONE', 4);
98
  /**#@-*/
@@ -117,8 +117,8 @@ define('MATH_BIGINTEGER_SIGN', 1);
117
 
118
  /**#@+
119
  * @access private
120
- * @see Math_BigInteger::_montgomery()
121
- * @see Math_BigInteger::_barrett()
122
  */
123
  /**
124
  * Cache constants
@@ -136,7 +136,7 @@ define('MATH_BIGINTEGER_DATA', 1);
136
  * Mode constants.
137
  *
138
  * @access private
139
- * @see Math_BigInteger::Math_BigInteger()
140
  */
141
  /**
142
  * To use the pure-PHP implementation
@@ -178,7 +178,7 @@ class Math_BigInteger
178
  /**
179
  * Holds the BigInteger's value.
180
  *
181
- * @var Array
182
  * @access private
183
  */
184
  var $value;
@@ -186,23 +186,15 @@ class Math_BigInteger
186
  /**
187
  * Holds the BigInteger's magnitude.
188
  *
189
- * @var Boolean
190
  * @access private
191
  */
192
  var $is_negative = false;
193
 
194
- /**
195
- * Random number generator function
196
- *
197
- * @see setRandomGenerator()
198
- * @access private
199
- */
200
- var $generator = 'mt_rand';
201
-
202
  /**
203
  * Precision
204
  *
205
- * @see setPrecision()
206
  * @access private
207
  */
208
  var $precision = -1;
@@ -210,7 +202,7 @@ class Math_BigInteger
210
  /**
211
  * Precision Bitmask
212
  *
213
- * @see setPrecision()
214
  * @access private
215
  */
216
  var $bitmask = false;
@@ -222,9 +214,9 @@ class Math_BigInteger
222
  * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
223
  * however, $this->hex is only calculated when $this->__sleep() is called.
224
  *
225
- * @see __sleep()
226
- * @see __wakeup()
227
- * @var String
228
  * @access private
229
  */
230
  var $hex;
@@ -246,14 +238,14 @@ class Math_BigInteger
246
  * ?>
247
  * </code>
248
  *
249
- * @param optional $x base-10 number or base-$base number if $base set.
250
- * @param optional integer $base
251
  * @return Math_BigInteger
252
  * @access public
253
  */
254
- function Math_BigInteger($x = 0, $base = 10)
255
  {
256
- if ( !defined('MATH_BIGINTEGER_MODE') ) {
257
  switch (true) {
258
  case extension_loaded('gmp'):
259
  define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
@@ -266,7 +258,7 @@ class Math_BigInteger
266
  }
267
  }
268
 
269
- if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
270
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
271
  ob_start();
272
  @phpinfo();
@@ -294,6 +286,7 @@ class Math_BigInteger
294
  case !isset($versions['Header']):
295
  case !isset($versions['Library']):
296
  case $versions['Header'] == $versions['Library']:
 
297
  define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
298
  break;
299
  default:
@@ -334,7 +327,7 @@ class Math_BigInteger
334
  }
335
  }
336
 
337
- switch ( MATH_BIGINTEGER_MODE ) {
338
  case MATH_BIGINTEGER_MODE_GMP:
339
  switch (true) {
340
  case is_resource($x) && get_resource_type($x) == 'GMP integer':
@@ -364,11 +357,15 @@ class Math_BigInteger
364
  $x = ~$x;
365
  $this->is_negative = true;
366
  }
367
- case 256:
368
- switch ( MATH_BIGINTEGER_MODE ) {
369
  case MATH_BIGINTEGER_MODE_GMP:
370
- $sign = $this->is_negative ? '-' : '';
371
- $this->value = gmp_init($sign . '0x' . bin2hex($x));
 
 
 
 
372
  break;
373
  case MATH_BIGINTEGER_MODE_BCMATH:
374
  // round $len to the nearest 4 (thanks, DavidMJ!)
@@ -401,7 +398,7 @@ class Math_BigInteger
401
  $this->value = $temp->value;
402
  }
403
  break;
404
- case 16:
405
  case -16:
406
  if ($base > 0 && $x[0] == '-') {
407
  $this->is_negative = true;
@@ -416,20 +413,20 @@ class Math_BigInteger
416
  $x = bin2hex(~pack('H*', $x));
417
  }
418
 
419
- switch ( MATH_BIGINTEGER_MODE ) {
420
  case MATH_BIGINTEGER_MODE_GMP:
421
  $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
422
  $this->value = gmp_init($temp);
423
  $this->is_negative = false;
424
  break;
425
  case MATH_BIGINTEGER_MODE_BCMATH:
426
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
427
  $temp = new Math_BigInteger(pack('H*', $x), 256);
428
  $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
429
  $this->is_negative = false;
430
  break;
431
  default:
432
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
433
  $temp = new Math_BigInteger(pack('H*', $x), 256);
434
  $this->value = $temp->value;
435
  }
@@ -439,14 +436,14 @@ class Math_BigInteger
439
  $this->value = $temp->value;
440
  }
441
  break;
442
- case 10:
443
  case -10:
444
  // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
445
  // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
446
  // [^-0-9].*: find any non-numeric characters and then any characters that follow that
447
  $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
448
 
449
- switch ( MATH_BIGINTEGER_MODE ) {
450
  case MATH_BIGINTEGER_MODE_GMP:
451
  $this->value = gmp_init($x);
452
  break;
@@ -476,7 +473,7 @@ class Math_BigInteger
476
  $this->value = $temp->value;
477
  }
478
  break;
479
- case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
480
  case -2:
481
  if ($base > 0 && $x[0] == '-') {
482
  $this->is_negative = true;
@@ -507,6 +504,19 @@ class Math_BigInteger
507
  }
508
  }
509
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  /**
511
  * Converts a BigInteger to a byte string (eg. base-256).
512
  *
@@ -524,8 +534,8 @@ class Math_BigInteger
524
  * ?>
525
  * </code>
526
  *
527
- * @param Boolean $twos_compliment
528
- * @return String
529
  * @access public
530
  * @internal Converts a base-2**26 number to base-2**8
531
  */
@@ -551,15 +561,19 @@ class Math_BigInteger
551
  return $comparison < 0 ? ~$bytes : $bytes;
552
  }
553
 
554
- switch ( MATH_BIGINTEGER_MODE ) {
555
  case MATH_BIGINTEGER_MODE_GMP:
556
  if (gmp_cmp($this->value, gmp_init(0)) == 0) {
557
  return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
558
  }
559
 
560
- $temp = gmp_strval(gmp_abs($this->value), 16);
561
- $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
562
- $temp = pack('H*', $temp);
 
 
 
 
563
 
564
  return $this->precision > 0 ?
565
  substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
@@ -621,8 +635,8 @@ class Math_BigInteger
621
  * ?>
622
  * </code>
623
  *
624
- * @param Boolean $twos_compliment
625
- * @return String
626
  * @access public
627
  * @internal Converts a base-2**26 number to base-2**8
628
  */
@@ -648,8 +662,8 @@ class Math_BigInteger
648
  * ?>
649
  * </code>
650
  *
651
- * @param Boolean $twos_compliment
652
- * @return String
653
  * @access public
654
  * @internal Converts a base-2**26 number to base-2**2
655
  */
@@ -686,13 +700,13 @@ class Math_BigInteger
686
  * ?>
687
  * </code>
688
  *
689
- * @return String
690
  * @access public
691
  * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
692
  */
693
  function toString()
694
  {
695
- switch ( MATH_BIGINTEGER_MODE ) {
696
  case MATH_BIGINTEGER_MODE_GMP:
697
  return gmp_strval($this->value);
698
  case MATH_BIGINTEGER_MODE_BCMATH:
@@ -738,7 +752,7 @@ class Math_BigInteger
738
  * {@link http://php.net/language.oop5.basic#51624}
739
  *
740
  * @access public
741
- * @see __clone()
742
  * @return Math_BigInteger
743
  */
744
  function copy()
@@ -746,7 +760,6 @@ class Math_BigInteger
746
  $temp = new Math_BigInteger();
747
  $temp->value = $this->value;
748
  $temp->is_negative = $this->is_negative;
749
- $temp->generator = $this->generator;
750
  $temp->precision = $this->precision;
751
  $temp->bitmask = $this->bitmask;
752
  return $temp;
@@ -775,7 +788,7 @@ class Math_BigInteger
775
  * call Math_BigInteger::copy(), instead.
776
  *
777
  * @access public
778
- * @see copy()
779
  * @return Math_BigInteger
780
  */
781
  function __clone()
@@ -788,21 +801,17 @@ class Math_BigInteger
788
  *
789
  * Will be called, automatically, when serialize() is called on a Math_BigInteger object.
790
  *
791
- * @see __wakeup()
792
  * @access public
793
  */
794
  function __sleep()
795
  {
796
  $this->hex = $this->toHex(true);
797
  $vars = array('hex');
798
- if ($this->generator != 'mt_rand') {
799
- $vars[] = 'generator';
800
- }
801
  if ($this->precision > 0) {
802
  $vars[] = 'precision';
803
  }
804
  return $vars;
805
-
806
  }
807
 
808
  /**
@@ -810,7 +819,7 @@ class Math_BigInteger
810
  *
811
  * Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
812
  *
813
- * @see __sleep()
814
  * @access public
815
  */
816
  function __wakeup()
@@ -818,13 +827,45 @@ class Math_BigInteger
818
  $temp = new Math_BigInteger($this->hex, -16);
819
  $this->value = $temp->value;
820
  $this->is_negative = $temp->is_negative;
821
- $this->setRandomGenerator($this->generator);
822
  if ($this->precision > 0) {
823
  // recalculate $this->bitmask
824
  $this->setPrecision($this->precision);
825
  }
826
  }
827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
828
  /**
829
  * Adds two BigIntegers.
830
  *
@@ -849,7 +890,7 @@ class Math_BigInteger
849
  */
850
  function add($y)
851
  {
852
- switch ( MATH_BIGINTEGER_MODE ) {
853
  case MATH_BIGINTEGER_MODE_GMP:
854
  $temp = new Math_BigInteger();
855
  $temp->value = gmp_add($this->value, $y->value);
@@ -874,11 +915,11 @@ class Math_BigInteger
874
  /**
875
  * Performs addition.
876
  *
877
- * @param Array $x_value
878
- * @param Boolean $x_negative
879
- * @param Array $y_value
880
- * @param Boolean $y_negative
881
- * @return Array
882
  * @access private
883
  */
884
  function _add($x_value, $x_negative, $y_value, $y_negative)
@@ -891,7 +932,7 @@ class Math_BigInteger
891
  MATH_BIGINTEGER_VALUE => $y_value,
892
  MATH_BIGINTEGER_SIGN => $y_negative
893
  );
894
- } else if ($y_size == 0) {
895
  return array(
896
  MATH_BIGINTEGER_VALUE => $x_value,
897
  MATH_BIGINTEGER_SIGN => $x_negative
@@ -899,8 +940,8 @@ class Math_BigInteger
899
  }
900
 
901
  // subtract, if appropriate
902
- if ( $x_negative != $y_negative ) {
903
- if ( $x_value == $y_value ) {
904
  return array(
905
  MATH_BIGINTEGER_VALUE => array(),
906
  MATH_BIGINTEGER_SIGN => false
@@ -980,7 +1021,7 @@ class Math_BigInteger
980
  */
981
  function subtract($y)
982
  {
983
- switch ( MATH_BIGINTEGER_MODE ) {
984
  case MATH_BIGINTEGER_MODE_GMP:
985
  $temp = new Math_BigInteger();
986
  $temp->value = gmp_sub($this->value, $y->value);
@@ -1005,11 +1046,11 @@ class Math_BigInteger
1005
  /**
1006
  * Performs subtraction.
1007
  *
1008
- * @param Array $x_value
1009
- * @param Boolean $x_negative
1010
- * @param Array $y_value
1011
- * @param Boolean $y_negative
1012
- * @return Array
1013
  * @access private
1014
  */
1015
  function _subtract($x_value, $x_negative, $y_value, $y_negative)
@@ -1022,7 +1063,7 @@ class Math_BigInteger
1022
  MATH_BIGINTEGER_VALUE => $y_value,
1023
  MATH_BIGINTEGER_SIGN => !$y_negative
1024
  );
1025
- } else if ($y_size == 0) {
1026
  return array(
1027
  MATH_BIGINTEGER_VALUE => $x_value,
1028
  MATH_BIGINTEGER_SIGN => $x_negative
@@ -1030,7 +1071,7 @@ class Math_BigInteger
1030
  }
1031
 
1032
  // add, if appropriate (ie. -$x - +$y or +$x - -$y)
1033
- if ( $x_negative != $y_negative ) {
1034
  $temp = $this->_add($x_value, false, $y_value, false);
1035
  $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
1036
 
@@ -1039,7 +1080,7 @@ class Math_BigInteger
1039
 
1040
  $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
1041
 
1042
- if ( !$diff ) {
1043
  return array(
1044
  MATH_BIGINTEGER_VALUE => array(),
1045
  MATH_BIGINTEGER_SIGN => false
@@ -1047,7 +1088,7 @@ class Math_BigInteger
1047
  }
1048
 
1049
  // switch $x and $y around, if appropriate.
1050
- if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) {
1051
  $temp = $x_value;
1052
  $x_value = $y_value;
1053
  $y_value = $temp;
@@ -1115,7 +1156,7 @@ class Math_BigInteger
1115
  */
1116
  function multiply($x)
1117
  {
1118
- switch ( MATH_BIGINTEGER_MODE ) {
1119
  case MATH_BIGINTEGER_MODE_GMP:
1120
  $temp = new Math_BigInteger();
1121
  $temp->value = gmp_mul($this->value, $x->value);
@@ -1140,11 +1181,11 @@ class Math_BigInteger
1140
  /**
1141
  * Performs multiplication.
1142
  *
1143
- * @param Array $x_value
1144
- * @param Boolean $x_negative
1145
- * @param Array $y_value
1146
- * @param Boolean $y_negative
1147
- * @return Array
1148
  * @access private
1149
  */
1150
  function _multiply($x_value, $x_negative, $y_value, $y_negative)
@@ -1159,7 +1200,7 @@ class Math_BigInteger
1159
  $x_length = count($x_value);
1160
  $y_length = count($y_value);
1161
 
1162
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
1163
  return array(
1164
  MATH_BIGINTEGER_VALUE => array(),
1165
  MATH_BIGINTEGER_SIGN => false
@@ -1179,9 +1220,9 @@ class Math_BigInteger
1179
  *
1180
  * Modeled after 'multiply' in MutableBigInteger.java.
1181
  *
1182
- * @param Array $x_value
1183
- * @param Array $y_value
1184
- * @return Array
1185
  * @access private
1186
  */
1187
  function _regularMultiply($x_value, $y_value)
@@ -1189,11 +1230,11 @@ class Math_BigInteger
1189
  $x_length = count($x_value);
1190
  $y_length = count($y_value);
1191
 
1192
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
1193
  return array();
1194
  }
1195
 
1196
- if ( $x_length < $y_length ) {
1197
  $temp = $x_value;
1198
  $x_value = $y_value;
1199
  $y_value = $temp;
@@ -1243,9 +1284,9 @@ class Math_BigInteger
1243
  * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1244
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
1245
  *
1246
- * @param Array $x_value
1247
- * @param Array $y_value
1248
- * @return Array
1249
  * @access private
1250
  */
1251
  function _karatsuba($x_value, $y_value)
@@ -1282,8 +1323,8 @@ class Math_BigInteger
1282
  /**
1283
  * Performs squaring
1284
  *
1285
- * @param Array $x
1286
- * @return Array
1287
  * @access private
1288
  */
1289
  function _square($x = false)
@@ -1300,13 +1341,13 @@ class Math_BigInteger
1300
  * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
1301
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
1302
  *
1303
- * @param Array $value
1304
- * @return Array
1305
  * @access private
1306
  */
1307
  function _baseSquare($value)
1308
  {
1309
- if ( empty($value) ) {
1310
  return array();
1311
  }
1312
  $square_value = $this->_array_repeat(0, 2 * count($value));
@@ -1339,8 +1380,8 @@ class Math_BigInteger
1339
  * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1340
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
1341
  *
1342
- * @param Array $value
1343
- * @return Array
1344
  * @access private
1345
  */
1346
  function _karatsubaSquare($value)
@@ -1396,13 +1437,13 @@ class Math_BigInteger
1396
  * </code>
1397
  *
1398
  * @param Math_BigInteger $y
1399
- * @return Array
1400
  * @access public
1401
  * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
1402
  */
1403
  function divide($y)
1404
  {
1405
- switch ( MATH_BIGINTEGER_MODE ) {
1406
  case MATH_BIGINTEGER_MODE_GMP:
1407
  $quotient = new Math_BigInteger();
1408
  $remainder = new Math_BigInteger();
@@ -1439,7 +1480,7 @@ class Math_BigInteger
1439
  }
1440
 
1441
  static $zero;
1442
- if ( !isset($zero) ) {
1443
  $zero = new Math_BigInteger();
1444
  }
1445
 
@@ -1453,16 +1494,16 @@ class Math_BigInteger
1453
 
1454
  $diff = $x->compare($y);
1455
 
1456
- if ( !$diff ) {
1457
  $temp = new Math_BigInteger();
1458
  $temp->value = array(1);
1459
  $temp->is_negative = $x_sign != $y_sign;
1460
  return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
1461
  }
1462
 
1463
- if ( $diff < 0 ) {
1464
  // if $x is negative, "add" $y.
1465
- if ( $x_sign ) {
1466
  $x = $y->subtract($x);
1467
  }
1468
  return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
@@ -1496,7 +1537,7 @@ class Math_BigInteger
1496
  // $temp = $y << ($x_max - $y_max-1) in base 2**26
1497
  $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
1498
 
1499
- while ( $x->compare($temp) >= 0 ) {
1500
  // calculate the "common residue"
1501
  ++$quotient_value[$x_max - $y_max];
1502
  $x = $x->subtract($temp);
@@ -1512,7 +1553,7 @@ class Math_BigInteger
1512
  );
1513
  $y_window = array(
1514
  $y_value[$y_max],
1515
- ( $y_max > 0 ) ? $y_value[$y_max - 1] : 0
1516
  );
1517
 
1518
  $q_index = $i - $y_max - 1;
@@ -1532,7 +1573,7 @@ class Math_BigInteger
1532
 
1533
  $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
1534
 
1535
- while ( $lhs->compare($rhs) > 0 ) {
1536
  --$quotient_value[$q_index];
1537
 
1538
  $lhs->value = array($quotient_value[$q_index]);
@@ -1563,7 +1604,7 @@ class Math_BigInteger
1563
  $quotient->is_negative = $x_sign != $y_sign;
1564
 
1565
  // calculate the "common residue", if appropriate
1566
- if ( $x_sign ) {
1567
  $y->_rshift($shift);
1568
  $x = $y->subtract($x);
1569
  }
@@ -1576,9 +1617,9 @@ class Math_BigInteger
1576
  *
1577
  * abc / x = a00 / x + b0 / x + c / x
1578
  *
1579
- * @param Array $dividend
1580
- * @param Array $divisor
1581
- * @return Array
1582
  * @access private
1583
  */
1584
  function _divide_digit($dividend, $divisor)
@@ -1652,7 +1693,7 @@ class Math_BigInteger
1652
  return $this->_normalize($temp->modPow($e, $n));
1653
  }
1654
 
1655
- if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP ) {
1656
  $temp = new Math_BigInteger();
1657
  $temp->value = gmp_powm($this->value, $e->value, $n->value);
1658
 
@@ -1675,17 +1716,23 @@ class Math_BigInteger
1675
  'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
1676
  );
1677
 
1678
- $RSAPublicKey = pack('Ca*a*a*',
1679
- 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
1680
- $components['modulus'], $components['publicExponent']
 
 
 
1681
  );
1682
 
1683
  $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
1684
  $RSAPublicKey = chr(0) . $RSAPublicKey;
1685
  $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
1686
 
1687
- $encapsulated = pack('Ca*a*',
1688
- 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
 
 
 
1689
  );
1690
 
1691
  $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@@ -1699,25 +1746,25 @@ class Math_BigInteger
1699
  }
1700
  }
1701
 
1702
- if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
1703
- $temp = new Math_BigInteger();
1704
- $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
1705
 
1706
- return $this->_normalize($temp);
1707
  }
1708
 
1709
- if ( empty($e->value) ) {
1710
  $temp = new Math_BigInteger();
1711
  $temp->value = array(1);
1712
  return $this->_normalize($temp);
1713
  }
1714
 
1715
- if ( $e->value == array(1) ) {
1716
  list(, $temp) = $this->divide($n);
1717
  return $this->_normalize($temp);
1718
  }
1719
 
1720
- if ( $e->value == array(2) ) {
1721
  $temp = new Math_BigInteger();
1722
  $temp->value = $this->_square($this->value);
1723
  list(, $temp) = $temp->divide($n);
@@ -1732,14 +1779,14 @@ class Math_BigInteger
1732
  // made uncallable
1733
 
1734
  // is the modulo odd?
1735
- if ( $n->value[0] & 1 ) {
1736
  return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
1737
  }
1738
  // if it's not, it's even
1739
 
1740
  // find the lowest set bit (eg. the max pow of 2 that divides $n)
1741
  for ($i = 0; $i < count($n->value); ++$i) {
1742
- if ( $n->value[$i] ) {
1743
  $temp = decbin($n->value[$i]);
1744
  $j = strlen($temp) - strrpos($temp, '1') - 1;
1745
  $j+= 26 * $i;
@@ -1754,7 +1801,7 @@ class Math_BigInteger
1754
  $mod2->value = array(1);
1755
  $mod2->_lshift($j);
1756
 
1757
- $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();
1758
  $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
1759
 
1760
  $y1 = $mod2->modInverse($mod1);
@@ -1797,7 +1844,7 @@ class Math_BigInteger
1797
  *
1798
  * @param Math_BigInteger $e
1799
  * @param Math_BigInteger $n
1800
- * @param Integer $mode
1801
  * @return Math_BigInteger
1802
  * @access private
1803
  */
@@ -1817,7 +1864,8 @@ class Math_BigInteger
1817
 
1818
  // calculate the appropriate window size.
1819
  // $window_size == 3 if $window_ranges is between 25 and 81, for example.
1820
- for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i);
 
1821
 
1822
  $n_value = $n->value;
1823
 
@@ -1837,24 +1885,25 @@ class Math_BigInteger
1837
  $result = array(1);
1838
  $result = $this->_prepareReduce($result, $n_value, $mode);
1839
 
1840
- for ($i = 0; $i < $e_length; ) {
1841
- if ( !$e_bits[$i] ) {
1842
  $result = $this->_squareReduce($result, $n_value, $mode);
1843
  ++$i;
1844
  } else {
1845
  for ($j = $window_size - 1; $j > 0; --$j) {
1846
- if ( !empty($e_bits[$i + $j]) ) {
1847
  break;
1848
  }
1849
  }
1850
 
1851
- for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1)
 
1852
  $result = $this->_squareReduce($result, $n_value, $mode);
1853
  }
1854
 
1855
  $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
1856
 
1857
- $i+=$j + 1;
1858
  }
1859
  }
1860
 
@@ -1869,12 +1918,12 @@ class Math_BigInteger
1869
  *
1870
  * For most $modes this will return the remainder.
1871
  *
1872
- * @see _slidingWindow()
1873
  * @access private
1874
- * @param Array $x
1875
- * @param Array $n
1876
- * @param Integer $mode
1877
- * @return Array
1878
  */
1879
  function _reduce($x, $n, $mode)
1880
  {
@@ -1906,12 +1955,12 @@ class Math_BigInteger
1906
  /**
1907
  * Modular reduction preperation
1908
  *
1909
- * @see _slidingWindow()
1910
  * @access private
1911
- * @param Array $x
1912
- * @param Array $n
1913
- * @param Integer $mode
1914
- * @return Array
1915
  */
1916
  function _prepareReduce($x, $n, $mode)
1917
  {
@@ -1924,13 +1973,13 @@ class Math_BigInteger
1924
  /**
1925
  * Modular multiply
1926
  *
1927
- * @see _slidingWindow()
1928
  * @access private
1929
- * @param Array $x
1930
- * @param Array $y
1931
- * @param Array $n
1932
- * @param Integer $mode
1933
- * @return Array
1934
  */
1935
  function _multiplyReduce($x, $y, $n, $mode)
1936
  {
@@ -1944,12 +1993,12 @@ class Math_BigInteger
1944
  /**
1945
  * Modular square
1946
  *
1947
- * @see _slidingWindow()
1948
  * @access private
1949
- * @param Array $x
1950
- * @param Array $n
1951
- * @param Integer $mode
1952
- * @return Array
1953
  */
1954
  function _squareReduce($x, $n, $mode)
1955
  {
@@ -1965,7 +2014,7 @@ class Math_BigInteger
1965
  * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
1966
  * we'll just use this function as a wrapper for doing that.
1967
  *
1968
- * @see _slidingWindow()
1969
  * @access private
1970
  * @param Math_BigInteger
1971
  * @return Math_BigInteger
@@ -1995,11 +2044,11 @@ class Math_BigInteger
1995
  * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
1996
  * comments for details.
1997
  *
1998
- * @see _slidingWindow()
1999
  * @access private
2000
- * @param Array $n
2001
- * @param Array $m
2002
- * @return Array
2003
  */
2004
  function _barrett($n, $m)
2005
  {
@@ -2027,7 +2076,7 @@ class Math_BigInteger
2027
 
2028
  // n = 2 * m.length
2029
 
2030
- if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
2031
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2032
  $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
2033
 
@@ -2092,11 +2141,11 @@ class Math_BigInteger
2092
  * For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
2093
  * is that this function does not fold the denominator into a smaller form.
2094
  *
2095
- * @see _slidingWindow()
2096
  * @access private
2097
- * @param Array $x
2098
- * @param Array $n
2099
- * @return Array
2100
  */
2101
  function _regularBarrett($x, $n)
2102
  {
@@ -2116,7 +2165,7 @@ class Math_BigInteger
2116
  return $temp->value;
2117
  }
2118
 
2119
- if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
2120
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2121
  $cache[MATH_BIGINTEGER_VARIABLE][] = $n;
2122
  $lhs = new Math_BigInteger();
@@ -2163,13 +2212,13 @@ class Math_BigInteger
2163
  *
2164
  * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
2165
  *
2166
- * @see _regularBarrett()
2167
- * @param Array $x_value
2168
- * @param Boolean $x_negative
2169
- * @param Array $y_value
2170
- * @param Boolean $y_negative
2171
- * @param Integer $stop
2172
- * @return Array
2173
  * @access private
2174
  */
2175
  function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
@@ -2177,14 +2226,14 @@ class Math_BigInteger
2177
  $x_length = count($x_value);
2178
  $y_length = count($y_value);
2179
 
2180
- if ( !$x_length || !$y_length ) { // a 0 is being multiplied
2181
  return array(
2182
  MATH_BIGINTEGER_VALUE => array(),
2183
  MATH_BIGINTEGER_SIGN => false
2184
  );
2185
  }
2186
 
2187
- if ( $x_length < $y_length ) {
2188
  $temp = $x_value;
2189
  $x_value = $y_value;
2190
  $y_value = $temp;
@@ -2244,12 +2293,12 @@ class Math_BigInteger
2244
  * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
2245
  * to work correctly.
2246
  *
2247
- * @see _prepMontgomery()
2248
- * @see _slidingWindow()
2249
  * @access private
2250
- * @param Array $x
2251
- * @param Array $n
2252
- * @return Array
2253
  */
2254
  function _montgomery($x, $n)
2255
  {
@@ -2258,7 +2307,7 @@ class Math_BigInteger
2258
  MATH_BIGINTEGER_DATA => array()
2259
  );
2260
 
2261
- if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
2262
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2263
  $cache[MATH_BIGINTEGER_VARIABLE][] = $x;
2264
  $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
@@ -2291,13 +2340,13 @@ class Math_BigInteger
2291
  * Interleaves the montgomery reduction and long multiplication algorithms together as described in
2292
  * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
2293
  *
2294
- * @see _prepMontgomery()
2295
- * @see _montgomery()
2296
  * @access private
2297
- * @param Array $x
2298
- * @param Array $y
2299
- * @param Array $m
2300
- * @return Array
2301
  */
2302
  function _montgomeryMultiply($x, $y, $m)
2303
  {
@@ -2314,7 +2363,7 @@ class Math_BigInteger
2314
  MATH_BIGINTEGER_DATA => array()
2315
  );
2316
 
2317
- if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) {
2318
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2319
  $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
2320
  $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
@@ -2343,12 +2392,12 @@ class Math_BigInteger
2343
  /**
2344
  * Prepare a number for use in Montgomery Modular Reductions
2345
  *
2346
- * @see _montgomery()
2347
- * @see _slidingWindow()
2348
  * @access private
2349
- * @param Array $x
2350
- * @param Array $n
2351
- * @return Array
2352
  */
2353
  function _prepMontgomery($x, $n)
2354
  {
@@ -2382,10 +2431,10 @@ class Math_BigInteger
2382
  *
2383
  * Thanks to Pedro Gimeno Fortea for input!
2384
  *
2385
- * @see _montgomery()
2386
  * @access private
2387
- * @param Array $x
2388
- * @return Integer
2389
  */
2390
  function _modInverse67108864($x) // 2**26 == 67,108,864
2391
  {
@@ -2423,18 +2472,18 @@ class Math_BigInteger
2423
  * </code>
2424
  *
2425
  * @param Math_BigInteger $n
2426
- * @return mixed false, if no modular inverse exists, Math_BigInteger, otherwise.
2427
  * @access public
2428
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
2429
  */
2430
  function modInverse($n)
2431
  {
2432
- switch ( MATH_BIGINTEGER_MODE ) {
2433
  case MATH_BIGINTEGER_MODE_GMP:
2434
  $temp = new Math_BigInteger();
2435
  $temp->value = gmp_invert($this->value, $n->value);
2436
 
2437
- return ( $temp->value === false ) ? false : $this->_normalize($temp);
2438
  }
2439
 
2440
  static $zero, $one;
@@ -2468,7 +2517,7 @@ class Math_BigInteger
2468
  *
2469
  * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
2470
  * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
2471
- * combination is returned is dependant upon which mode is in use. See
2472
  * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
2473
  *
2474
  * Here's an example:
@@ -2495,7 +2544,7 @@ class Math_BigInteger
2495
  */
2496
  function extendedGCD($n)
2497
  {
2498
- switch ( MATH_BIGINTEGER_MODE ) {
2499
  case MATH_BIGINTEGER_MODE_GMP:
2500
  extract(gmp_gcdext($this->value, $n->value));
2501
 
@@ -2545,7 +2594,7 @@ class Math_BigInteger
2545
  $g = new Math_BigInteger();
2546
  $g->value = array(1);
2547
 
2548
- while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) {
2549
  $x->_rshift(1);
2550
  $y->_rshift(1);
2551
  $g->_lshift(1);
@@ -2562,10 +2611,10 @@ class Math_BigInteger
2562
  $a->value = $d->value = $g->value = array(1);
2563
  $b->value = $c->value = array();
2564
 
2565
- while ( !empty($u->value) ) {
2566
- while ( !($u->value[0] & 1) ) {
2567
  $u->_rshift(1);
2568
- if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) {
2569
  $a = $a->add($y);
2570
  $b = $b->subtract($x);
2571
  }
@@ -2573,9 +2622,9 @@ class Math_BigInteger
2573
  $b->_rshift(1);
2574
  }
2575
 
2576
- while ( !($v->value[0] & 1) ) {
2577
  $v->_rshift(1);
2578
- if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) {
2579
  $c = $c->add($y);
2580
  $d = $d->subtract($x);
2581
  }
@@ -2640,7 +2689,7 @@ class Math_BigInteger
2640
  {
2641
  $temp = new Math_BigInteger();
2642
 
2643
- switch ( MATH_BIGINTEGER_MODE ) {
2644
  case MATH_BIGINTEGER_MODE_GMP:
2645
  $temp->value = gmp_abs($this->value);
2646
  break;
@@ -2667,14 +2716,14 @@ class Math_BigInteger
2667
  * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
2668
  *
2669
  * @param Math_BigInteger $y
2670
- * @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
2671
  * @access public
2672
- * @see equals()
2673
  * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
2674
  */
2675
  function compare($y)
2676
  {
2677
- switch ( MATH_BIGINTEGER_MODE ) {
2678
  case MATH_BIGINTEGER_MODE_GMP:
2679
  return gmp_cmp($this->value, $y->value);
2680
  case MATH_BIGINTEGER_MODE_BCMATH:
@@ -2687,24 +2736,24 @@ class Math_BigInteger
2687
  /**
2688
  * Compares two numbers.
2689
  *
2690
- * @param Array $x_value
2691
- * @param Boolean $x_negative
2692
- * @param Array $y_value
2693
- * @param Boolean $y_negative
2694
- * @return Integer
2695
- * @see compare()
2696
  * @access private
2697
  */
2698
  function _compare($x_value, $x_negative, $y_value, $y_negative)
2699
  {
2700
- if ( $x_negative != $y_negative ) {
2701
- return ( !$x_negative && $y_negative ) ? 1 : -1;
2702
  }
2703
 
2704
  $result = $x_negative ? -1 : 1;
2705
 
2706
- if ( count($x_value) != count($y_value) ) {
2707
- return ( count($x_value) > count($y_value) ) ? $result : -$result;
2708
  }
2709
  $size = max(count($x_value), count($y_value));
2710
 
@@ -2713,7 +2762,7 @@ class Math_BigInteger
2713
 
2714
  for ($i = count($x_value) - 1; $i >= 0; --$i) {
2715
  if ($x_value[$i] != $y_value[$i]) {
2716
- return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result;
2717
  }
2718
  }
2719
 
@@ -2726,13 +2775,13 @@ class Math_BigInteger
2726
  * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()
2727
  *
2728
  * @param Math_BigInteger $x
2729
- * @return Boolean
2730
  * @access public
2731
- * @see compare()
2732
  */
2733
  function equals($x)
2734
  {
2735
- switch ( MATH_BIGINTEGER_MODE ) {
2736
  case MATH_BIGINTEGER_MODE_GMP:
2737
  return gmp_cmp($this->value, $x->value) == 0;
2738
  default:
@@ -2746,13 +2795,13 @@ class Math_BigInteger
2746
  * Some bitwise operations give different results depending on the precision being used. Examples include left
2747
  * shift, not, and rotates.
2748
  *
2749
- * @param Integer $bits
2750
  * @access public
2751
  */
2752
  function setPrecision($bits)
2753
  {
2754
  $this->precision = $bits;
2755
- if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) {
2756
  $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
2757
  } else {
2758
  $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
@@ -2772,7 +2821,7 @@ class Math_BigInteger
2772
  */
2773
  function bitwise_and($x)
2774
  {
2775
- switch ( MATH_BIGINTEGER_MODE ) {
2776
  case MATH_BIGINTEGER_MODE_GMP:
2777
  $temp = new Math_BigInteger();
2778
  $temp->value = gmp_and($this->value, $x->value);
@@ -2813,7 +2862,7 @@ class Math_BigInteger
2813
  */
2814
  function bitwise_or($x)
2815
  {
2816
- switch ( MATH_BIGINTEGER_MODE ) {
2817
  case MATH_BIGINTEGER_MODE_GMP:
2818
  $temp = new Math_BigInteger();
2819
  $temp->value = gmp_or($this->value, $x->value);
@@ -2853,7 +2902,7 @@ class Math_BigInteger
2853
  */
2854
  function bitwise_xor($x)
2855
  {
2856
- switch ( MATH_BIGINTEGER_MODE ) {
2857
  case MATH_BIGINTEGER_MODE_GMP:
2858
  $temp = new Math_BigInteger();
2859
  $temp->value = gmp_xor($this->value, $x->value);
@@ -2895,6 +2944,9 @@ class Math_BigInteger
2895
  // calculuate "not" without regard to $this->precision
2896
  // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
2897
  $temp = $this->toBytes();
 
 
 
2898
  $pre_msb = decbin(ord($temp[0]));
2899
  $temp = ~$temp;
2900
  $msb = decbin(ord($temp[0]));
@@ -2924,7 +2976,7 @@ class Math_BigInteger
2924
  *
2925
  * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
2926
  *
2927
- * @param Integer $shift
2928
  * @return Math_BigInteger
2929
  * @access public
2930
  * @internal The only version that yields any speed increases is the internal version.
@@ -2933,7 +2985,7 @@ class Math_BigInteger
2933
  {
2934
  $temp = new Math_BigInteger();
2935
 
2936
- switch ( MATH_BIGINTEGER_MODE ) {
2937
  case MATH_BIGINTEGER_MODE_GMP:
2938
  static $two;
2939
 
@@ -2962,7 +3014,7 @@ class Math_BigInteger
2962
  *
2963
  * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
2964
  *
2965
- * @param Integer $shift
2966
  * @return Math_BigInteger
2967
  * @access public
2968
  * @internal The only version that yields any speed increases is the internal version.
@@ -2971,7 +3023,7 @@ class Math_BigInteger
2971
  {
2972
  $temp = new Math_BigInteger();
2973
 
2974
- switch ( MATH_BIGINTEGER_MODE ) {
2975
  case MATH_BIGINTEGER_MODE_GMP:
2976
  static $two;
2977
 
@@ -3000,7 +3052,7 @@ class Math_BigInteger
3000
  *
3001
  * Instead of the top x bits being dropped they're appended to the shifted bit string.
3002
  *
3003
- * @param Integer $shift
3004
  * @return Math_BigInteger
3005
  * @access public
3006
  */
@@ -3010,7 +3062,7 @@ class Math_BigInteger
3010
 
3011
  if ($this->precision > 0) {
3012
  $precision = $this->precision;
3013
- if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
3014
  $mask = $this->bitmask->subtract(new Math_BigInteger(1));
3015
  $mask = $mask->toBytes();
3016
  } else {
@@ -3018,7 +3070,8 @@ class Math_BigInteger
3018
  }
3019
  } else {
3020
  $temp = ord($bits[0]);
3021
- for ($i = 0; $temp >> $i; ++$i);
 
3022
  $precision = 8 * strlen($bits) - 8 + $i;
3023
  $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
3024
  }
@@ -3044,7 +3097,7 @@ class Math_BigInteger
3044
  *
3045
  * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
3046
  *
3047
- * @param Integer $shift
3048
  * @return Math_BigInteger
3049
  * @access public
3050
  */
@@ -3058,7 +3111,7 @@ class Math_BigInteger
3058
  *
3059
  * This function is deprecated.
3060
  *
3061
- * @param String $generator
3062
  * @access public
3063
  */
3064
  function setRandomGenerator($generator)
@@ -3070,7 +3123,7 @@ class Math_BigInteger
3070
  *
3071
  * Byte length is equal to $length. Uses crypt_random if it's loaded and mt_rand if it's not.
3072
  *
3073
- * @param Integer $length
3074
  * @return Math_BigInteger
3075
  * @access private
3076
  */
@@ -3105,7 +3158,7 @@ class Math_BigInteger
3105
  * $max->random($min)
3106
  *
3107
  * @param Math_BigInteger $arg1
3108
- * @param optional Math_BigInteger $arg2
3109
  * @return Math_BigInteger
3110
  * @access public
3111
  * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a Math_BigInteger object.
@@ -3129,7 +3182,7 @@ class Math_BigInteger
3129
 
3130
  if (!$compare) {
3131
  return $this->_normalize($min);
3132
- } else if ($compare < 0) {
3133
  // if $min is bigger then $max, swap $min and $max
3134
  $temp = $max;
3135
  $max = $min;
@@ -3182,13 +3235,13 @@ class Math_BigInteger
3182
  /**
3183
  * Generate a random prime number.
3184
  *
3185
- * If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed,
3186
- * give up and return false.
3187
  *
3188
  * @param Math_BigInteger $arg1
3189
- * @param optional Math_BigInteger $arg2
3190
- * @param optional Integer $timeout
3191
- * @return Mixed
3192
  * @access public
3193
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
3194
  */
@@ -3210,7 +3263,7 @@ class Math_BigInteger
3210
 
3211
  if (!$compare) {
3212
  return $min->isPrime() ? $min : false;
3213
- } else if ($compare < 0) {
3214
  // if $min is bigger then $max, swap $min and $max
3215
  $temp = $max;
3216
  $max = $min;
@@ -3228,7 +3281,7 @@ class Math_BigInteger
3228
  $x = $this->random($min, $max);
3229
 
3230
  // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
3231
- if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
3232
  $p = new Math_BigInteger();
3233
  $p->value = gmp_nextprime($x->value);
3234
 
@@ -3289,12 +3342,12 @@ class Math_BigInteger
3289
  *
3290
  * If the current number is odd it'll be unchanged. If it's even, one will be added to it.
3291
  *
3292
- * @see randomPrime()
3293
  * @access private
3294
  */
3295
  function _make_odd()
3296
  {
3297
- switch ( MATH_BIGINTEGER_MODE ) {
3298
  case MATH_BIGINTEGER_MODE_GMP:
3299
  gmp_setbit($this->value, 0);
3300
  break;
@@ -3315,8 +3368,8 @@ class Math_BigInteger
3315
  * $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed across multiple pageloads
3316
  * on a website instead of just one.
3317
  *
3318
- * @param optional Math_BigInteger $t
3319
- * @return Boolean
3320
  * @access public
3321
  * @internal Uses the
3322
  * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
@@ -3346,7 +3399,7 @@ class Math_BigInteger
3346
 
3347
  // ie. gmp_testbit($this, 0)
3348
  // ie. isEven() or !isOdd()
3349
- switch ( MATH_BIGINTEGER_MODE ) {
3350
  case MATH_BIGINTEGER_MODE_GMP:
3351
  return gmp_prob_prime($this->value, $t) != 0;
3352
  case MATH_BIGINTEGER_MODE_BCMATH:
@@ -3383,7 +3436,7 @@ class Math_BigInteger
3383
  953, 967, 971, 977, 983, 991, 997
3384
  );
3385
 
3386
- if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
3387
  for ($i = 0; $i < count($primes); ++$i) {
3388
  $primes[$i] = new Math_BigInteger($primes[$i]);
3389
  }
@@ -3399,7 +3452,7 @@ class Math_BigInteger
3399
  }
3400
 
3401
  // see HAC 4.4.1 "Random search for probable primes"
3402
- if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) {
3403
  foreach ($primes as $prime) {
3404
  list(, $r) = $this->divide($prime);
3405
  if ($r->equals($zero)) {
@@ -3423,7 +3476,7 @@ class Math_BigInteger
3423
  $r = $n_1->copy();
3424
  $r_value = $r->value;
3425
  // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
3426
- if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) {
3427
  $s = 0;
3428
  // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
3429
  while ($r->value[strlen($r->value) - 1] % 2 == 0) {
@@ -3433,12 +3486,13 @@ class Math_BigInteger
3433
  } else {
3434
  for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
3435
  $temp = ~$r_value[$i] & 0xFFFFFF;
3436
- for ($j = 1; ($temp >> $j) & 1; ++$j);
 
3437
  if ($j != 25) {
3438
  break;
3439
  }
3440
  }
3441
- $s = 26 * $i + $j - 1;
3442
  $r->_rshift($s);
3443
  }
3444
 
@@ -3467,12 +3521,12 @@ class Math_BigInteger
3467
  *
3468
  * Shifts BigInteger's by $shift bits.
3469
  *
3470
- * @param Integer $shift
3471
  * @access private
3472
  */
3473
  function _lshift($shift)
3474
  {
3475
- if ( $shift == 0 ) {
3476
  return;
3477
  }
3478
 
@@ -3488,7 +3542,7 @@ class Math_BigInteger
3488
  $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
3489
  }
3490
 
3491
- if ( $carry ) {
3492
  $this->value[count($this->value)] = $carry;
3493
  }
3494
 
@@ -3502,7 +3556,7 @@ class Math_BigInteger
3502
  *
3503
  * Shifts BigInteger's by $shift bits.
3504
  *
3505
- * @param Integer $shift
3506
  * @access private
3507
  */
3508
  function _rshift($shift)
@@ -3516,7 +3570,7 @@ class Math_BigInteger
3516
  $carry_shift = MATH_BIGINTEGER_BASE - $shift;
3517
  $carry_mask = (1 << $shift) - 1;
3518
 
3519
- if ( $num_digits ) {
3520
  $this->value = array_slice($this->value, $num_digits);
3521
  }
3522
 
@@ -3538,7 +3592,7 @@ class Math_BigInteger
3538
  *
3539
  * @param Math_BigInteger
3540
  * @return Math_BigInteger
3541
- * @see _trim()
3542
  * @access private
3543
  */
3544
  function _normalize($result)
@@ -3546,9 +3600,9 @@ class Math_BigInteger
3546
  $result->precision = $this->precision;
3547
  $result->bitmask = $this->bitmask;
3548
 
3549
- switch ( MATH_BIGINTEGER_MODE ) {
3550
  case MATH_BIGINTEGER_MODE_GMP:
3551
- if (!empty($result->bitmask->value)) {
3552
  $result->value = gmp_and($result->value, $result->bitmask->value);
3553
  }
3554
 
@@ -3563,7 +3617,7 @@ class Math_BigInteger
3563
 
3564
  $value = &$result->value;
3565
 
3566
- if ( !count($value) ) {
3567
  return $result;
3568
  }
3569
 
@@ -3586,14 +3640,14 @@ class Math_BigInteger
3586
  *
3587
  * Removes leading zeros
3588
  *
3589
- * @param Array $value
3590
  * @return Math_BigInteger
3591
  * @access private
3592
  */
3593
  function _trim($value)
3594
  {
3595
  for ($i = count($value) - 1; $i >= 0; --$i) {
3596
- if ( $value[$i] ) {
3597
  break;
3598
  }
3599
  unset($value[$i]);
@@ -3607,7 +3661,7 @@ class Math_BigInteger
3607
  *
3608
  * @param $input Array
3609
  * @param $multiplier mixed
3610
- * @return Array
3611
  * @access private
3612
  */
3613
  function _array_repeat($input, $multiplier)
@@ -3622,7 +3676,7 @@ class Math_BigInteger
3622
  *
3623
  * @param $x String
3624
  * @param $shift Integer
3625
- * @return String
3626
  * @access private
3627
  */
3628
  function _base256_lshift(&$x, $shift)
@@ -3651,7 +3705,7 @@ class Math_BigInteger
3651
  *
3652
  * @param $x String
3653
  * @param $shift Integer
3654
- * @return String
3655
  * @access private
3656
  */
3657
  function _base256_rshift(&$x, $shift)
@@ -3691,8 +3745,8 @@ class Math_BigInteger
3691
  /**
3692
  * Converts 32-bit integers to bytes.
3693
  *
3694
- * @param Integer $x
3695
- * @return String
3696
  * @access private
3697
  */
3698
  function _int2bytes($x)
@@ -3703,8 +3757,8 @@ class Math_BigInteger
3703
  /**
3704
  * Converts bytes to 32-bit integers
3705
  *
3706
- * @param String $x
3707
- * @return Integer
3708
  * @access private
3709
  */
3710
  function _bytes2int($x)
@@ -3718,10 +3772,10 @@ class Math_BigInteger
3718
  *
3719
  * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
3720
  *
3721
- * @see modPow()
3722
  * @access private
3723
- * @param Integer $length
3724
- * @return String
3725
  */
3726
  function _encodeASN1Length($length)
3727
  {
@@ -3742,9 +3796,9 @@ class Math_BigInteger
3742
  * we'll guarantee that the dividend is divisible by first subtracting the remainder.
3743
  *
3744
  * @access private
3745
- * @param Integer $x
3746
- * @param Integer $y
3747
- * @return Integer
3748
  */
3749
  function _safe_divide($x, $y)
3750
  {
72
  * Reduction constants
73
  *
74
  * @access private
75
+ * @see self::_reduce()
76
  */
77
  /**
78
+ * @see self::_montgomery()
79
+ * @see self::_prepMontgomery()
80
  */
81
  define('MATH_BIGINTEGER_MONTGOMERY', 0);
82
  /**
83
+ * @see self::_barrett()
84
  */
85
  define('MATH_BIGINTEGER_BARRETT', 1);
86
  /**
87
+ * @see self::_mod2()
88
  */
89
  define('MATH_BIGINTEGER_POWEROF2', 2);
90
  /**
91
+ * @see self::_remainder()
92
  */
93
  define('MATH_BIGINTEGER_CLASSIC', 3);
94
  /**
95
+ * @see self::__clone()
96
  */
97
  define('MATH_BIGINTEGER_NONE', 4);
98
  /**#@-*/
117
 
118
  /**#@+
119
  * @access private
120
+ * @see self::_montgomery()
121
+ * @see self::_barrett()
122
  */
123
  /**
124
  * Cache constants
136
  * Mode constants.
137
  *
138
  * @access private
139
+ * @see self::Math_BigInteger()
140
  */
141
  /**
142
  * To use the pure-PHP implementation
178
  /**
179
  * Holds the BigInteger's value.
180
  *
181
+ * @var array
182
  * @access private
183
  */
184
  var $value;
186
  /**
187
  * Holds the BigInteger's magnitude.
188
  *
189
+ * @var bool
190
  * @access private
191
  */
192
  var $is_negative = false;
193
 
 
 
 
 
 
 
 
 
194
  /**
195
  * Precision
196
  *
197
+ * @see self::setPrecision()
198
  * @access private
199
  */
200
  var $precision = -1;
202
  /**
203
  * Precision Bitmask
204
  *
205
+ * @see self::setPrecision()
206
  * @access private
207
  */
208
  var $bitmask = false;
214
  * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
215
  * however, $this->hex is only calculated when $this->__sleep() is called.
216
  *
217
+ * @see self::__sleep()
218
+ * @see self::__wakeup()
219
+ * @var string
220
  * @access private
221
  */
222
  var $hex;
238
  * ?>
239
  * </code>
240
  *
241
+ * @param $x base-10 number or base-$base number if $base set.
242
+ * @param int $base
243
  * @return Math_BigInteger
244
  * @access public
245
  */
246
+ function __construct($x = 0, $base = 10)
247
  {
248
+ if (!defined('MATH_BIGINTEGER_MODE')) {
249
  switch (true) {
250
  case extension_loaded('gmp'):
251
  define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
258
  }
259
  }
260
 
261
+ if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
262
  // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
263
  ob_start();
264
  @phpinfo();
286
  case !isset($versions['Header']):
287
  case !isset($versions['Library']):
288
  case $versions['Header'] == $versions['Library']:
289
+ case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0:
290
  define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
291
  break;
292
  default:
327
  }
328
  }
329
 
330
+ switch (MATH_BIGINTEGER_MODE) {
331
  case MATH_BIGINTEGER_MODE_GMP:
332
  switch (true) {
333
  case is_resource($x) && get_resource_type($x) == 'GMP integer':
357
  $x = ~$x;
358
  $this->is_negative = true;
359
  }
360
+ case 256:
361
+ switch (MATH_BIGINTEGER_MODE) {
362
  case MATH_BIGINTEGER_MODE_GMP:
363
+ $this->value = function_exists('gmp_import') ?
364
+ gmp_import($x) :
365
+ gmp_init('0x' . bin2hex($x));
366
+ if ($this->is_negative) {
367
+ $this->value = gmp_neg($this->value);
368
+ }
369
  break;
370
  case MATH_BIGINTEGER_MODE_BCMATH:
371
  // round $len to the nearest 4 (thanks, DavidMJ!)
398
  $this->value = $temp->value;
399
  }
400
  break;
401
+ case 16:
402
  case -16:
403
  if ($base > 0 && $x[0] == '-') {
404
  $this->is_negative = true;
413
  $x = bin2hex(~pack('H*', $x));
414
  }
415
 
416
+ switch (MATH_BIGINTEGER_MODE) {
417
  case MATH_BIGINTEGER_MODE_GMP:
418
  $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
419
  $this->value = gmp_init($temp);
420
  $this->is_negative = false;
421
  break;
422
  case MATH_BIGINTEGER_MODE_BCMATH:
423
+ $x = (strlen($x) & 1) ? '0' . $x : $x;
424
  $temp = new Math_BigInteger(pack('H*', $x), 256);
425
  $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
426
  $this->is_negative = false;
427
  break;
428
  default:
429
+ $x = (strlen($x) & 1) ? '0' . $x : $x;
430
  $temp = new Math_BigInteger(pack('H*', $x), 256);
431
  $this->value = $temp->value;
432
  }
436
  $this->value = $temp->value;
437
  }
438
  break;
439
+ case 10:
440
  case -10:
441
  // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
442
  // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
443
  // [^-0-9].*: find any non-numeric characters and then any characters that follow that
444
  $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
445
 
446
+ switch (MATH_BIGINTEGER_MODE) {
447
  case MATH_BIGINTEGER_MODE_GMP:
448
  $this->value = gmp_init($x);
449
  break;
473
  $this->value = $temp->value;
474
  }
475
  break;
476
+ case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
477
  case -2:
478
  if ($base > 0 && $x[0] == '-') {
479
  $this->is_negative = true;
504
  }
505
  }
506
 
507
+ /**
508
+ * PHP4 compatible Default Constructor.
509
+ *
510
+ * @see self::__construct()
511
+ * @param $x base-10 number or base-$base number if $base set.
512
+ * @param int $base
513
+ * @access public
514
+ */
515
+ function Math_BigInteger($x = 0, $base = 10)
516
+ {
517
+ $this->__construct($x, $base);
518
+ }
519
+
520
  /**
521
  * Converts a BigInteger to a byte string (eg. base-256).
522
  *
534
  * ?>
535
  * </code>
536
  *
537
+ * @param bool $twos_compliment
538
+ * @return string
539
  * @access public
540
  * @internal Converts a base-2**26 number to base-2**8
541
  */
561
  return $comparison < 0 ? ~$bytes : $bytes;
562
  }
563
 
564
+ switch (MATH_BIGINTEGER_MODE) {
565
  case MATH_BIGINTEGER_MODE_GMP:
566
  if (gmp_cmp($this->value, gmp_init(0)) == 0) {
567
  return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
568
  }
569
 
570
+ if (function_exists('gmp_export')) {
571
+ $temp = gmp_export($this->value);
572
+ } else {
573
+ $temp = gmp_strval(gmp_abs($this->value), 16);
574
+ $temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
575
+ $temp = pack('H*', $temp);
576
+ }
577
 
578
  return $this->precision > 0 ?
579
  substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
635
  * ?>
636
  * </code>
637
  *
638
+ * @param bool $twos_compliment
639
+ * @return string
640
  * @access public
641
  * @internal Converts a base-2**26 number to base-2**8
642
  */
662
  * ?>
663
  * </code>
664
  *
665
+ * @param bool $twos_compliment
666
+ * @return string
667
  * @access public
668
  * @internal Converts a base-2**26 number to base-2**2
669
  */
700
  * ?>
701
  * </code>
702
  *
703
+ * @return string
704
  * @access public
705
  * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
706
  */
707
  function toString()
708
  {
709
+ switch (MATH_BIGINTEGER_MODE) {
710
  case MATH_BIGINTEGER_MODE_GMP:
711
  return gmp_strval($this->value);
712
  case MATH_BIGINTEGER_MODE_BCMATH:
752
  * {@link http://php.net/language.oop5.basic#51624}
753
  *
754
  * @access public
755
+ * @see self::__clone()
756
  * @return Math_BigInteger
757
  */
758
  function copy()
760
  $temp = new Math_BigInteger();
761
  $temp->value = $this->value;
762
  $temp->is_negative = $this->is_negative;
 
763
  $temp->precision = $this->precision;
764
  $temp->bitmask = $this->bitmask;
765
  return $temp;
788
  * call Math_BigInteger::copy(), instead.
789
  *
790
  * @access public
791
+ * @see self::copy()
792
  * @return Math_BigInteger
793
  */
794
  function __clone()
801
  *
802
  * Will be called, automatically, when serialize() is called on a Math_BigInteger object.
803
  *
804
+ * @see self::__wakeup()
805
  * @access public
806
  */
807
  function __sleep()
808
  {
809
  $this->hex = $this->toHex(true);
810
  $vars = array('hex');
 
 
 
811
  if ($this->precision > 0) {
812
  $vars[] = 'precision';
813
  }
814
  return $vars;
 
815
  }
816
 
817
  /**
819
  *
820
  * Will be called, automatically, when unserialize() is called on a Math_BigInteger object.
821
  *
822
+ * @see self::__sleep()
823
  * @access public
824
  */
825
  function __wakeup()
827
  $temp = new Math_BigInteger($this->hex, -16);
828
  $this->value = $temp->value;
829
  $this->is_negative = $temp->is_negative;
 
830
  if ($this->precision > 0) {
831
  // recalculate $this->bitmask
832
  $this->setPrecision($this->precision);
833
  }
834
  }
835
 
836
+ /**
837
+ * __debugInfo() magic method
838
+ *
839
+ * Will be called, automatically, when print_r() or var_dump() are called
840
+ *
841
+ * @access public
842
+ */
843
+ function __debugInfo()
844
+ {
845
+ $opts = array();
846
+ switch (MATH_BIGINTEGER_MODE) {
847
+ case MATH_BIGINTEGER_MODE_GMP:
848
+ $engine = 'gmp';
849
+ break;
850
+ case MATH_BIGINTEGER_MODE_BCMATH:
851
+ $engine = 'bcmath';
852
+ break;
853
+ case MATH_BIGINTEGER_MODE_INTERNAL:
854
+ $engine = 'internal';
855
+ $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit';
856
+ }
857
+ if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
858
+ $opts[] = 'OpenSSL';
859
+ }
860
+ if (!empty($opts)) {
861
+ $engine.= ' (' . implode($opts, ', ') . ')';
862
+ }
863
+ return array(
864
+ 'value' => '0x' . $this->toHex(true),
865
+ 'engine' => $engine
866
+ );
867
+ }
868
+
869
  /**
870
  * Adds two BigIntegers.
871
  *
890
  */
891
  function add($y)
892
  {
893
+ switch (MATH_BIGINTEGER_MODE) {
894
  case MATH_BIGINTEGER_MODE_GMP:
895
  $temp = new Math_BigInteger();
896
  $temp->value = gmp_add($this->value, $y->value);
915
  /**
916
  * Performs addition.
917
  *
918
+ * @param array $x_value
919
+ * @param bool $x_negative
920
+ * @param array $y_value
921
+ * @param bool $y_negative
922
+ * @return array
923
  * @access private
924
  */
925
  function _add($x_value, $x_negative, $y_value, $y_negative)
932
  MATH_BIGINTEGER_VALUE => $y_value,
933
  MATH_BIGINTEGER_SIGN => $y_negative
934
  );
935
+ } elseif ($y_size == 0) {
936
  return array(
937
  MATH_BIGINTEGER_VALUE => $x_value,
938
  MATH_BIGINTEGER_SIGN => $x_negative
940
  }
941
 
942
  // subtract, if appropriate
943
+ if ($x_negative != $y_negative) {
944
+ if ($x_value == $y_value) {
945
  return array(
946
  MATH_BIGINTEGER_VALUE => array(),
947
  MATH_BIGINTEGER_SIGN => false
1021
  */
1022
  function subtract($y)
1023
  {
1024
+ switch (MATH_BIGINTEGER_MODE) {
1025
  case MATH_BIGINTEGER_MODE_GMP:
1026
  $temp = new Math_BigInteger();
1027
  $temp->value = gmp_sub($this->value, $y->value);
1046
  /**
1047
  * Performs subtraction.
1048
  *
1049
+ * @param array $x_value
1050
+ * @param bool $x_negative
1051
+ * @param array $y_value
1052
+ * @param bool $y_negative
1053
+ * @return array
1054
  * @access private
1055
  */
1056
  function _subtract($x_value, $x_negative, $y_value, $y_negative)
1063
  MATH_BIGINTEGER_VALUE => $y_value,
1064
  MATH_BIGINTEGER_SIGN => !$y_negative
1065
  );
1066
+ } elseif ($y_size == 0) {
1067
  return array(
1068
  MATH_BIGINTEGER_VALUE => $x_value,
1069
  MATH_BIGINTEGER_SIGN => $x_negative
1071
  }
1072
 
1073
  // add, if appropriate (ie. -$x - +$y or +$x - -$y)
1074
+ if ($x_negative != $y_negative) {
1075
  $temp = $this->_add($x_value, false, $y_value, false);
1076
  $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
1077
 
1080
 
1081
  $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
1082
 
1083
+ if (!$diff) {
1084
  return array(
1085
  MATH_BIGINTEGER_VALUE => array(),
1086
  MATH_BIGINTEGER_SIGN => false
1088
  }
1089
 
1090
  // switch $x and $y around, if appropriate.
1091
+ if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
1092
  $temp = $x_value;
1093
  $x_value = $y_value;
1094
  $y_value = $temp;
1156
  */
1157
  function multiply($x)
1158
  {
1159
+ switch (MATH_BIGINTEGER_MODE) {
1160
  case MATH_BIGINTEGER_MODE_GMP:
1161
  $temp = new Math_BigInteger();
1162
  $temp->value = gmp_mul($this->value, $x->value);
1181
  /**
1182
  * Performs multiplication.
1183
  *
1184
+ * @param array $x_value
1185
+ * @param bool $x_negative
1186
+ * @param array $y_value
1187
+ * @param bool $y_negative
1188
+ * @return array
1189
  * @access private
1190
  */
1191
  function _multiply($x_value, $x_negative, $y_value, $y_negative)
1200
  $x_length = count($x_value);
1201
  $y_length = count($y_value);
1202
 
1203
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
1204
  return array(
1205
  MATH_BIGINTEGER_VALUE => array(),
1206
  MATH_BIGINTEGER_SIGN => false
1220
  *
1221
  * Modeled after 'multiply' in MutableBigInteger.java.
1222
  *
1223
+ * @param array $x_value
1224
+ * @param array $y_value
1225
+ * @return array
1226
  * @access private
1227
  */
1228
  function _regularMultiply($x_value, $y_value)
1230
  $x_length = count($x_value);
1231
  $y_length = count($y_value);
1232
 
1233
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
1234
  return array();
1235
  }
1236
 
1237
+ if ($x_length < $y_length) {
1238
  $temp = $x_value;
1239
  $x_value = $y_value;
1240
  $y_value = $temp;
1284
  * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1285
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
1286
  *
1287
+ * @param array $x_value
1288
+ * @param array $y_value
1289
+ * @return array
1290
  * @access private
1291
  */
1292
  function _karatsuba($x_value, $y_value)
1323
  /**
1324
  * Performs squaring
1325
  *
1326
+ * @param array $x
1327
+ * @return array
1328
  * @access private
1329
  */
1330
  function _square($x = false)
1341
  * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
1342
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
1343
  *
1344
+ * @param array $value
1345
+ * @return array
1346
  * @access private
1347
  */
1348
  function _baseSquare($value)
1349
  {
1350
+ if (empty($value)) {
1351
  return array();
1352
  }
1353
  $square_value = $this->_array_repeat(0, 2 * count($value));
1380
  * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
1381
  * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
1382
  *
1383
+ * @param array $value
1384
+ * @return array
1385
  * @access private
1386
  */
1387
  function _karatsubaSquare($value)
1437
  * </code>
1438
  *
1439
  * @param Math_BigInteger $y
1440
+ * @return array
1441
  * @access public
1442
  * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
1443
  */
1444
  function divide($y)
1445
  {
1446
+ switch (MATH_BIGINTEGER_MODE) {
1447
  case MATH_BIGINTEGER_MODE_GMP:
1448
  $quotient = new Math_BigInteger();
1449
  $remainder = new Math_BigInteger();
1480
  }
1481
 
1482
  static $zero;
1483
+ if (!isset($zero)) {
1484
  $zero = new Math_BigInteger();
1485
  }
1486
 
1494
 
1495
  $diff = $x->compare($y);
1496
 
1497
+ if (!$diff) {
1498
  $temp = new Math_BigInteger();
1499
  $temp->value = array(1);
1500
  $temp->is_negative = $x_sign != $y_sign;
1501
  return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
1502
  }
1503
 
1504
+ if ($diff < 0) {
1505
  // if $x is negative, "add" $y.
1506
+ if ($x_sign) {
1507
  $x = $y->subtract($x);
1508
  }
1509
  return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
1537
  // $temp = $y << ($x_max - $y_max-1) in base 2**26
1538
  $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
1539
 
1540
+ while ($x->compare($temp) >= 0) {
1541
  // calculate the "common residue"
1542
  ++$quotient_value[$x_max - $y_max];
1543
  $x = $x->subtract($temp);
1553
  );
1554
  $y_window = array(
1555
  $y_value[$y_max],
1556
+ ($y_max > 0) ? $y_value[$y_max - 1] : 0
1557
  );
1558
 
1559
  $q_index = $i - $y_max - 1;
1573
 
1574
  $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
1575
 
1576
+ while ($lhs->compare($rhs) > 0) {
1577
  --$quotient_value[$q_index];
1578
 
1579
  $lhs->value = array($quotient_value[$q_index]);
1604
  $quotient->is_negative = $x_sign != $y_sign;
1605
 
1606
  // calculate the "common residue", if appropriate
1607
+ if ($x_sign) {
1608
  $y->_rshift($shift);
1609
  $x = $y->subtract($x);
1610
  }
1617
  *
1618
  * abc / x = a00 / x + b0 / x + c / x
1619
  *
1620
+ * @param array $dividend
1621
+ * @param array $divisor
1622
+ * @return array
1623
  * @access private
1624
  */
1625
  function _divide_digit($dividend, $divisor)
1693
  return $this->_normalize($temp->modPow($e, $n));
1694
  }
1695
 
1696
+ if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) {
1697
  $temp = new Math_BigInteger();
1698
  $temp->value = gmp_powm($this->value, $e->value, $n->value);
1699
 
1716
  'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
1717
  );
1718
 
1719
+ $RSAPublicKey = pack(
1720
+ 'Ca*a*a*',
1721
+ 48,
1722
+ $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
1723
+ $components['modulus'],
1724
+ $components['publicExponent']
1725
  );
1726
 
1727
  $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
1728
  $RSAPublicKey = chr(0) . $RSAPublicKey;
1729
  $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
1730
 
1731
+ $encapsulated = pack(
1732
+ 'Ca*a*',
1733
+ 48,
1734
+ $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)),
1735
+ $rsaOID . $RSAPublicKey
1736
  );
1737
 
1738
  $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
1746
  }
1747
  }
1748
 
1749
+ if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
1750
+ $temp = new Math_BigInteger();
1751
+ $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
1752
 
1753
+ return $this->_normalize($temp);
1754
  }
1755
 
1756
+ if (empty($e->value)) {
1757
  $temp = new Math_BigInteger();
1758
  $temp->value = array(1);
1759
  return $this->_normalize($temp);
1760
  }
1761
 
1762
+ if ($e->value == array(1)) {
1763
  list(, $temp) = $this->divide($n);
1764
  return $this->_normalize($temp);
1765
  }
1766
 
1767
+ if ($e->value == array(2)) {
1768
  $temp = new Math_BigInteger();
1769
  $temp->value = $this->_square($this->value);
1770
  list(, $temp) = $temp->divide($n);
1779
  // made uncallable
1780
 
1781
  // is the modulo odd?
1782
+ if ($n->value[0] & 1) {
1783
  return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
1784
  }
1785
  // if it's not, it's even
1786
 
1787
  // find the lowest set bit (eg. the max pow of 2 that divides $n)
1788
  for ($i = 0; $i < count($n->value); ++$i) {
1789
+ if ($n->value[$i]) {
1790
  $temp = decbin($n->value[$i]);
1791
  $j = strlen($temp) - strrpos($temp, '1') - 1;
1792
  $j+= 26 * $i;
1801
  $mod2->value = array(1);
1802
  $mod2->_lshift($j);
1803
 
1804
+ $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger();
1805
  $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2);
1806
 
1807
  $y1 = $mod2->modInverse($mod1);
1844
  *
1845
  * @param Math_BigInteger $e
1846
  * @param Math_BigInteger $n
1847
+ * @param int $mode
1848
  * @return Math_BigInteger
1849
  * @access private
1850
  */
1864
 
1865
  // calculate the appropriate window size.
1866
  // $window_size == 3 if $window_ranges is between 25 and 81, for example.
1867
+ for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
1868
+ }
1869
 
1870
  $n_value = $n->value;
1871
 
1885
  $result = array(1);
1886
  $result = $this->_prepareReduce($result, $n_value, $mode);
1887
 
1888
+ for ($i = 0; $i < $e_length;) {
1889
+ if (!$e_bits[$i]) {
1890
  $result = $this->_squareReduce($result, $n_value, $mode);
1891
  ++$i;
1892
  } else {
1893
  for ($j = $window_size - 1; $j > 0; --$j) {
1894
+ if (!empty($e_bits[$i + $j])) {
1895
  break;
1896
  }
1897
  }
1898
 
1899
+ // eg. the length of substr($e_bits, $i, $j + 1)
1900
+ for ($k = 0; $k <= $j; ++$k) {
1901
  $result = $this->_squareReduce($result, $n_value, $mode);
1902
  }
1903
 
1904
  $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode);
1905
 
1906
+ $i += $j + 1;
1907
  }
1908
  }
1909
 
1918
  *
1919
  * For most $modes this will return the remainder.
1920
  *
1921
+ * @see self::_slidingWindow()
1922
  * @access private
1923
+ * @param array $x
1924
+ * @param array $n
1925
+ * @param int $mode
1926
+ * @return array
1927
  */
1928
  function _reduce($x, $n, $mode)
1929
  {
1955
  /**
1956
  * Modular reduction preperation
1957
  *
1958
+ * @see self::_slidingWindow()
1959
  * @access private
1960
+ * @param array $x
1961
+ * @param array $n
1962
+ * @param int $mode
1963
+ * @return array
1964
  */
1965
  function _prepareReduce($x, $n, $mode)
1966
  {
1973
  /**
1974
  * Modular multiply
1975
  *
1976
+ * @see self::_slidingWindow()
1977
  * @access private
1978
+ * @param array $x
1979
+ * @param array $y
1980
+ * @param array $n
1981
+ * @param int $mode
1982
+ * @return array
1983
  */
1984
  function _multiplyReduce($x, $y, $n, $mode)
1985
  {
1993
  /**
1994
  * Modular square
1995
  *
1996
+ * @see self::_slidingWindow()
1997
  * @access private
1998
+ * @param array $x
1999
+ * @param array $n
2000
+ * @param int $mode
2001
+ * @return array
2002
  */
2003
  function _squareReduce($x, $n, $mode)
2004
  {
2014
  * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
2015
  * we'll just use this function as a wrapper for doing that.
2016
  *
2017
+ * @see self::_slidingWindow()
2018
  * @access private
2019
  * @param Math_BigInteger
2020
  * @return Math_BigInteger
2044
  * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line
2045
  * comments for details.
2046
  *
2047
+ * @see self::_slidingWindow()
2048
  * @access private
2049
+ * @param array $n
2050
+ * @param array $m
2051
+ * @return array
2052
  */
2053
  function _barrett($n, $m)
2054
  {
2076
 
2077
  // n = 2 * m.length
2078
 
2079
+ if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
2080
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2081
  $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
2082
 
2141
  * For numbers with more than four digits Math_BigInteger::_barrett() is faster. The difference between that and this
2142
  * is that this function does not fold the denominator into a smaller form.
2143
  *
2144
+ * @see self::_slidingWindow()
2145
  * @access private
2146
+ * @param array $x
2147
+ * @param array $n
2148
+ * @return array
2149
  */
2150
  function _regularBarrett($x, $n)
2151
  {
2165
  return $temp->value;
2166
  }
2167
 
2168
+ if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
2169
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2170
  $cache[MATH_BIGINTEGER_VARIABLE][] = $n;
2171
  $lhs = new Math_BigInteger();
2212
  *
2213
  * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
2214
  *
2215
+ * @see self::_regularBarrett()
2216
+ * @param array $x_value
2217
+ * @param bool $x_negative
2218
+ * @param array $y_value
2219
+ * @param bool $y_negative
2220
+ * @param int $stop
2221
+ * @return array
2222
  * @access private
2223
  */
2224
  function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop)
2226
  $x_length = count($x_value);
2227
  $y_length = count($y_value);
2228
 
2229
+ if (!$x_length || !$y_length) { // a 0 is being multiplied
2230
  return array(
2231
  MATH_BIGINTEGER_VALUE => array(),
2232
  MATH_BIGINTEGER_SIGN => false
2233
  );
2234
  }
2235
 
2236
+ if ($x_length < $y_length) {
2237
  $temp = $x_value;
2238
  $x_value = $y_value;
2239
  $y_value = $temp;
2293
  * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
2294
  * to work correctly.
2295
  *
2296
+ * @see self::_prepMontgomery()
2297
+ * @see self::_slidingWindow()
2298
  * @access private
2299
+ * @param array $x
2300
+ * @param array $n
2301
+ * @return array
2302
  */
2303
  function _montgomery($x, $n)
2304
  {
2307
  MATH_BIGINTEGER_DATA => array()
2308
  );
2309
 
2310
+ if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
2311
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2312
  $cache[MATH_BIGINTEGER_VARIABLE][] = $x;
2313
  $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
2340
  * Interleaves the montgomery reduction and long multiplication algorithms together as described in
2341
  * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
2342
  *
2343
+ * @see self::_prepMontgomery()
2344
+ * @see self::_montgomery()
2345
  * @access private
2346
+ * @param array $x
2347
+ * @param array $y
2348
+ * @param array $m
2349
+ * @return array
2350
  */
2351
  function _montgomeryMultiply($x, $y, $m)
2352
  {
2363
  MATH_BIGINTEGER_DATA => array()
2364
  );
2365
 
2366
+ if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
2367
  $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
2368
  $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
2369
  $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
2392
  /**
2393
  * Prepare a number for use in Montgomery Modular Reductions
2394
  *
2395
+ * @see self::_montgomery()
2396
+ * @see self::_slidingWindow()
2397
  * @access private
2398
+ * @param array $x
2399
+ * @param array $n
2400
+ * @return array
2401
  */
2402
  function _prepMontgomery($x, $n)
2403
  {
2431
  *
2432
  * Thanks to Pedro Gimeno Fortea for input!
2433
  *
2434
+ * @see self::_montgomery()
2435
  * @access private
2436
+ * @param array $x
2437
+ * @return int
2438
  */
2439
  function _modInverse67108864($x) // 2**26 == 67,108,864
2440
  {
2472
  * </code>
2473
  *
2474
  * @param Math_BigInteger $n
2475
+ * @return Math_BigInteger|false
2476
  * @access public
2477
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
2478
  */
2479
  function modInverse($n)
2480
  {
2481
+ switch (MATH_BIGINTEGER_MODE) {
2482
  case MATH_BIGINTEGER_MODE_GMP:
2483
  $temp = new Math_BigInteger();
2484
  $temp->value = gmp_invert($this->value, $n->value);
2485
 
2486
+ return ($temp->value === false) ? false : $this->_normalize($temp);
2487
  }
2488
 
2489
  static $zero, $one;
2517
  *
2518
  * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
2519
  * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
2520
+ * combination is returned is dependent upon which mode is in use. See
2521
  * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
2522
  *
2523
  * Here's an example:
2544
  */
2545
  function extendedGCD($n)
2546
  {
2547
+ switch (MATH_BIGINTEGER_MODE) {
2548
  case MATH_BIGINTEGER_MODE_GMP:
2549
  extract(gmp_gcdext($this->value, $n->value));
2550
 
2594
  $g = new Math_BigInteger();
2595
  $g->value = array(1);
2596
 
2597
+ while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) {
2598
  $x->_rshift(1);
2599
  $y->_rshift(1);
2600
  $g->_lshift(1);
2611
  $a->value = $d->value = $g->value = array(1);
2612
  $b->value = $c->value = array();
2613
 
2614
+ while (!empty($u->value)) {
2615
+ while (!($u->value[0] & 1)) {
2616
  $u->_rshift(1);
2617
+ if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) {
2618
  $a = $a->add($y);
2619
  $b = $b->subtract($x);
2620
  }
2622
  $b->_rshift(1);
2623
  }
2624
 
2625
+ while (!($v->value[0] & 1)) {
2626
  $v->_rshift(1);
2627
+ if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) {
2628
  $c = $c->add($y);
2629
  $d = $d->subtract($x);
2630
  }
2689
  {
2690
  $temp = new Math_BigInteger();
2691
 
2692
+ switch (MATH_BIGINTEGER_MODE) {
2693
  case MATH_BIGINTEGER_MODE_GMP:
2694
  $temp->value = gmp_abs($this->value);
2695
  break;
2716
  * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
2717
  *
2718
  * @param Math_BigInteger $y
2719
+ * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
2720
  * @access public
2721
+ * @see self::equals()
2722
  * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
2723
  */
2724
  function compare($y)
2725
  {
2726
+ switch (MATH_BIGINTEGER_MODE) {
2727
  case MATH_BIGINTEGER_MODE_GMP:
2728
  return gmp_cmp($this->value, $y->value);
2729
  case MATH_BIGINTEGER_MODE_BCMATH:
2736
  /**
2737
  * Compares two numbers.
2738
  *
2739
+ * @param array $x_value
2740
+ * @param bool $x_negative
2741
+ * @param array $y_value
2742
+ * @param bool $y_negative
2743
+ * @return int
2744
+ * @see self::compare()
2745
  * @access private
2746
  */
2747
  function _compare($x_value, $x_negative, $y_value, $y_negative)
2748
  {
2749
+ if ($x_negative != $y_negative) {
2750
+ return (!$x_negative && $y_negative) ? 1 : -1;
2751
  }
2752
 
2753
  $result = $x_negative ? -1 : 1;
2754
 
2755
+ if (count($x_value) != count($y_value)) {
2756
+ return (count($x_value) > count($y_value)) ? $result : -$result;
2757
  }
2758
  $size = max(count($x_value), count($y_value));
2759
 
2762
 
2763
  for ($i = count($x_value) - 1; $i >= 0; --$i) {
2764
  if ($x_value[$i] != $y_value[$i]) {
2765
+ return ($x_value[$i] > $y_value[$i]) ? $result : -$result;
2766
  }
2767
  }
2768
 
2775
  * If you need to see if one number is greater than or less than another number, use Math_BigInteger::compare()
2776
  *
2777
  * @param Math_BigInteger $x
2778
+ * @return bool
2779
  * @access public
2780
+ * @see self::compare()
2781
  */
2782
  function equals($x)
2783
  {
2784
+ switch (MATH_BIGINTEGER_MODE) {
2785
  case MATH_BIGINTEGER_MODE_GMP:
2786
  return gmp_cmp($this->value, $x->value) == 0;
2787
  default:
2795
  * Some bitwise operations give different results depending on the precision being used. Examples include left
2796
  * shift, not, and rotates.
2797
  *
2798
+ * @param int $bits
2799
  * @access public
2800
  */
2801
  function setPrecision($bits)
2802
  {
2803
  $this->precision = $bits;
2804
+ if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH) {
2805
  $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
2806
  } else {
2807
  $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
2821
  */
2822
  function bitwise_and($x)
2823
  {
2824
+ switch (MATH_BIGINTEGER_MODE) {
2825
  case MATH_BIGINTEGER_MODE_GMP:
2826
  $temp = new Math_BigInteger();
2827
  $temp->value = gmp_and($this->value, $x->value);
2862
  */
2863
  function bitwise_or($x)
2864
  {
2865
+ switch (MATH_BIGINTEGER_MODE) {
2866
  case MATH_BIGINTEGER_MODE_GMP:
2867
  $temp = new Math_BigInteger();
2868
  $temp->value = gmp_or($this->value, $x->value);
2902
  */
2903
  function bitwise_xor($x)
2904
  {
2905
+ switch (MATH_BIGINTEGER_MODE) {
2906
  case MATH_BIGINTEGER_MODE_GMP:
2907
  $temp = new Math_BigInteger();
2908
  $temp->value = gmp_xor($this->value, $x->value);
2944
  // calculuate "not" without regard to $this->precision
2945
  // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
2946
  $temp = $this->toBytes();
2947
+ if ($temp == '') {
2948
+ return $this->_normalize(new Math_BigInteger());
2949
+ }
2950
  $pre_msb = decbin(ord($temp[0]));
2951
  $temp = ~$temp;
2952
  $msb = decbin(ord($temp[0]));
2976
  *
2977
  * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
2978
  *
2979
+ * @param int $shift
2980
  * @return Math_BigInteger
2981
  * @access public
2982
  * @internal The only version that yields any speed increases is the internal version.
2985
  {
2986
  $temp = new Math_BigInteger();
2987
 
2988
+ switch (MATH_BIGINTEGER_MODE) {
2989
  case MATH_BIGINTEGER_MODE_GMP:
2990
  static $two;
2991
 
3014
  *
3015
  * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
3016
  *
3017
+ * @param int $shift
3018
  * @return Math_BigInteger
3019
  * @access public
3020
  * @internal The only version that yields any speed increases is the internal version.
3023
  {
3024
  $temp = new Math_BigInteger();
3025
 
3026
+ switch (MATH_BIGINTEGER_MODE) {
3027
  case MATH_BIGINTEGER_MODE_GMP:
3028
  static $two;
3029
 
3052
  *
3053
  * Instead of the top x bits being dropped they're appended to the shifted bit string.
3054
  *
3055
+ * @param int $shift
3056
  * @return Math_BigInteger
3057
  * @access public
3058
  */
3062
 
3063
  if ($this->precision > 0) {
3064
  $precision = $this->precision;
3065
+ if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
3066
  $mask = $this->bitmask->subtract(new Math_BigInteger(1));
3067
  $mask = $mask->toBytes();
3068
  } else {
3070
  }
3071
  } else {
3072
  $temp = ord($bits[0]);
3073
+ for ($i = 0; $temp >> $i; ++$i) {
3074
+ }
3075
  $precision = 8 * strlen($bits) - 8 + $i;
3076
  $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
3077
  }
3097
  *
3098
  * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
3099
  *
3100
+ * @param int $shift
3101
  * @return Math_BigInteger
3102
  * @access public
3103
  */
3111
  *
3112
  * This function is deprecated.
3113
  *
3114
+ * @param string $generator
3115
  * @access public
3116
  */
3117
  function setRandomGenerator($generator)
3123
  *
3124
  * Byte length is equal to $length. Uses crypt_random if it's loaded and mt_rand if it's not.
3125
  *
3126
+ * @param int $length
3127
  * @return Math_BigInteger
3128
  * @access private
3129
  */
3158
  * $max->random($min)
3159
  *
3160
  * @param Math_BigInteger $arg1
3161
+ * @param Math_BigInteger $arg2
3162
  * @return Math_BigInteger
3163
  * @access public
3164
  * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a Math_BigInteger object.
3182
 
3183
  if (!$compare) {
3184
  return $this->_normalize($min);
3185
+ } elseif ($compare < 0) {
3186
  // if $min is bigger then $max, swap $min and $max
3187
  $temp = $max;
3188
  $max = $min;
3235
  /**
3236
  * Generate a random prime number.
3237
  *
3238
+ * If there's not a prime within the given range, false will be returned.
3239
+ * If more than $timeout seconds have elapsed, give up and return false.
3240
  *
3241
  * @param Math_BigInteger $arg1
3242
+ * @param Math_BigInteger $arg2
3243
+ * @param int $timeout
3244
+ * @return Math_BigInteger|false
3245
  * @access public
3246
  * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
3247
  */
3263
 
3264
  if (!$compare) {
3265
  return $min->isPrime() ? $min : false;
3266
+ } elseif ($compare < 0) {
3267
  // if $min is bigger then $max, swap $min and $max
3268
  $temp = $max;
3269
  $max = $min;
3281
  $x = $this->random($min, $max);
3282
 
3283
  // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
3284
+ if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && extension_loaded('gmp') && version_compare(PHP_VERSION, '5.2.0', '>=')) {
3285
  $p = new Math_BigInteger();
3286
  $p->value = gmp_nextprime($x->value);
3287
 
3342
  *
3343
  * If the current number is odd it'll be unchanged. If it's even, one will be added to it.
3344
  *
3345
+ * @see self::randomPrime()
3346
  * @access private
3347
  */
3348
  function _make_odd()
3349
  {
3350
+ switch (MATH_BIGINTEGER_MODE) {
3351
  case MATH_BIGINTEGER_MODE_GMP:
3352
  gmp_setbit($this->value, 0);
3353
  break;
3368
  * $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed across multiple pageloads
3369
  * on a website instead of just one.
3370
  *
3371
+ * @param Math_BigInteger $t
3372
+ * @return bool
3373
  * @access public
3374
  * @internal Uses the
3375
  * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See
3399
 
3400
  // ie. gmp_testbit($this, 0)
3401
  // ie. isEven() or !isOdd()
3402
+ switch (MATH_BIGINTEGER_MODE) {
3403
  case MATH_BIGINTEGER_MODE_GMP:
3404
  return gmp_prob_prime($this->value, $t) != 0;
3405
  case MATH_BIGINTEGER_MODE_BCMATH:
3436
  953, 967, 971, 977, 983, 991, 997
3437
  );
3438
 
3439
+ if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
3440
  for ($i = 0; $i < count($primes); ++$i) {
3441
  $primes[$i] = new Math_BigInteger($primes[$i]);
3442
  }
3452
  }
3453
 
3454
  // see HAC 4.4.1 "Random search for probable primes"
3455
+ if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
3456
  foreach ($primes as $prime) {
3457
  list(, $r) = $this->divide($prime);
3458
  if ($r->equals($zero)) {
3476
  $r = $n_1->copy();
3477
  $r_value = $r->value;
3478
  // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
3479
+ if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
3480
  $s = 0;
3481
  // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
3482
  while ($r->value[strlen($r->value) - 1] % 2 == 0) {
3486
  } else {
3487
  for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
3488
  $temp = ~$r_value[$i] & 0xFFFFFF;
3489
+ for ($j = 1; ($temp >> $j) & 1; ++$j) {
3490
+ }
3491
  if ($j != 25) {
3492
  break;
3493
  }
3494
  }
3495
+ $s = 26 * $i + $j;
3496
  $r->_rshift($s);
3497
  }
3498
 
3521
  *
3522
  * Shifts BigInteger's by $shift bits.
3523
  *
3524
+ * @param int $shift
3525
  * @access private
3526
  */
3527
  function _lshift($shift)
3528
  {
3529
+ if ($shift == 0) {
3530
  return;
3531
  }
3532
 
3542
  $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
3543
  }
3544
 
3545
+ if ($carry) {
3546
  $this->value[count($this->value)] = $carry;
3547
  }
3548
 
3556
  *
3557
  * Shifts BigInteger's by $shift bits.
3558
  *
3559
+ * @param int $shift
3560
  * @access private
3561
  */
3562
  function _rshift($shift)
3570
  $carry_shift = MATH_BIGINTEGER_BASE - $shift;
3571
  $carry_mask = (1 << $shift) - 1;
3572
 
3573
+ if ($num_digits) {
3574
  $this->value = array_slice($this->value, $num_digits);
3575
  }
3576
 
3592
  *
3593
  * @param Math_BigInteger
3594
  * @return Math_BigInteger
3595
+ * @see self::_trim()
3596
  * @access private
3597
  */
3598
  function _normalize($result)
3600
  $result->precision = $this->precision;
3601
  $result->bitmask = $this->bitmask;
3602
 
3603
+ switch (MATH_BIGINTEGER_MODE) {
3604
  case MATH_BIGINTEGER_MODE_GMP:
3605
+ if ($this->bitmask !== false) {
3606
  $result->value = gmp_and($result->value, $result->bitmask->value);
3607
  }
3608
 
3617
 
3618
  $value = &$result->value;
3619
 
3620
+ if (!count($value)) {
3621
  return $result;
3622
  }
3623
 
3640
  *
3641
  * Removes leading zeros
3642
  *
3643
+ * @param array $value
3644
  * @return Math_BigInteger
3645
  * @access private
3646
  */
3647
  function _trim($value)
3648
  {
3649
  for ($i = count($value) - 1; $i >= 0; --$i) {
3650
+ if ($value[$i]) {
3651
  break;
3652
  }
3653
  unset($value[$i]);
3661
  *
3662
  * @param $input Array
3663
  * @param $multiplier mixed
3664
+ * @return array
3665
  * @access private
3666
  */
3667
  function _array_repeat($input, $multiplier)
3676
  *
3677
  * @param $x String
3678
  * @param $shift Integer
3679
+ * @return string
3680
  * @access private
3681
  */
3682
  function _base256_lshift(&$x, $shift)
3705
  *
3706
  * @param $x String
3707
  * @param $shift Integer
3708
+ * @return string
3709
  * @access private
3710
  */
3711
  function _base256_rshift(&$x, $shift)
3745
  /**
3746
  * Converts 32-bit integers to bytes.
3747
  *
3748
+ * @param int $x
3749
+ * @return string
3750
  * @access private
3751
  */
3752
  function _int2bytes($x)
3757
  /**
3758
  * Converts bytes to 32-bit integers
3759
  *
3760
+ * @param string $x
3761
+ * @return int
3762
  * @access private
3763
  */
3764
  function _bytes2int($x)
3772
  *
3773
  * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL
3774
  *
3775
+ * @see self::modPow()
3776
  * @access private
3777
+ * @param int $length
3778
+ * @return string
3779
  */
3780
  function _encodeASN1Length($length)
3781
  {
3796
  * we'll guarantee that the dividend is divisible by first subtracting the remainder.
3797
  *
3798
  * @access private
3799
+ * @param int $x
3800
+ * @param int $y
3801
+ * @return int
3802
  */
3803
  function _safe_divide($x, $y)
3804
  {
phpseclib/Net/SFTP.php CHANGED
@@ -62,7 +62,7 @@ if (!class_exists('Net_SSH2')) {
62
 
63
  /**#@+
64
  * @access public
65
- * @see Net_SFTP::getLog()
66
  */
67
  /**
68
  * Returns the message numbers
@@ -91,7 +91,7 @@ define('NET_SFTP_CHANNEL', 0x100);
91
 
92
  /**#@+
93
  * @access public
94
- * @see Net_SFTP::put()
95
  */
96
  /**
97
  * Reads data from a local file.
@@ -129,8 +129,8 @@ class Net_SFTP extends Net_SSH2
129
  /**
130
  * Packet Types
131
  *
132
- * @see Net_SFTP::Net_SFTP()
133
- * @var Array
134
  * @access private
135
  */
136
  var $packet_types = array();
@@ -138,8 +138,8 @@ class Net_SFTP extends Net_SSH2
138
  /**
139
  * Status Codes
140
  *
141
- * @see Net_SFTP::Net_SFTP()
142
- * @var Array
143
  * @access private
144
  */
145
  var $status_codes = array();
@@ -150,8 +150,8 @@ class Net_SFTP extends Net_SSH2
150
  * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
151
  * concurrent actions, so it's somewhat academic, here.
152
  *
153
- * @var Integer
154
- * @see Net_SFTP::_send_sftp_packet()
155
  * @access private
156
  */
157
  var $request_id = false;
@@ -162,8 +162,8 @@ class Net_SFTP extends Net_SSH2
162
  * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
163
  * concurrent actions, so it's somewhat academic, here.
164
  *
165
- * @var Integer
166
- * @see Net_SFTP::_get_sftp_packet()
167
  * @access private
168
  */
169
  var $packet_type = -1;
@@ -171,8 +171,8 @@ class Net_SFTP extends Net_SSH2
171
  /**
172
  * Packet Buffer
173
  *
174
- * @var String
175
- * @see Net_SFTP::_get_sftp_packet()
176
  * @access private
177
  */
178
  var $packet_buffer = '';
@@ -180,8 +180,8 @@ class Net_SFTP extends Net_SSH2
180
  /**
181
  * Extensions supported by the server
182
  *
183
- * @var Array
184
- * @see Net_SFTP::_initChannel()
185
  * @access private
186
  */
187
  var $extensions = array();
@@ -189,8 +189,8 @@ class Net_SFTP extends Net_SSH2
189
  /**
190
  * Server SFTP version
191
  *
192
- * @var Integer
193
- * @see Net_SFTP::_initChannel()
194
  * @access private
195
  */
196
  var $version;
@@ -198,9 +198,9 @@ class Net_SFTP extends Net_SSH2
198
  /**
199
  * Current working directory
200
  *
201
- * @var String
202
- * @see Net_SFTP::_realpath()
203
- * @see Net_SFTP::chdir()
204
  * @access private
205
  */
206
  var $pwd = false;
@@ -208,8 +208,8 @@ class Net_SFTP extends Net_SSH2
208
  /**
209
  * Packet Type Log
210
  *
211
- * @see Net_SFTP::getLog()
212
- * @var Array
213
  * @access private
214
  */
215
  var $packet_type_log = array();
@@ -217,8 +217,8 @@ class Net_SFTP extends Net_SSH2
217
  /**
218
  * Packet Log
219
  *
220
- * @see Net_SFTP::getLog()
221
- * @var Array
222
  * @access private
223
  */
224
  var $packet_log = array();
@@ -226,9 +226,9 @@ class Net_SFTP extends Net_SSH2
226
  /**
227
  * Error information
228
  *
229
- * @see Net_SFTP::getSFTPErrors()
230
- * @see Net_SFTP::getLastSFTPError()
231
- * @var String
232
  * @access private
233
  */
234
  var $sftp_errors = array();
@@ -239,10 +239,10 @@ class Net_SFTP extends Net_SSH2
239
  * Rather than always having to open a directory and close it immediately there after to see if a file is a directory
240
  * we'll cache the results.
241
  *
242
- * @see Net_SFTP::_update_stat_cache()
243
- * @see Net_SFTP::_remove_from_stat_cache()
244
- * @see Net_SFTP::_query_stat_cache()
245
- * @var Array
246
  * @access private
247
  */
248
  var $stat_cache = array();
@@ -250,9 +250,9 @@ class Net_SFTP extends Net_SSH2
250
  /**
251
  * Max SFTP Packet Size
252
  *
253
- * @see Net_SFTP::Net_SFTP()
254
- * @see Net_SFTP::get()
255
- * @var Array
256
  * @access private
257
  */
258
  var $max_sftp_packet;
@@ -260,9 +260,9 @@ class Net_SFTP extends Net_SSH2
260
  /**
261
  * Stat Cache Flag
262
  *
263
- * @see Net_SFTP::disableStatCache()
264
- * @see Net_SFTP::enableStatCache()
265
- * @var Boolean
266
  * @access private
267
  */
268
  var $use_stat_cache = true;
@@ -270,27 +270,41 @@ class Net_SFTP extends Net_SSH2
270
  /**
271
  * Sort Options
272
  *
273
- * @see Net_SFTP::_comparator()
274
- * @see Net_SFTP::setListOrder()
275
- * @var Array
276
  * @access private
277
  */
278
  var $sortOptions = array();
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  /**
281
  * Default Constructor.
282
  *
283
  * Connects to an SFTP server
284
  *
285
- * @param String $host
286
- * @param optional Integer $port
287
- * @param optional Integer $timeout
288
  * @return Net_SFTP
289
  * @access public
290
  */
291
- function Net_SFTP($host, $port = 22, $timeout = 10)
292
  {
293
- parent::Net_SSH2($host, $port, $timeout);
294
 
295
  $this->max_sftp_packet = 1 << 15;
296
 
@@ -380,7 +394,7 @@ class Net_SFTP extends Net_SSH2
380
  );
381
  // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
382
  // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
383
- // the array for that $this->open5_flags and similarily alter the constant names.
384
  $this->open_flags = array(
385
  0x00000001 => 'NET_SFTP_OPEN_READ',
386
  0x00000002 => 'NET_SFTP_OPEN_WRITE',
@@ -413,16 +427,30 @@ class Net_SFTP extends Net_SSH2
413
  );
414
 
415
  if (!defined('NET_SFTP_QUEUE_SIZE')) {
416
- define('NET_SFTP_QUEUE_SIZE', 50);
417
  }
418
  }
419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  /**
421
  * Login
422
  *
423
- * @param String $username
424
- * @param optional String $password
425
- * @return Boolean
426
  * @access public
427
  */
428
  function login($username)
@@ -434,8 +462,15 @@ class Net_SFTP extends Net_SSH2
434
 
435
  $this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size;
436
 
437
- $packet = pack('CNa*N3',
438
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SFTP_CHANNEL, $this->window_size, 0x4000);
 
 
 
 
 
 
 
439
 
440
  if (!$this->_send_binary_packet($packet)) {
441
  return false;
@@ -443,20 +478,28 @@ class Net_SFTP extends Net_SSH2
443
 
444
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
445
 
446
- $response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
447
  if ($response === false) {
448
  return false;
449
  }
450
 
451
- $packet = pack('CNNa*CNa*',
452
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
 
 
 
 
 
 
 
 
453
  if (!$this->_send_binary_packet($packet)) {
454
  return false;
455
  }
456
 
457
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
458
 
459
- $response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
460
  if ($response === false) {
461
  // from PuTTY's psftp.exe
462
  $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
@@ -464,15 +507,23 @@ class Net_SFTP extends Net_SSH2
464
  "exec sftp-server";
465
  // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
466
  // is redundant
467
- $packet = pack('CNNa*CNa*',
468
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command);
 
 
 
 
 
 
 
 
469
  if (!$this->_send_binary_packet($packet)) {
470
  return false;
471
  }
472
 
473
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
474
 
475
- $response = $this->_get_channel_packet(NET_SFTP_CHANNEL);
476
  if ($response === false) {
477
  return false;
478
  }
@@ -490,11 +541,20 @@ class Net_SFTP extends Net_SSH2
490
  return false;
491
  }
492
 
 
 
 
493
  extract(unpack('Nversion', $this->_string_shift($response, 4)));
494
  $this->version = $version;
495
  while (!empty($response)) {
 
 
 
496
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
497
  $key = $this->_string_shift($response, $length);
 
 
 
498
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
499
  $value = $this->_string_shift($response, $length);
500
  $this->extensions[$key] = $value;
@@ -584,10 +644,30 @@ class Net_SFTP extends Net_SSH2
584
  $this->stat_cache = array();
585
  }
586
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  /**
588
  * Returns the current directory name
589
  *
590
- * @return Mixed
591
  * @access public
592
  */
593
  function pwd()
@@ -598,19 +678,22 @@ class Net_SFTP extends Net_SSH2
598
  /**
599
  * Logs errors
600
  *
601
- * @param String $response
602
- * @param optional Integer $status
603
  * @access public
604
  */
605
  function _logError($response, $status = -1)
606
  {
607
  if ($status == -1) {
 
 
 
608
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
609
  }
610
 
611
  $error = $this->status_codes[$status];
612
 
613
- if ($this->version > 2) {
614
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
615
  $this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length);
616
  } else {
@@ -618,19 +701,41 @@ class Net_SFTP extends Net_SSH2
618
  }
619
  }
620
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  /**
622
  * Canonicalize the Server-Side Path Name
623
  *
624
  * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
625
  * the absolute (canonicalized) path.
626
  *
627
- * @see Net_SFTP::chdir()
628
- * @param String $path
629
- * @return Mixed
 
 
 
630
  * @access private
631
  */
632
  function _realpath($path)
633
  {
 
 
 
 
634
  if ($this->pwd === false) {
635
  // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
636
  if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
@@ -644,6 +749,9 @@ class Net_SFTP extends Net_SSH2
644
  // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
645
  // at is the first part and that part is defined the same in SFTP versions 3 through 6.
646
  $this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
 
 
 
647
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
648
  return $this->_string_shift($response, $length);
649
  case NET_SFTP_STATUS:
@@ -681,8 +789,8 @@ class Net_SFTP extends Net_SSH2
681
  /**
682
  * Changes the current directory
683
  *
684
- * @param String $dir
685
- * @return Boolean
686
  * @access public
687
  */
688
  function chdir($dir)
@@ -743,9 +851,9 @@ class Net_SFTP extends Net_SSH2
743
  /**
744
  * Returns a list of files in the given directory
745
  *
746
- * @param optional String $dir
747
- * @param optional Boolean $recursive
748
- * @return Mixed
749
  * @access public
750
  */
751
  function nlist($dir = '.', $recursive = false)
@@ -756,17 +864,17 @@ class Net_SFTP extends Net_SSH2
756
  /**
757
  * Helper method for nlist
758
  *
759
- * @param String $dir
760
- * @param Boolean $recursive
761
- * @param String $relativeDir
762
- * @return Mixed
763
  * @access private
764
  */
765
  function _nlist_helper($dir, $recursive, $relativeDir)
766
  {
767
  $files = $this->_list($dir, false);
768
 
769
- if (!$recursive) {
770
  return $files;
771
  }
772
 
@@ -792,9 +900,9 @@ class Net_SFTP extends Net_SSH2
792
  /**
793
  * Returns a detailed list of files in the given directory
794
  *
795
- * @param optional String $dir
796
- * @param optional Boolean $recursive
797
- * @return Mixed
798
  * @access public
799
  */
800
  function rawlist($dir = '.', $recursive = false)
@@ -806,7 +914,7 @@ class Net_SFTP extends Net_SSH2
806
 
807
  static $depth = 0;
808
 
809
- foreach ($files as $key=>$value) {
810
  if ($depth != 0 && $key == '..') {
811
  unset($files[$key]);
812
  continue;
@@ -826,9 +934,9 @@ class Net_SFTP extends Net_SSH2
826
  /**
827
  * Reads a list, be it detailed or not, of files in the given directory
828
  *
829
- * @param String $dir
830
- * @param optional Boolean $raw
831
- * @return Mixed
832
  * @access private
833
  */
834
  function _list($dir, $raw = true)
@@ -878,10 +986,19 @@ class Net_SFTP extends Net_SSH2
878
  $response = $this->_get_sftp_packet();
879
  switch ($this->packet_type) {
880
  case NET_SFTP_NAME:
 
 
 
881
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
882
  for ($i = 0; $i < $count; $i++) {
 
 
 
883
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
884
  $shortname = $this->_string_shift($response, $length);
 
 
 
885
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
886
  $longname = $this->_string_shift($response, $length);
887
  $attributes = $this->_parseAttributes($response);
@@ -901,13 +1018,16 @@ class Net_SFTP extends Net_SSH2
901
  } else {
902
  $temp = $dir . '/' . $shortname;
903
  }
904
- $this->_update_stat_cache($temp, (object) $attributes);
905
  }
906
  // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
907
  // final SSH_FXP_STATUS packet should tell us that, already.
908
  }
909
  break;
910
  case NET_SFTP_STATUS:
 
 
 
911
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
912
  if ($status != NET_SFTP_STATUS_EOF) {
913
  $this->_logError($response, $status);
@@ -936,9 +1056,9 @@ class Net_SFTP extends Net_SSH2
936
  *
937
  * Intended for use with uasort()
938
  *
939
- * @param Array $a
940
- * @param Array $b
941
- * @return Integer
942
  * @access private
943
  */
944
  function _comparator($a, $b)
@@ -1036,8 +1156,8 @@ class Net_SFTP extends Net_SSH2
1036
  *
1037
  * Files larger than 4GB will show up as being exactly 4GB.
1038
  *
1039
- * @param String $filename
1040
- * @return Mixed
1041
  * @access public
1042
  */
1043
  function size($filename)
@@ -1056,22 +1176,40 @@ class Net_SFTP extends Net_SSH2
1056
  /**
1057
  * Save files / directories to cache
1058
  *
1059
- * @param String $path
1060
- * @param Mixed $value
1061
  * @access private
1062
  */
1063
  function _update_stat_cache($path, $value)
1064
  {
 
 
 
 
1065
  // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
1066
  $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
1067
 
1068
  $temp = &$this->stat_cache;
1069
  $max = count($dirs) - 1;
1070
- foreach ($dirs as $i=>$dir) {
 
 
 
 
 
 
1071
  if (!isset($temp[$dir])) {
1072
  $temp[$dir] = array();
1073
  }
1074
  if ($i === $max) {
 
 
 
 
 
 
 
 
1075
  $temp[$dir] = $value;
1076
  break;
1077
  }
@@ -1082,8 +1220,8 @@ class Net_SFTP extends Net_SSH2
1082
  /**
1083
  * Remove files / directories from cache
1084
  *
1085
- * @param String $path
1086
- * @return Boolean
1087
  * @access private
1088
  */
1089
  function _remove_from_stat_cache($path)
@@ -1092,7 +1230,7 @@ class Net_SFTP extends Net_SSH2
1092
 
1093
  $temp = &$this->stat_cache;
1094
  $max = count($dirs) - 1;
1095
- foreach ($dirs as $i=>$dir) {
1096
  if ($i === $max) {
1097
  unset($temp[$dir]);
1098
  return true;
@@ -1109,8 +1247,8 @@ class Net_SFTP extends Net_SSH2
1109
  *
1110
  * Mainly used by file_exists
1111
  *
1112
- * @param String $dir
1113
- * @return Mixed
1114
  * @access private
1115
  */
1116
  function _query_stat_cache($path)
@@ -1132,8 +1270,8 @@ class Net_SFTP extends Net_SSH2
1132
  *
1133
  * Returns an array on success and false otherwise.
1134
  *
1135
- * @param String $filename
1136
- * @return Mixed
1137
  * @access public
1138
  */
1139
  function stat($filename)
@@ -1149,11 +1287,11 @@ class Net_SFTP extends Net_SSH2
1149
 
1150
  if ($this->use_stat_cache) {
1151
  $result = $this->_query_stat_cache($filename);
1152
- if (is_array($result) && isset($result['.'])) {
1153
- return (array) $result['.'];
1154
  }
1155
- if (is_object($result)) {
1156
- return (array) $result;
1157
  }
1158
  }
1159
 
@@ -1166,7 +1304,7 @@ class Net_SFTP extends Net_SSH2
1166
  if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1167
  $filename.= '/.';
1168
  }
1169
- $this->_update_stat_cache($filename, (object) $stat);
1170
  return $stat;
1171
  }
1172
 
@@ -1179,7 +1317,7 @@ class Net_SFTP extends Net_SSH2
1179
  if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1180
  $filename.= '/.';
1181
  }
1182
- $this->_update_stat_cache($filename, (object) $stat);
1183
 
1184
  return $stat;
1185
  }
@@ -1189,8 +1327,8 @@ class Net_SFTP extends Net_SSH2
1189
  *
1190
  * Returns an array on success and false otherwise.
1191
  *
1192
- * @param String $filename
1193
- * @return Mixed
1194
  * @access public
1195
  */
1196
  function lstat($filename)
@@ -1206,11 +1344,11 @@ class Net_SFTP extends Net_SSH2
1206
 
1207
  if ($this->use_stat_cache) {
1208
  $result = $this->_query_stat_cache($filename);
1209
- if (is_array($result) && isset($result['.'])) {
1210
- return (array) $result['.'];
1211
  }
1212
- if (is_object($result)) {
1213
- return (array) $result;
1214
  }
1215
  }
1216
 
@@ -1223,7 +1361,7 @@ class Net_SFTP extends Net_SSH2
1223
  if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1224
  $filename.= '/.';
1225
  }
1226
- $this->_update_stat_cache($filename, (object) $lstat);
1227
  return $lstat;
1228
  }
1229
 
@@ -1231,7 +1369,7 @@ class Net_SFTP extends Net_SSH2
1231
 
1232
  if ($lstat != $stat) {
1233
  $lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
1234
- $this->_update_stat_cache($filename, (object) $lstat);
1235
  return $stat;
1236
  }
1237
 
@@ -1244,7 +1382,7 @@ class Net_SFTP extends Net_SSH2
1244
  if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1245
  $filename.= '/.';
1246
  }
1247
- $this->_update_stat_cache($filename, (object) $lstat);
1248
 
1249
  return $lstat;
1250
  }
@@ -1252,12 +1390,12 @@ class Net_SFTP extends Net_SSH2
1252
  /**
1253
  * Returns general information about a file or symbolic link
1254
  *
1255
- * Determines information without calling Net_SFTP::_realpath().
1256
  * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
1257
  *
1258
- * @param String $filename
1259
- * @param Integer $type
1260
- * @return Mixed
1261
  * @access private
1262
  */
1263
  function _stat($filename, $type)
@@ -1284,9 +1422,9 @@ class Net_SFTP extends Net_SSH2
1284
  /**
1285
  * Truncates a file to a given length
1286
  *
1287
- * @param String $filename
1288
- * @param Integer $new_size
1289
- * @return Boolean
1290
  * @access public
1291
  */
1292
  function truncate($filename, $new_size)
@@ -1301,10 +1439,10 @@ class Net_SFTP extends Net_SSH2
1301
  *
1302
  * If the file does not exist, it will be created.
1303
  *
1304
- * @param String $filename
1305
- * @param optional Integer $time
1306
- * @param optional Integer $atime
1307
- * @return Boolean
1308
  * @access public
1309
  */
1310
  function touch($filename, $time = null, $atime = null)
@@ -1352,10 +1490,10 @@ class Net_SFTP extends Net_SSH2
1352
  *
1353
  * Returns true on success or false on error.
1354
  *
1355
- * @param String $filename
1356
- * @param Integer $uid
1357
- * @param optional Boolean $recursive
1358
- * @return Boolean
1359
  * @access public
1360
  */
1361
  function chown($filename, $uid, $recursive = false)
@@ -1372,10 +1510,10 @@ class Net_SFTP extends Net_SSH2
1372
  *
1373
  * Returns true on success or false on error.
1374
  *
1375
- * @param String $filename
1376
- * @param Integer $gid
1377
- * @param optional Boolean $recursive
1378
- * @return Boolean
1379
  * @access public
1380
  */
1381
  function chgrp($filename, $gid, $recursive = false)
@@ -1391,10 +1529,10 @@ class Net_SFTP extends Net_SSH2
1391
  * Returns the new file permissions on success or false on error.
1392
  * If $recursive is true than this just returns true or false.
1393
  *
1394
- * @param Integer $mode
1395
- * @param String $filename
1396
- * @param optional Boolean $recursive
1397
- * @return Mixed
1398
  * @access public
1399
  */
1400
  function chmod($mode, $filename, $recursive = false)
@@ -1413,6 +1551,7 @@ class Net_SFTP extends Net_SSH2
1413
  return true;
1414
  }
1415
 
 
1416
  // rather than return what the permissions *should* be, we'll return what they actually are. this will also
1417
  // tell us if the file actually exists.
1418
  // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
@@ -1438,10 +1577,10 @@ class Net_SFTP extends Net_SSH2
1438
  /**
1439
  * Sets information about a file
1440
  *
1441
- * @param String $filename
1442
- * @param String $attr
1443
- * @param Boolean $recursive
1444
- * @return Boolean
1445
  * @access private
1446
  */
1447
  function _setstat($filename, $attr, $recursive)
@@ -1483,6 +1622,9 @@ class Net_SFTP extends Net_SSH2
1483
  return false;
1484
  }
1485
 
 
 
 
1486
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1487
  if ($status != NET_SFTP_STATUS_OK) {
1488
  $this->_logError($response, $status);
@@ -1497,10 +1639,10 @@ class Net_SFTP extends Net_SSH2
1497
  *
1498
  * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
1499
  *
1500
- * @param String $path
1501
- * @param String $attr
1502
- * @param Integer $i
1503
- * @return Boolean
1504
  * @access private
1505
  */
1506
  function _setstat_recursive($path, $attr, &$i)
@@ -1522,7 +1664,7 @@ class Net_SFTP extends Net_SSH2
1522
  }
1523
 
1524
  unset($entries['.'], $entries['..']);
1525
- foreach ($entries as $filename=>$props) {
1526
  if (!isset($props['type'])) {
1527
  return false;
1528
  }
@@ -1567,8 +1709,8 @@ class Net_SFTP extends Net_SSH2
1567
  /**
1568
  * Return the target of a symbolic link
1569
  *
1570
- * @param String $link
1571
- * @return Mixed
1572
  * @access public
1573
  */
1574
  function readlink($link)
@@ -1595,12 +1737,18 @@ class Net_SFTP extends Net_SSH2
1595
  return false;
1596
  }
1597
 
 
 
 
1598
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
1599
  // the file isn't a symlink
1600
  if (!$count) {
1601
  return false;
1602
  }
1603
 
 
 
 
1604
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
1605
  return $this->_string_shift($response, $length);
1606
  }
@@ -1610,9 +1758,9 @@ class Net_SFTP extends Net_SSH2
1610
  *
1611
  * symlink() creates a symbolic link to the existing target with the specified name link.
1612
  *
1613
- * @param String $target
1614
- * @param String $link
1615
- * @return Boolean
1616
  * @access public
1617
  */
1618
  function symlink($target, $link)
@@ -1621,7 +1769,7 @@ class Net_SFTP extends Net_SSH2
1621
  return false;
1622
  }
1623
 
1624
- $target = $this->_realpath($target);
1625
  $link = $this->_realpath($link);
1626
 
1627
  $packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
@@ -1635,6 +1783,9 @@ class Net_SFTP extends Net_SSH2
1635
  return false;
1636
  }
1637
 
 
 
 
1638
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1639
  if ($status != NET_SFTP_STATUS_OK) {
1640
  $this->_logError($response, $status);
@@ -1647,8 +1798,8 @@ class Net_SFTP extends Net_SSH2
1647
  /**
1648
  * Creates a directory.
1649
  *
1650
- * @param String $dir
1651
- * @return Boolean
1652
  * @access public
1653
  */
1654
  function mkdir($dir, $mode = -1, $recursive = false)
@@ -1682,8 +1833,8 @@ class Net_SFTP extends Net_SSH2
1682
  /**
1683
  * Helper function for directory creation
1684
  *
1685
- * @param String $dir
1686
- * @return Boolean
1687
  * @access private
1688
  */
1689
  function _mkdir_helper($dir, $attr)
@@ -1698,6 +1849,9 @@ class Net_SFTP extends Net_SSH2
1698
  return false;
1699
  }
1700
 
 
 
 
1701
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1702
  if ($status != NET_SFTP_STATUS_OK) {
1703
  $this->_logError($response, $status);
@@ -1710,8 +1864,8 @@ class Net_SFTP extends Net_SSH2
1710
  /**
1711
  * Removes a directory.
1712
  *
1713
- * @param String $dir
1714
- * @return Boolean
1715
  * @access public
1716
  */
1717
  function rmdir($dir)
@@ -1735,6 +1889,9 @@ class Net_SFTP extends Net_SSH2
1735
  return false;
1736
  }
1737
 
 
 
 
1738
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1739
  if ($status != NET_SFTP_STATUS_OK) {
1740
  // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
@@ -1788,13 +1945,13 @@ class Net_SFTP extends Net_SSH2
1788
  *
1789
  * Setting $local_start to > 0 or $mode | NET_SFTP_RESUME_START doesn't do anything unless $mode | NET_SFTP_LOCAL_FILE.
1790
  *
1791
- * @param String $remote_file
1792
- * @param String|resource $data
1793
- * @param optional Integer $mode
1794
- * @param optional Integer $start
1795
- * @param optional Integer $local_start
1796
- * @param optional callable|null $progressCallback
1797
- * @return Boolean
1798
  * @access public
1799
  * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode().
1800
  */
@@ -1857,7 +2014,14 @@ class Net_SFTP extends Net_SSH2
1857
  break;
1858
  case is_resource($data):
1859
  $mode = $mode & ~NET_SFTP_LOCAL_FILE;
1860
- $fp = $data;
 
 
 
 
 
 
 
1861
  break;
1862
  case $mode & NET_SFTP_LOCAL_FILE:
1863
  if (!is_file($data)) {
@@ -1872,14 +2036,11 @@ class Net_SFTP extends Net_SSH2
1872
 
1873
  if (isset($fp)) {
1874
  $stat = fstat($fp);
1875
- $size = $stat['size'];
1876
 
1877
  if ($local_start >= 0) {
1878
  fseek($fp, $local_start);
1879
- } elseif ($mode & NET_SFTP_RESUME_START) {
1880
- // do nothing
1881
- } else {
1882
- fseek($fp, $offset);
1883
  }
1884
  } elseif ($dataCallback) {
1885
  $size = 0;
@@ -1894,7 +2055,7 @@ class Net_SFTP extends Net_SSH2
1894
  // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header"
1895
  $sftp_packet_size-= strlen($handle) + 25;
1896
  $i = 0;
1897
- while ($dataCallback || ($sent < $size)) {
1898
  if ($dataCallback) {
1899
  $temp = call_user_func($dataCallback, $sftp_packet_size);
1900
  if (is_null($temp)) {
@@ -1902,7 +2063,11 @@ class Net_SFTP extends Net_SSH2
1902
  }
1903
  } else {
1904
  $temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
 
 
 
1905
  }
 
1906
  $subtemp = $offset + $sent;
1907
  $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
1908
  if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
@@ -1948,8 +2113,8 @@ class Net_SFTP extends Net_SSH2
1948
  * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
1949
  * SSH_FXP_WRITEs, in succession, and then reading $i responses.
1950
  *
1951
- * @param Integer $i
1952
- * @return Boolean
1953
  * @access private
1954
  */
1955
  function _read_put_responses($i)
@@ -1961,6 +2126,9 @@ class Net_SFTP extends Net_SSH2
1961
  return false;
1962
  }
1963
 
 
 
 
1964
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1965
  if ($status != NET_SFTP_STATUS_OK) {
1966
  $this->_logError($response, $status);
@@ -1974,8 +2142,8 @@ class Net_SFTP extends Net_SSH2
1974
  /**
1975
  * Close handle
1976
  *
1977
- * @param String $handle
1978
- * @return Boolean
1979
  * @access private
1980
  */
1981
  function _close_handle($handle)
@@ -1992,6 +2160,9 @@ class Net_SFTP extends Net_SSH2
1992
  return false;
1993
  }
1994
 
 
 
 
1995
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1996
  if ($status != NET_SFTP_STATUS_OK) {
1997
  $this->_logError($response, $status);
@@ -2010,11 +2181,11 @@ class Net_SFTP extends Net_SSH2
2010
  *
2011
  * $offset and $length can be used to download files in chunks.
2012
  *
2013
- * @param String $remote_file
2014
- * @param optional String $local_file
2015
- * @param optional Integer $offset
2016
- * @param optional Integer $length
2017
- * @return Mixed
2018
  * @access public
2019
  */
2020
  function get($remote_file, $local_file = false, $offset = 0, $length = -1)
@@ -2065,40 +2236,68 @@ class Net_SFTP extends Net_SSH2
2065
  $fclose_check = $local_file !== false && !is_resource($local_file);
2066
 
2067
  $start = $offset;
2068
- $size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length;
2069
  while (true) {
2070
- $packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size);
2071
- if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
2072
- if ($fclose_check) {
2073
- fclose($fp);
2074
- }
2075
- return false;
2076
- }
2077
 
2078
- $response = $this->_get_sftp_packet();
2079
- switch ($this->packet_type) {
2080
- case NET_SFTP_DATA:
2081
- $temp = substr($response, 4);
2082
- $offset+= strlen($temp);
2083
- if ($local_file === false) {
2084
- $content.= $temp;
2085
- } else {
2086
- fputs($fp, $temp);
2087
- }
2088
- break;
2089
- case NET_SFTP_STATUS:
2090
- // could, in theory, return false if !strlen($content) but we'll hold off for the time being
2091
- $this->_logError($response);
2092
- break 2;
2093
- default:
2094
- user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
2095
  if ($fclose_check) {
2096
  fclose($fp);
2097
  }
2098
  return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2099
  }
2100
 
2101
- if ($length > 0 && $length <= $offset - $start) {
2102
  break;
2103
  }
2104
  }
@@ -2126,9 +2325,9 @@ class Net_SFTP extends Net_SSH2
2126
  /**
2127
  * Deletes a file on the SFTP server.
2128
  *
2129
- * @param String $path
2130
- * @param Boolean $recursive
2131
- * @return Boolean
2132
  * @access public
2133
  */
2134
  function delete($path, $recursive = true)
@@ -2137,6 +2336,15 @@ class Net_SFTP extends Net_SSH2
2137
  return false;
2138
  }
2139
 
 
 
 
 
 
 
 
 
 
2140
  $path = $this->_realpath($path);
2141
  if ($path === false) {
2142
  return false;
@@ -2154,6 +2362,9 @@ class Net_SFTP extends Net_SSH2
2154
  }
2155
 
2156
  // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
 
 
 
2157
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2158
  if ($status != NET_SFTP_STATUS_OK) {
2159
  $this->_logError($response, $status);
@@ -2176,9 +2387,9 @@ class Net_SFTP extends Net_SSH2
2176
  *
2177
  * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
2178
  *
2179
- * @param String $path
2180
- * @param Integer $i
2181
- * @return Boolean
2182
  * @access private
2183
  */
2184
  function _delete_recursive($path, &$i)
@@ -2196,7 +2407,7 @@ class Net_SFTP extends Net_SSH2
2196
  }
2197
 
2198
  unset($entries['.'], $entries['..']);
2199
- foreach ($entries as $filename=>$props) {
2200
  if (!isset($props['type'])) {
2201
  return false;
2202
  }
@@ -2210,6 +2421,7 @@ class Net_SFTP extends Net_SSH2
2210
  if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
2211
  return false;
2212
  }
 
2213
 
2214
  $i++;
2215
 
@@ -2220,12 +2432,12 @@ class Net_SFTP extends Net_SSH2
2220
  $i = 0;
2221
  }
2222
  }
2223
- $this->_remove_from_stat_cache($path);
2224
  }
2225
 
2226
  if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
2227
  return false;
2228
  }
 
2229
 
2230
  $i++;
2231
 
@@ -2242,8 +2454,8 @@ class Net_SFTP extends Net_SSH2
2242
  /**
2243
  * Checks whether a file or directory exists
2244
  *
2245
- * @param String $path
2246
- * @return Boolean
2247
  * @access public
2248
  */
2249
  function file_exists($path)
@@ -2265,8 +2477,8 @@ class Net_SFTP extends Net_SSH2
2265
  /**
2266
  * Tells whether the filename is a directory
2267
  *
2268
- * @param String $path
2269
- * @return Boolean
2270
  * @access public
2271
  */
2272
  function is_dir($path)
@@ -2281,8 +2493,8 @@ class Net_SFTP extends Net_SSH2
2281
  /**
2282
  * Tells whether the filename is a regular file
2283
  *
2284
- * @param String $path
2285
- * @return Boolean
2286
  * @access public
2287
  */
2288
  function is_file($path)
@@ -2297,24 +2509,94 @@ class Net_SFTP extends Net_SSH2
2297
  /**
2298
  * Tells whether the filename is a symbolic link
2299
  *
2300
- * @param String $path
2301
- * @return Boolean
2302
  * @access public
2303
  */
2304
  function is_link($path)
2305
  {
2306
- $result = $this->_get_stat_cache_prop($path, 'type');
2307
  if ($result === false) {
2308
  return false;
2309
  }
2310
  return $result === NET_SFTP_TYPE_SYMLINK;
2311
  }
2312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2313
  /**
2314
  * Gets last access time of file
2315
  *
2316
- * @param String $path
2317
- * @return Mixed
2318
  * @access public
2319
  */
2320
  function fileatime($path)
@@ -2325,8 +2607,8 @@ class Net_SFTP extends Net_SSH2
2325
  /**
2326
  * Gets file modification time
2327
  *
2328
- * @param String $path
2329
- * @return Mixed
2330
  * @access public
2331
  */
2332
  function filemtime($path)
@@ -2337,8 +2619,8 @@ class Net_SFTP extends Net_SSH2
2337
  /**
2338
  * Gets file permissions
2339
  *
2340
- * @param String $path
2341
- * @return Mixed
2342
  * @access public
2343
  */
2344
  function fileperms($path)
@@ -2349,8 +2631,8 @@ class Net_SFTP extends Net_SSH2
2349
  /**
2350
  * Gets file owner
2351
  *
2352
- * @param String $path
2353
- * @return Mixed
2354
  * @access public
2355
  */
2356
  function fileowner($path)
@@ -2361,8 +2643,8 @@ class Net_SFTP extends Net_SSH2
2361
  /**
2362
  * Gets file group
2363
  *
2364
- * @param String $path
2365
- * @return Mixed
2366
  * @access public
2367
  */
2368
  function filegroup($path)
@@ -2373,8 +2655,8 @@ class Net_SFTP extends Net_SSH2
2373
  /**
2374
  * Gets file size
2375
  *
2376
- * @param String $path
2377
- * @return Mixed
2378
  * @access public
2379
  */
2380
  function filesize($path)
@@ -2385,8 +2667,8 @@ class Net_SFTP extends Net_SSH2
2385
  /**
2386
  * Gets file type
2387
  *
2388
- * @param String $path
2389
- * @return Mixed
2390
  * @access public
2391
  */
2392
  function filetype($path)
@@ -2397,13 +2679,20 @@ class Net_SFTP extends Net_SSH2
2397
  }
2398
 
2399
  switch ($type) {
2400
- case NET_SFTP_TYPE_BLOCK_DEVICE: return 'block';
2401
- case NET_SFTP_TYPE_CHAR_DEVICE: return 'char';
2402
- case NET_SFTP_TYPE_DIRECTORY: return 'dir';
2403
- case NET_SFTP_TYPE_FIFO: return 'fifo';
2404
- case NET_SFTP_TYPE_REGULAR: return 'file';
2405
- case NET_SFTP_TYPE_SYMLINK: return 'link';
2406
- default: return false;
 
 
 
 
 
 
 
2407
  }
2408
  }
2409
 
@@ -2412,24 +2701,54 @@ class Net_SFTP extends Net_SSH2
2412
  *
2413
  * Uses cache if appropriate.
2414
  *
2415
- * @param String $path
2416
- * @param String $prop
2417
- * @return Mixed
2418
  * @access private
2419
  */
2420
  function _get_stat_cache_prop($path, $prop)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2421
  {
2422
  if ($this->use_stat_cache) {
2423
  $path = $this->_realpath($path);
2424
 
2425
  $result = $this->_query_stat_cache($path);
2426
 
2427
- if (is_object($result) && isset($result->$prop)) {
2428
- return $result->$prop;
2429
  }
2430
  }
2431
 
2432
- $result = $this->stat($path);
2433
 
2434
  if ($result === false || !isset($result[$prop])) {
2435
  return false;
@@ -2441,9 +2760,9 @@ class Net_SFTP extends Net_SSH2
2441
  /**
2442
  * Renames a file or a directory on the SFTP server
2443
  *
2444
- * @param String $oldname
2445
- * @param String $newname
2446
- * @return Boolean
2447
  * @access public
2448
  */
2449
  function rename($oldname, $newname)
@@ -2471,6 +2790,9 @@ class Net_SFTP extends Net_SSH2
2471
  }
2472
 
2473
  // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
 
 
 
2474
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2475
  if ($status != NET_SFTP_STATUS_OK) {
2476
  $this->_logError($response, $status);
@@ -2491,13 +2813,17 @@ class Net_SFTP extends Net_SSH2
2491
  *
2492
  * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
2493
  *
2494
- * @param String $response
2495
- * @return Array
2496
  * @access private
2497
  */
2498
  function _parseAttributes(&$response)
2499
  {
2500
  $attr = array();
 
 
 
 
2501
  extract(unpack('Nflags', $this->_string_shift($response, 4)));
2502
  // SFTPv4+ have a type field (a byte) that follows the above flag field
2503
  foreach ($this->attributes as $key => $value) {
@@ -2512,9 +2838,17 @@ class Net_SFTP extends Net_SSH2
2512
  $attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
2513
  break;
2514
  case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
 
 
 
 
2515
  $attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
2516
  break;
2517
  case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
 
 
 
 
2518
  $attr+= unpack('Npermissions', $this->_string_shift($response, 4));
2519
  // mode == permissions; permissions was the original array key and is retained for bc purposes.
2520
  // mode was added because that's the more industry standard terminology
@@ -2525,13 +2859,29 @@ class Net_SFTP extends Net_SSH2
2525
  }
2526
  break;
2527
  case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
 
 
 
 
2528
  $attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
2529
  break;
2530
  case NET_SFTP_ATTR_EXTENDED: // 0x80000000
 
 
 
 
2531
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
2532
  for ($i = 0; $i < $count; $i++) {
 
 
 
 
2533
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2534
  $key = $this->_string_shift($response, $length);
 
 
 
 
2535
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2536
  $attr[$key] = $this->_string_shift($response, $length);
2537
  }
@@ -2545,8 +2895,8 @@ class Net_SFTP extends Net_SSH2
2545
  *
2546
  * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
2547
  *
2548
- * @param Integer $mode
2549
- * @return Integer
2550
  * @access private
2551
  */
2552
  function _parseMode($mode)
@@ -2592,8 +2942,8 @@ class Net_SFTP extends Net_SSH2
2592
  *
2593
  * If the longname is in an unrecognized format bool(false) is returned.
2594
  *
2595
- * @param String $longname
2596
- * @return Mixed
2597
  * @access private
2598
  */
2599
  function _parseLongname($longname)
@@ -2621,18 +2971,18 @@ class Net_SFTP extends Net_SSH2
2621
  *
2622
  * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
2623
  *
2624
- * @param Integer $type
2625
- * @param String $data
2626
- * @see Net_SFTP::_get_sftp_packet()
2627
  * @see Net_SSH2::_send_channel_packet()
2628
- * @return Boolean
2629
  * @access private
2630
  */
2631
  function _send_sftp_packet($type, $data)
2632
  {
2633
  $packet = $this->request_id !== false ?
2634
  pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
2635
- pack('NCa*', strlen($data) + 1, $type, $data);
2636
 
2637
  $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
2638
  $result = $this->_send_channel_packet(NET_SFTP_CHANNEL, $packet);
@@ -2665,8 +3015,8 @@ class Net_SFTP extends Net_SSH2
2665
  * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
2666
  * messages containing one SFTP packet.
2667
  *
2668
- * @see Net_SFTP::_send_sftp_packet()
2669
- * @return String
2670
  * @access private
2671
  */
2672
  function _get_sftp_packet()
@@ -2677,7 +3027,7 @@ class Net_SFTP extends Net_SSH2
2677
 
2678
  // SFTP packet length
2679
  while (strlen($this->packet_buffer) < 4) {
2680
- $temp = $this->_get_channel_packet(NET_SFTP_CHANNEL);
2681
  if (is_bool($temp)) {
2682
  $this->packet_type = false;
2683
  $this->packet_buffer = '';
@@ -2685,13 +3035,16 @@ class Net_SFTP extends Net_SSH2
2685
  }
2686
  $this->packet_buffer.= $temp;
2687
  }
 
 
 
2688
  extract(unpack('Nlength', $this->_string_shift($this->packet_buffer, 4)));
2689
  $tempLength = $length;
2690
  $tempLength-= strlen($this->packet_buffer);
2691
 
2692
  // SFTP packet type and data payload
2693
  while ($tempLength > 0) {
2694
- $temp = $this->_get_channel_packet(NET_SFTP_CHANNEL);
2695
  if (is_bool($temp)) {
2696
  $this->packet_type = false;
2697
  $this->packet_buffer = '';
@@ -2738,7 +3091,7 @@ class Net_SFTP extends Net_SSH2
2738
  * Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
2739
  *
2740
  * @access public
2741
- * @return String or Array
2742
  */
2743
  function getSFTPLog()
2744
  {
@@ -2759,7 +3112,7 @@ class Net_SFTP extends Net_SSH2
2759
  /**
2760
  * Returns all errors
2761
  *
2762
- * @return String
2763
  * @access public
2764
  */
2765
  function getSFTPErrors()
@@ -2770,7 +3123,7 @@ class Net_SFTP extends Net_SSH2
2770
  /**
2771
  * Returns the last error
2772
  *
2773
- * @return String
2774
  * @access public
2775
  */
2776
  function getLastSFTPError()
@@ -2781,7 +3134,7 @@ class Net_SFTP extends Net_SSH2
2781
  /**
2782
  * Get supported SFTP versions
2783
  *
2784
- * @return Array
2785
  * @access public
2786
  */
2787
  function getSupportedVersions()
@@ -2796,8 +3149,8 @@ class Net_SFTP extends Net_SSH2
2796
  /**
2797
  * Disconnect
2798
  *
2799
- * @param Integer $reason
2800
- * @return Boolean
2801
  * @access private
2802
  */
2803
  function _disconnect($reason)
62
 
63
  /**#@+
64
  * @access public
65
+ * @see self::getLog()
66
  */
67
  /**
68
  * Returns the message numbers
91
 
92
  /**#@+
93
  * @access public
94
+ * @see self::put()
95
  */
96
  /**
97
  * Reads data from a local file.
129
  /**
130
  * Packet Types
131
  *
132
+ * @see self::Net_SFTP()
133
+ * @var array
134
  * @access private
135
  */
136
  var $packet_types = array();
138
  /**
139
  * Status Codes
140
  *
141
+ * @see self::Net_SFTP()
142
+ * @var array
143
  * @access private
144
  */
145
  var $status_codes = array();
150
  * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
151
  * concurrent actions, so it's somewhat academic, here.
152
  *
153
+ * @var int
154
+ * @see self::_send_sftp_packet()
155
  * @access private
156
  */
157
  var $request_id = false;
162
  * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
163
  * concurrent actions, so it's somewhat academic, here.
164
  *
165
+ * @var int
166
+ * @see self::_get_sftp_packet()
167
  * @access private
168
  */
169
  var $packet_type = -1;
171
  /**
172
  * Packet Buffer
173
  *
174
+ * @var string
175
+ * @see self::_get_sftp_packet()
176
  * @access private
177
  */
178
  var $packet_buffer = '';
180
  /**
181
  * Extensions supported by the server
182
  *
183
+ * @var array
184
+ * @see self::_initChannel()
185
  * @access private
186
  */
187
  var $extensions = array();
189
  /**
190
  * Server SFTP version
191
  *
192
+ * @var int
193
+ * @see self::_initChannel()
194
  * @access private
195
  */
196
  var $version;
198
  /**
199
  * Current working directory
200
  *
201
+ * @var string
202
+ * @see self::realpath()
203
+ * @see self::chdir()
204
  * @access private
205
  */
206
  var $pwd = false;
208
  /**
209
  * Packet Type Log
210
  *
211
+ * @see self::getLog()
212
+ * @var array
213
  * @access private
214
  */
215
  var $packet_type_log = array();
217
  /**
218
  * Packet Log
219
  *
220
+ * @see self::getLog()
221
+ * @var array
222
  * @access private
223
  */
224
  var $packet_log = array();
226
  /**
227
  * Error information
228
  *
229
+ * @see self::getSFTPErrors()
230
+ * @see self::getLastSFTPError()
231
+ * @var array
232
  * @access private
233
  */
234
  var $sftp_errors = array();
239
  * Rather than always having to open a directory and close it immediately there after to see if a file is a directory
240
  * we'll cache the results.
241
  *
242
+ * @see self::_update_stat_cache()
243
+ * @see self::_remove_from_stat_cache()
244
+ * @see self::_query_stat_cache()
245
+ * @var array
246
  * @access private
247
  */
248
  var $stat_cache = array();
250
  /**
251
  * Max SFTP Packet Size
252
  *
253
+ * @see self::Net_SFTP()
254
+ * @see self::get()
255
+ * @var array
256
  * @access private
257
  */
258
  var $max_sftp_packet;
260
  /**
261
  * Stat Cache Flag
262
  *
263
+ * @see self::disableStatCache()
264
+ * @see self::enableStatCache()
265
+ * @var bool
266
  * @access private
267
  */
268
  var $use_stat_cache = true;
270
  /**
271
  * Sort Options
272
  *
273
+ * @see self::_comparator()
274
+ * @see self::setListOrder()
275
+ * @var array
276
  * @access private
277
  */
278
  var $sortOptions = array();
279
 
280
+ /**
281
+ * Canonicalization Flag
282
+ *
283
+ * Determines whether or not paths should be canonicalized before being
284
+ * passed on to the remote server.
285
+ *
286
+ * @see self::enablePathCanonicalization()
287
+ * @see self::disablePathCanonicalization()
288
+ * @see self::realpath()
289
+ * @var bool
290
+ * @access private
291
+ */
292
+ var $canonicalize_paths = true;
293
+
294
  /**
295
  * Default Constructor.
296
  *
297
  * Connects to an SFTP server
298
  *
299
+ * @param string $host
300
+ * @param int $port
301
+ * @param int $timeout
302
  * @return Net_SFTP
303
  * @access public
304
  */
305
+ function __construct($host, $port = 22, $timeout = 10)
306
  {
307
+ parent::__construct($host, $port, $timeout);
308
 
309
  $this->max_sftp_packet = 1 << 15;
310
 
394
  );
395
  // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
396
  // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
397
+ // the array for that $this->open5_flags and similarly alter the constant names.
398
  $this->open_flags = array(
399
  0x00000001 => 'NET_SFTP_OPEN_READ',
400
  0x00000002 => 'NET_SFTP_OPEN_WRITE',
427
  );
428
 
429
  if (!defined('NET_SFTP_QUEUE_SIZE')) {
430
+ define('NET_SFTP_QUEUE_SIZE', 32);
431
  }
432
  }
433
 
434
+ /**
435
+ * PHP4 compatible Default Constructor.
436
+ *
437
+ * @see self::__construct()
438
+ * @param string $host
439
+ * @param int $port
440
+ * @param int $timeout
441
+ * @access public
442
+ */
443
+ function Net_SFTP($host, $port = 22, $timeout = 10)
444
+ {
445
+ $this->__construct($host, $port, $timeout);
446
+ }
447
+
448
  /**
449
  * Login
450
  *
451
+ * @param string $username
452
+ * @param string $password
453
+ * @return bool
454
  * @access public
455
  */
456
  function login($username)
462
 
463
  $this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size;
464
 
465
+ $packet = pack(
466
+ 'CNa*N3',
467
+ NET_SSH2_MSG_CHANNEL_OPEN,
468
+ strlen('session'),
469
+ 'session',
470
+ NET_SFTP_CHANNEL,
471
+ $this->window_size,
472
+ 0x4000
473
+ );
474
 
475
  if (!$this->_send_binary_packet($packet)) {
476
  return false;
478
 
479
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
480
 
481
+ $response = $this->_get_channel_packet(NET_SFTP_CHANNEL, true);
482
  if ($response === false) {
483
  return false;
484
  }
485
 
486
+ $packet = pack(
487
+ 'CNNa*CNa*',
488
+ NET_SSH2_MSG_CHANNEL_REQUEST,
489
+ $this->server_channels[NET_SFTP_CHANNEL],
490
+ strlen('subsystem'),
491
+ 'subsystem',
492
+ 1,
493
+ strlen('sftp'),
494
+ 'sftp'
495
+ );
496
  if (!$this->_send_binary_packet($packet)) {
497
  return false;
498
  }
499
 
500
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
501
 
502
+ $response = $this->_get_channel_packet(NET_SFTP_CHANNEL, true);
503
  if ($response === false) {
504
  // from PuTTY's psftp.exe
505
  $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
507
  "exec sftp-server";
508
  // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
509
  // is redundant
510
+ $packet = pack(
511
+ 'CNNa*CNa*',
512
+ NET_SSH2_MSG_CHANNEL_REQUEST,
513
+ $this->server_channels[NET_SFTP_CHANNEL],
514
+ strlen('exec'),
515
+ 'exec',
516
+ 1,
517
+ strlen($command),
518
+ $command
519
+ );
520
  if (!$this->_send_binary_packet($packet)) {
521
  return false;
522
  }
523
 
524
  $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
525
 
526
+ $response = $this->_get_channel_packet(NET_SFTP_CHANNEL, true);
527
  if ($response === false) {
528
  return false;
529
  }
541
  return false;
542
  }
543
 
544
+ if (strlen($response) < 4) {
545
+ return false;
546
+ }
547
  extract(unpack('Nversion', $this->_string_shift($response, 4)));
548
  $this->version = $version;
549
  while (!empty($response)) {
550
+ if (strlen($response) < 4) {
551
+ return false;
552
+ }
553
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
554
  $key = $this->_string_shift($response, $length);
555
+ if (strlen($response) < 4) {
556
+ return false;
557
+ }
558
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
559
  $value = $this->_string_shift($response, $length);
560
  $this->extensions[$key] = $value;
644
  $this->stat_cache = array();
645
  }
646
 
647
+ /**
648
+ * Enable path canonicalization
649
+ *
650
+ * @access public
651
+ */
652
+ function enablePathCanonicalization()
653
+ {
654
+ $this->canonicalize_paths = true;
655
+ }
656
+
657
+ /**
658
+ * Enable path canonicalization
659
+ *
660
+ * @access public
661
+ */
662
+ function disablePathCanonicalization()
663
+ {
664
+ $this->canonicalize_paths = false;
665
+ }
666
+
667
  /**
668
  * Returns the current directory name
669
  *
670
+ * @return mixed
671
  * @access public
672
  */
673
  function pwd()
678
  /**
679
  * Logs errors
680
  *
681
+ * @param string $response
682
+ * @param int $status
683
  * @access public
684
  */
685
  function _logError($response, $status = -1)
686
  {
687
  if ($status == -1) {
688
+ if (strlen($response) < 4) {
689
+ return;
690
+ }
691
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
692
  }
693
 
694
  $error = $this->status_codes[$status];
695
 
696
+ if ($this->version > 2 || strlen($response) < 4) {
697
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
698
  $this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length);
699
  } else {
701
  }
702
  }
703
 
704
+ /**
705
+ * Returns canonicalized absolute pathname
706
+ *
707
+ * realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input
708
+ * path and returns the canonicalized absolute pathname.
709
+ *
710
+ * @param string $path
711
+ * @return mixed
712
+ * @access public
713
+ */
714
+ function realpath($path)
715
+ {
716
+ return $this->_realpath($path);
717
+ }
718
+
719
  /**
720
  * Canonicalize the Server-Side Path Name
721
  *
722
  * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
723
  * the absolute (canonicalized) path.
724
  *
725
+ * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
726
+ *
727
+ * @see self::chdir()
728
+ * @see self::disablePathCanonicalization()
729
+ * @param string $path
730
+ * @return mixed
731
  * @access private
732
  */
733
  function _realpath($path)
734
  {
735
+ if (!$this->canonicalize_paths) {
736
+ return $path;
737
+ }
738
+
739
  if ($this->pwd === false) {
740
  // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
741
  if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
749
  // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
750
  // at is the first part and that part is defined the same in SFTP versions 3 through 6.
751
  $this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
752
+ if (strlen($response) < 4) {
753
+ return false;
754
+ }
755
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
756
  return $this->_string_shift($response, $length);
757
  case NET_SFTP_STATUS:
789
  /**
790
  * Changes the current directory
791
  *
792
+ * @param string $dir
793
+ * @return bool
794
  * @access public
795
  */
796
  function chdir($dir)
851
  /**
852
  * Returns a list of files in the given directory
853
  *
854
+ * @param string $dir
855
+ * @param bool $recursive
856
+ * @return mixed
857
  * @access public
858
  */
859
  function nlist($dir = '.', $recursive = false)
864
  /**
865
  * Helper method for nlist
866
  *
867
+ * @param string $dir
868
+ * @param bool $recursive
869
+ * @param string $relativeDir
870
+ * @return mixed
871
  * @access private
872
  */
873
  function _nlist_helper($dir, $recursive, $relativeDir)
874
  {
875
  $files = $this->_list($dir, false);
876
 
877
+ if (!$recursive || $files === false) {
878
  return $files;
879
  }
880
 
900
  /**
901
  * Returns a detailed list of files in the given directory
902
  *
903
+ * @param string $dir
904
+ * @param bool $recursive
905
+ * @return mixed
906
  * @access public
907
  */
908
  function rawlist($dir = '.', $recursive = false)
914
 
915
  static $depth = 0;
916
 
917
+ foreach ($files as $key => $value) {
918
  if ($depth != 0 && $key == '..') {
919
  unset($files[$key]);
920
  continue;
934
  /**
935
  * Reads a list, be it detailed or not, of files in the given directory
936
  *
937
+ * @param string $dir
938
+ * @param bool $raw
939
+ * @return mixed
940
  * @access private
941
  */
942
  function _list($dir, $raw = true)
986
  $response = $this->_get_sftp_packet();
987
  switch ($this->packet_type) {
988
  case NET_SFTP_NAME:
989
+ if (strlen($response) < 4) {
990
+ return false;
991
+ }
992
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
993
  for ($i = 0; $i < $count; $i++) {
994
+ if (strlen($response) < 4) {
995
+ return false;
996
+ }
997
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
998
  $shortname = $this->_string_shift($response, $length);
999
+ if (strlen($response) < 4) {
1000
+ return false;
1001
+ }
1002
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
1003
  $longname = $this->_string_shift($response, $length);
1004
  $attributes = $this->_parseAttributes($response);
1018
  } else {
1019
  $temp = $dir . '/' . $shortname;
1020
  }
1021
+ $this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
1022
  }
1023
  // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
1024
  // final SSH_FXP_STATUS packet should tell us that, already.
1025
  }
1026
  break;
1027
  case NET_SFTP_STATUS:
1028
+ if (strlen($response) < 4) {
1029
+ return false;
1030
+ }
1031
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1032
  if ($status != NET_SFTP_STATUS_EOF) {
1033
  $this->_logError($response, $status);
1056
  *
1057
  * Intended for use with uasort()
1058
  *
1059
+ * @param array $a
1060
+ * @param array $b
1061
+ * @return int
1062
  * @access private
1063
  */
1064
  function _comparator($a, $b)
1156
  *
1157
  * Files larger than 4GB will show up as being exactly 4GB.
1158
  *
1159
+ * @param string $filename
1160
+ * @return mixed
1161
  * @access public
1162
  */
1163
  function size($filename)
1176
  /**
1177
  * Save files / directories to cache
1178
  *
1179
+ * @param string $path
1180
+ * @param mixed $value
1181
  * @access private
1182
  */
1183
  function _update_stat_cache($path, $value)
1184
  {
1185
+ if ($this->use_stat_cache === false) {
1186
+ return;
1187
+ }
1188
+
1189
  // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
1190
  $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
1191
 
1192
  $temp = &$this->stat_cache;
1193
  $max = count($dirs) - 1;
1194
+ foreach ($dirs as $i => $dir) {
1195
+ // if $temp is an object that means one of two things.
1196
+ // 1. a file was deleted and changed to a directory behind phpseclib's back
1197
+ // 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
1198
+ if (is_object($temp)) {
1199
+ $temp = array();
1200
+ }
1201
  if (!isset($temp[$dir])) {
1202
  $temp[$dir] = array();
1203
  }
1204
  if ($i === $max) {
1205
+ if (is_object($temp[$dir])) {
1206
+ if (!isset($value->stat) && isset($temp[$dir]->stat)) {
1207
+ $value->stat = $temp[$dir]->stat;
1208
+ }
1209
+ if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
1210
+ $value->lstat = $temp[$dir]->lstat;
1211
+ }
1212
+ }
1213
  $temp[$dir] = $value;
1214
  break;
1215
  }
1220
  /**
1221
  * Remove files / directories from cache
1222
  *
1223
+ * @param string $path
1224
+ * @return bool
1225
  * @access private
1226
  */
1227
  function _remove_from_stat_cache($path)
1230
 
1231
  $temp = &$this->stat_cache;
1232
  $max = count($dirs) - 1;
1233
+ foreach ($dirs as $i => $dir) {
1234
  if ($i === $max) {
1235
  unset($temp[$dir]);
1236
  return true;
1247
  *
1248
  * Mainly used by file_exists
1249
  *
1250
+ * @param string $dir
1251
+ * @return mixed
1252
  * @access private
1253
  */
1254
  function _query_stat_cache($path)
1270
  *
1271
  * Returns an array on success and false otherwise.
1272
  *
1273
+ * @param string $filename
1274
+ * @return mixed
1275
  * @access public
1276
  */
1277
  function stat($filename)
1287
 
1288
  if ($this->use_stat_cache) {
1289
  $result = $this->_query_stat_cache($filename);
1290
+ if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
1291
+ return $result['.']->stat;
1292
  }
1293
+ if (is_object($result) && isset($result->stat)) {
1294
+ return $result->stat;
1295
  }
1296
  }
1297
 
1304
  if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1305
  $filename.= '/.';
1306
  }
1307
+ $this->_update_stat_cache($filename, (object) array('stat' => $stat));
1308
  return $stat;
1309
  }
1310
 
1317
  if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1318
  $filename.= '/.';
1319
  }
1320
+ $this->_update_stat_cache($filename, (object) array('stat' => $stat));
1321
 
1322
  return $stat;
1323
  }
1327
  *
1328
  * Returns an array on success and false otherwise.
1329
  *
1330
+ * @param string $filename
1331
+ * @return mixed
1332
  * @access public
1333
  */
1334
  function lstat($filename)
1344
 
1345
  if ($this->use_stat_cache) {
1346
  $result = $this->_query_stat_cache($filename);
1347
+ if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
1348
+ return $result['.']->lstat;
1349
  }
1350
+ if (is_object($result) && isset($result->lstat)) {
1351
+ return $result->lstat;
1352
  }
1353
  }
1354
 
1361
  if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1362
  $filename.= '/.';
1363
  }
1364
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
1365
  return $lstat;
1366
  }
1367
 
1369
 
1370
  if ($lstat != $stat) {
1371
  $lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
1372
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
1373
  return $stat;
1374
  }
1375
 
1382
  if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
1383
  $filename.= '/.';
1384
  }
1385
+ $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
1386
 
1387
  return $lstat;
1388
  }
1390
  /**
1391
  * Returns general information about a file or symbolic link
1392
  *
1393
+ * Determines information without calling Net_SFTP::realpath().
1394
  * The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
1395
  *
1396
+ * @param string $filename
1397
+ * @param int $type
1398
+ * @return mixed
1399
  * @access private
1400
  */
1401
  function _stat($filename, $type)
1422
  /**
1423
  * Truncates a file to a given length
1424
  *
1425
+ * @param string $filename
1426
+ * @param int $new_size
1427
+ * @return bool
1428
  * @access public
1429
  */
1430
  function truncate($filename, $new_size)
1439
  *
1440
  * If the file does not exist, it will be created.
1441
  *
1442
+ * @param string $filename
1443
+ * @param int $time
1444
+ * @param int $atime
1445
+ * @return bool
1446
  * @access public
1447
  */
1448
  function touch($filename, $time = null, $atime = null)
1490
  *
1491
  * Returns true on success or false on error.
1492
  *
1493
+ * @param string $filename
1494
+ * @param int $uid
1495
+ * @param bool $recursive
1496
+ * @return bool
1497
  * @access public
1498
  */
1499
  function chown($filename, $uid, $recursive = false)
1510
  *
1511
  * Returns true on success or false on error.
1512
  *
1513
+ * @param string $filename
1514
+ * @param int $gid
1515
+ * @param bool $recursive
1516
+ * @return bool
1517
  * @access public
1518
  */
1519
  function chgrp($filename, $gid, $recursive = false)
1529
  * Returns the new file permissions on success or false on error.
1530
  * If $recursive is true than this just returns true or false.
1531
  *
1532
+ * @param int $mode
1533
+ * @param string $filename
1534
+ * @param bool $recursive
1535
+ * @return mixed
1536
  * @access public
1537
  */
1538
  function chmod($mode, $filename, $recursive = false)
1551
  return true;
1552
  }
1553
 
1554
+ $filename = $this->realpath($filename);
1555
  // rather than return what the permissions *should* be, we'll return what they actually are. this will also
1556
  // tell us if the file actually exists.
1557
  // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
1577
  /**
1578
  * Sets information about a file
1579
  *
1580
+ * @param string $filename
1581
+ * @param string $attr
1582
+ * @param bool $recursive
1583
+ * @return bool
1584
  * @access private
1585
  */
1586
  function _setstat($filename, $attr, $recursive)
1622
  return false;
1623
  }
1624
 
1625
+ if (strlen($response) < 4) {
1626
+ return false;
1627
+ }
1628
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1629
  if ($status != NET_SFTP_STATUS_OK) {
1630
  $this->_logError($response, $status);
1639
  *
1640
  * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
1641
  *
1642
+ * @param string $path
1643
+ * @param string $attr
1644
+ * @param int $i
1645
+ * @return bool
1646
  * @access private
1647
  */
1648
  function _setstat_recursive($path, $attr, &$i)
1664
  }
1665
 
1666
  unset($entries['.'], $entries['..']);
1667
+ foreach ($entries as $filename => $props) {
1668
  if (!isset($props['type'])) {
1669
  return false;
1670
  }
1709
  /**
1710
  * Return the target of a symbolic link
1711
  *
1712
+ * @param string $link
1713
+ * @return mixed
1714
  * @access public
1715
  */
1716
  function readlink($link)
1737
  return false;
1738
  }
1739
 
1740
+ if (strlen($response) < 4) {
1741
+ return false;
1742
+ }
1743
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
1744
  // the file isn't a symlink
1745
  if (!$count) {
1746
  return false;
1747
  }
1748
 
1749
+ if (strlen($response) < 4) {
1750
+ return false;
1751
+ }
1752
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
1753
  return $this->_string_shift($response, $length);
1754
  }
1758
  *
1759
  * symlink() creates a symbolic link to the existing target with the specified name link.
1760
  *
1761
+ * @param string $target
1762
+ * @param string $link
1763
+ * @return bool
1764
  * @access public
1765
  */
1766
  function symlink($target, $link)
1769
  return false;
1770
  }
1771
 
1772
+ //$target = $this->_realpath($target);
1773
  $link = $this->_realpath($link);
1774
 
1775
  $packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
1783
  return false;
1784
  }
1785
 
1786
+ if (strlen($response) < 4) {
1787
+ return false;
1788
+ }
1789
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1790
  if ($status != NET_SFTP_STATUS_OK) {
1791
  $this->_logError($response, $status);
1798
  /**
1799
  * Creates a directory.
1800
  *
1801
+ * @param string $dir
1802
+ * @return bool
1803
  * @access public
1804
  */
1805
  function mkdir($dir, $mode = -1, $recursive = false)
1833
  /**
1834
  * Helper function for directory creation
1835
  *
1836
+ * @param string $dir
1837
+ * @return bool
1838
  * @access private
1839
  */
1840
  function _mkdir_helper($dir, $attr)
1849
  return false;
1850
  }
1851
 
1852
+ if (strlen($response) < 4) {
1853
+ return false;
1854
+ }
1855
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1856
  if ($status != NET_SFTP_STATUS_OK) {
1857
  $this->_logError($response, $status);
1864
  /**
1865
  * Removes a directory.
1866
  *
1867
+ * @param string $dir
1868
+ * @return bool
1869
  * @access public
1870
  */
1871
  function rmdir($dir)
1889
  return false;
1890
  }
1891
 
1892
+ if (strlen($response) < 4) {
1893
+ return false;
1894
+ }
1895
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
1896
  if ($status != NET_SFTP_STATUS_OK) {
1897
  // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
1945
  *
1946
  * Setting $local_start to > 0 or $mode | NET_SFTP_RESUME_START doesn't do anything unless $mode | NET_SFTP_LOCAL_FILE.
1947
  *
1948
+ * @param string $remote_file
1949
+ * @param string|resource $data
1950
+ * @param int $mode
1951
+ * @param int $start
1952
+ * @param int $local_start
1953
+ * @param callable|null $progressCallback
1954
+ * @return bool
1955
  * @access public
1956
  * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode().
1957
  */
2014
  break;
2015
  case is_resource($data):
2016
  $mode = $mode & ~NET_SFTP_LOCAL_FILE;
2017
+ $info = stream_get_meta_data($data);
2018
+ if ($info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
2019
+ $fp = fopen('php://memory', 'w+');
2020
+ stream_copy_to_stream($data, $fp);
2021
+ rewind($fp);
2022
+ } else {
2023
+ $fp = $data;
2024
+ }
2025
  break;
2026
  case $mode & NET_SFTP_LOCAL_FILE:
2027
  if (!is_file($data)) {
2036
 
2037
  if (isset($fp)) {
2038
  $stat = fstat($fp);
2039
+ $size = !empty($stat) ? $stat['size'] : 0;
2040
 
2041
  if ($local_start >= 0) {
2042
  fseek($fp, $local_start);
2043
+ $size-= $local_start;
 
 
 
2044
  }
2045
  } elseif ($dataCallback) {
2046
  $size = 0;
2055
  // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header"
2056
  $sftp_packet_size-= strlen($handle) + 25;
2057
  $i = 0;
2058
+ while ($dataCallback || ($size === 0 || $sent < $size)) {
2059
  if ($dataCallback) {
2060
  $temp = call_user_func($dataCallback, $sftp_packet_size);
2061
  if (is_null($temp)) {
2063
  }
2064
  } else {
2065
  $temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
2066
+ if ($temp === false || $temp === '') {
2067
+ break;
2068
+ }
2069
  }
2070
+
2071
  $subtemp = $offset + $sent;
2072
  $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
2073
  if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
2113
  * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
2114
  * SSH_FXP_WRITEs, in succession, and then reading $i responses.
2115
  *
2116
+ * @param int $i
2117
+ * @return bool
2118
  * @access private
2119
  */
2120
  function _read_put_responses($i)
2126
  return false;
2127
  }
2128
 
2129
+ if (strlen($response) < 4) {
2130
+ return false;
2131
+ }
2132
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2133
  if ($status != NET_SFTP_STATUS_OK) {
2134
  $this->_logError($response, $status);
2142
  /**
2143
  * Close handle
2144
  *
2145
+ * @param string $handle
2146
+ * @return bool
2147
  * @access private
2148
  */
2149
  function _close_handle($handle)
2160
  return false;
2161
  }
2162
 
2163
+ if (strlen($response) < 4) {
2164
+ return false;
2165
+ }
2166
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2167
  if ($status != NET_SFTP_STATUS_OK) {
2168
  $this->_logError($response, $status);
2181
  *
2182
  * $offset and $length can be used to download files in chunks.
2183
  *
2184
+ * @param string $remote_file
2185
+ * @param string $local_file
2186
+ * @param int $offset
2187
+ * @param int $length
2188
+ * @return mixed
2189
  * @access public
2190
  */
2191
  function get($remote_file, $local_file = false, $offset = 0, $length = -1)
2236
  $fclose_check = $local_file !== false && !is_resource($local_file);
2237
 
2238
  $start = $offset;
2239
+ $read = 0;
2240
  while (true) {
2241
+ $i = 0;
 
 
 
 
 
 
2242
 
2243
+ while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
2244
+ $tempoffset = $start + $read;
2245
+
2246
+ $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
2247
+
2248
+ $packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
2249
+ if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
 
 
 
 
 
 
 
 
 
 
2250
  if ($fclose_check) {
2251
  fclose($fp);
2252
  }
2253
  return false;
2254
+ }
2255
+ $packet = null;
2256
+ $read+= $packet_size;
2257
+ $i++;
2258
+ }
2259
+
2260
+ if (!$i) {
2261
+ break;
2262
+ }
2263
+
2264
+ $clear_responses = false;
2265
+ while ($i > 0) {
2266
+ $i--;
2267
+
2268
+ if ($clear_responses) {
2269
+ $this->_get_sftp_packet();
2270
+ continue;
2271
+ } else {
2272
+ $response = $this->_get_sftp_packet();
2273
+ }
2274
+
2275
+ switch ($this->packet_type) {
2276
+ case NET_SFTP_DATA:
2277
+ $temp = substr($response, 4);
2278
+ $offset+= strlen($temp);
2279
+ if ($local_file === false) {
2280
+ $content.= $temp;
2281
+ } else {
2282
+ fputs($fp, $temp);
2283
+ }
2284
+ $temp = null;
2285
+ break;
2286
+ case NET_SFTP_STATUS:
2287
+ // could, in theory, return false if !strlen($content) but we'll hold off for the time being
2288
+ $this->_logError($response);
2289
+ $clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses
2290
+ break;
2291
+ default:
2292
+ if ($fclose_check) {
2293
+ fclose($fp);
2294
+ }
2295
+ user_error('Expected SSH_FX_DATA or SSH_FXP_STATUS');
2296
+ }
2297
+ $response = null;
2298
  }
2299
 
2300
+ if ($clear_responses) {
2301
  break;
2302
  }
2303
  }
2325
  /**
2326
  * Deletes a file on the SFTP server.
2327
  *
2328
+ * @param string $path
2329
+ * @param bool $recursive
2330
+ * @return bool
2331
  * @access public
2332
  */
2333
  function delete($path, $recursive = true)
2336
  return false;
2337
  }
2338
 
2339
+ if (is_object($path)) {
2340
+ // It's an object. Cast it as string before we check anything else.
2341
+ $path = (string) $path;
2342
+ }
2343
+
2344
+ if (!is_string($path) || $path == '') {
2345
+ return false;
2346
+ }
2347
+
2348
  $path = $this->_realpath($path);
2349
  if ($path === false) {
2350
  return false;
2362
  }
2363
 
2364
  // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
2365
+ if (strlen($response) < 4) {
2366
+ return false;
2367
+ }
2368
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2369
  if ($status != NET_SFTP_STATUS_OK) {
2370
  $this->_logError($response, $status);
2387
  *
2388
  * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
2389
  *
2390
+ * @param string $path
2391
+ * @param int $i
2392
+ * @return bool
2393
  * @access private
2394
  */
2395
  function _delete_recursive($path, &$i)
2407
  }
2408
 
2409
  unset($entries['.'], $entries['..']);
2410
+ foreach ($entries as $filename => $props) {
2411
  if (!isset($props['type'])) {
2412
  return false;
2413
  }
2421
  if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
2422
  return false;
2423
  }
2424
+ $this->_remove_from_stat_cache($temp);
2425
 
2426
  $i++;
2427
 
2432
  $i = 0;
2433
  }
2434
  }
 
2435
  }
2436
 
2437
  if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
2438
  return false;
2439
  }
2440
+ $this->_remove_from_stat_cache($path);
2441
 
2442
  $i++;
2443
 
2454
  /**
2455
  * Checks whether a file or directory exists
2456
  *
2457
+ * @param string $path
2458
+ * @return bool
2459
  * @access public
2460
  */
2461
  function file_exists($path)
2477
  /**
2478
  * Tells whether the filename is a directory
2479
  *
2480
+ * @param string $path
2481
+ * @return bool
2482
  * @access public
2483
  */
2484
  function is_dir($path)
2493
  /**
2494
  * Tells whether the filename is a regular file
2495
  *
2496
+ * @param string $path
2497
+ * @return bool
2498
  * @access public
2499
  */
2500
  function is_file($path)
2509
  /**
2510
  * Tells whether the filename is a symbolic link
2511
  *
2512
+ * @param string $path
2513
+ * @return bool
2514
  * @access public
2515
  */
2516
  function is_link($path)
2517
  {
2518
+ $result = $this->_get_lstat_cache_prop($path, 'type');
2519
  if ($result === false) {
2520
  return false;
2521
  }
2522
  return $result === NET_SFTP_TYPE_SYMLINK;
2523
  }
2524
 
2525
+ /**
2526
+ * Tells whether a file exists and is readable
2527
+ *
2528
+ * @param string $path
2529
+ * @return bool
2530
+ * @access public
2531
+ */
2532
+ function is_readable($path)
2533
+ {
2534
+ $path = $this->_realpath($path);
2535
+
2536
+ $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_READ, 0);
2537
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
2538
+ return false;
2539
+ }
2540
+
2541
+ $response = $this->_get_sftp_packet();
2542
+ switch ($this->packet_type) {
2543
+ case NET_SFTP_HANDLE:
2544
+ return true;
2545
+ case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
2546
+ return false;
2547
+ default:
2548
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
2549
+ return false;
2550
+ }
2551
+ }
2552
+
2553
+ /**
2554
+ * Tells whether the filename is writable
2555
+ *
2556
+ * @param string $path
2557
+ * @return bool
2558
+ * @access public
2559
+ */
2560
+ function is_writable($path)
2561
+ {
2562
+ $path = $this->_realpath($path);
2563
+
2564
+ $packet = pack('Na*N2', strlen($path), $path, NET_SFTP_OPEN_WRITE, 0);
2565
+ if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
2566
+ return false;
2567
+ }
2568
+
2569
+ $response = $this->_get_sftp_packet();
2570
+ switch ($this->packet_type) {
2571
+ case NET_SFTP_HANDLE:
2572
+ return true;
2573
+ case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
2574
+ return false;
2575
+ default:
2576
+ user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
2577
+ return false;
2578
+ }
2579
+ }
2580
+
2581
+ /**
2582
+ * Tells whether the filename is writeable
2583
+ *
2584
+ * Alias of is_writable
2585
+ *
2586
+ * @param string $path
2587
+ * @return bool
2588
+ * @access public
2589
+ */
2590
+ function is_writeable($path)
2591
+ {
2592
+ return $this->is_writable($path);
2593
+ }
2594
+
2595
  /**
2596
  * Gets last access time of file
2597
  *
2598
+ * @param string $path
2599
+ * @return mixed
2600
  * @access public
2601
  */
2602
  function fileatime($path)
2607
  /**
2608
  * Gets file modification time
2609
  *
2610
+ * @param string $path
2611
+ * @return mixed
2612
  * @access public
2613
  */
2614
  function filemtime($path)
2619
  /**
2620
  * Gets file permissions
2621
  *
2622
+ * @param string $path
2623
+ * @return mixed
2624
  * @access public
2625
  */
2626
  function fileperms($path)
2631
  /**
2632
  * Gets file owner
2633
  *
2634
+ * @param string $path
2635
+ * @return mixed
2636
  * @access public
2637
  */
2638
  function fileowner($path)
2643
  /**
2644
  * Gets file group
2645
  *
2646
+ * @param string $path
2647
+ * @return mixed
2648
  * @access public
2649
  */
2650
  function filegroup($path)
2655
  /**
2656
  * Gets file size
2657
  *
2658
+ * @param string $path
2659
+ * @return mixed
2660
  * @access public
2661
  */
2662
  function filesize($path)
2667
  /**
2668
  * Gets file type
2669
  *
2670
+ * @param string $path
2671
+ * @return mixed
2672
  * @access public
2673
  */
2674
  function filetype($path)
2679
  }
2680
 
2681
  switch ($type) {
2682
+ case NET_SFTP_TYPE_BLOCK_DEVICE:
2683
+ return 'block';
2684
+ case NET_SFTP_TYPE_CHAR_DEVICE:
2685
+ return 'char';
2686
+ case NET_SFTP_TYPE_DIRECTORY:
2687
+ return 'dir';
2688
+ case NET_SFTP_TYPE_FIFO:
2689
+ return 'fifo';
2690
+ case NET_SFTP_TYPE_REGULAR:
2691
+ return 'file';
2692
+ case NET_SFTP_TYPE_SYMLINK:
2693
+ return 'link';
2694
+ default:
2695
+ return false;
2696
  }
2697
  }
2698
 
2701
  *
2702
  * Uses cache if appropriate.
2703
  *
2704
+ * @param string $path
2705
+ * @param string $prop
2706
+ * @return mixed
2707
  * @access private
2708
  */
2709
  function _get_stat_cache_prop($path, $prop)
2710
+ {
2711
+ return $this->_get_xstat_cache_prop($path, $prop, 'stat');
2712
+ }
2713
+
2714
+ /**
2715
+ * Return an lstat properity
2716
+ *
2717
+ * Uses cache if appropriate.
2718
+ *
2719
+ * @param string $path
2720
+ * @param string $prop
2721
+ * @return mixed
2722
+ * @access private
2723
+ */
2724
+ function _get_lstat_cache_prop($path, $prop)
2725
+ {
2726
+ return $this->_get_xstat_cache_prop($path, $prop, 'lstat');
2727
+ }
2728
+
2729
+ /**
2730
+ * Return a stat or lstat properity
2731
+ *
2732
+ * Uses cache if appropriate.
2733
+ *
2734
+ * @param string $path
2735
+ * @param string $prop
2736
+ * @return mixed
2737
+ * @access private
2738
+ */
2739
+ function _get_xstat_cache_prop($path, $prop, $type)
2740
  {
2741
  if ($this->use_stat_cache) {
2742
  $path = $this->_realpath($path);
2743
 
2744
  $result = $this->_query_stat_cache($path);
2745
 
2746
+ if (is_object($result) && isset($result->$type)) {
2747
+ return $result->{$type}[$prop];
2748
  }
2749
  }
2750
 
2751
+ $result = $this->$type($path);
2752
 
2753
  if ($result === false || !isset($result[$prop])) {
2754
  return false;
2760
  /**
2761
  * Renames a file or a directory on the SFTP server
2762
  *
2763
+ * @param string $oldname
2764
+ * @param string $newname
2765
+ * @return bool
2766
  * @access public
2767
  */
2768
  function rename($oldname, $newname)
2790
  }
2791
 
2792
  // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
2793
+ if (strlen($response) < 4) {
2794
+ return false;
2795
+ }
2796
  extract(unpack('Nstatus', $this->_string_shift($response, 4)));
2797
  if ($status != NET_SFTP_STATUS_OK) {
2798
  $this->_logError($response, $status);
2813
  *
2814
  * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
2815
  *
2816
+ * @param string $response
2817
+ * @return array
2818
  * @access private
2819
  */
2820
  function _parseAttributes(&$response)
2821
  {
2822
  $attr = array();
2823
+ if (strlen($response) < 4) {
2824
+ user_error('Malformed file attributes');
2825
+ return array();
2826
+ }
2827
  extract(unpack('Nflags', $this->_string_shift($response, 4)));
2828
  // SFTPv4+ have a type field (a byte) that follows the above flag field
2829
  foreach ($this->attributes as $key => $value) {
2838
  $attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
2839
  break;
2840
  case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
2841
+ if (strlen($response) < 8) {
2842
+ user_error('Malformed file attributes');
2843
+ return $attr;
2844
+ }
2845
  $attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
2846
  break;
2847
  case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
2848
+ if (strlen($response) < 4) {
2849
+ user_error('Malformed file attributes');
2850
+ return $attr;
2851
+ }
2852
  $attr+= unpack('Npermissions', $this->_string_shift($response, 4));
2853
  // mode == permissions; permissions was the original array key and is retained for bc purposes.
2854
  // mode was added because that's the more industry standard terminology
2859
  }
2860
  break;
2861
  case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
2862
+ if (strlen($response) < 8) {
2863
+ user_error('Malformed file attributes');
2864
+ return $attr;
2865
+ }
2866
  $attr+= unpack('Natime/Nmtime', $this->_string_shift($response, 8));
2867
  break;
2868
  case NET_SFTP_ATTR_EXTENDED: // 0x80000000
2869
+ if (strlen($response) < 4) {
2870
+ user_error('Malformed file attributes');
2871
+ return $attr;
2872
+ }
2873
  extract(unpack('Ncount', $this->_string_shift($response, 4)));
2874
  for ($i = 0; $i < $count; $i++) {
2875
+ if (strlen($response) < 4) {
2876
+ user_error('Malformed file attributes');
2877
+ return $attr;
2878
+ }
2879
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2880
  $key = $this->_string_shift($response, $length);
2881
+ if (strlen($response) < 4) {
2882
+ user_error('Malformed file attributes');
2883
+ return $attr;
2884
+ }
2885
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2886
  $attr[$key] = $this->_string_shift($response, $length);
2887
  }
2895
  *
2896
  * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
2897
  *
2898
+ * @param int $mode
2899
+ * @return int
2900
  * @access private
2901
  */
2902
  function _parseMode($mode)
2942
  *
2943
  * If the longname is in an unrecognized format bool(false) is returned.
2944
  *
2945
+ * @param string $longname
2946
+ * @return mixed
2947
  * @access private
2948
  */
2949
  function _parseLongname($longname)
2971
  *
2972
  * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
2973
  *
2974
+ * @param int $type
2975
+ * @param string $data
2976
+ * @see self::_get_sftp_packet()
2977
  * @see Net_SSH2::_send_channel_packet()
2978
+ * @return bool
2979
  * @access private
2980
  */
2981
  function _send_sftp_packet($type, $data)
2982
  {
2983
  $packet = $this->request_id !== false ?
2984
  pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
2985
+ pack('NCa*', strlen($data) + 1, $type, $data);
2986
 
2987
  $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
2988
  $result = $this->_send_channel_packet(NET_SFTP_CHANNEL, $packet);
3015
  * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
3016
  * messages containing one SFTP packet.
3017
  *
3018
+ * @see self::_send_sftp_packet()
3019
+ * @return string
3020
  * @access private
3021
  */
3022
  function _get_sftp_packet()
3027
 
3028
  // SFTP packet length
3029
  while (strlen($this->packet_buffer) < 4) {
3030
+ $temp = $this->_get_channel_packet(NET_SFTP_CHANNEL, true);
3031
  if (is_bool($temp)) {
3032
  $this->packet_type = false;
3033
  $this->packet_buffer = '';
3035
  }
3036
  $this->packet_buffer.= $temp;
3037
  }
3038
+ if (strlen($this->packet_buffer) < 4) {
3039
+ return false;
3040
+ }
3041
  extract(unpack('Nlength', $this->_string_shift($this->packet_buffer, 4)));
3042
  $tempLength = $length;
3043
  $tempLength-= strlen($this->packet_buffer);
3044
 
3045
  // SFTP packet type and data payload
3046
  while ($tempLength > 0) {
3047
+ $temp = $this->_get_channel_packet(NET_SFTP_CHANNEL, true);
3048
  if (is_bool($temp)) {
3049
  $this->packet_type = false;
3050
  $this->packet_buffer = '';
3091
  * Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
3092
  *
3093
  * @access public
3094
+ * @return string or Array
3095
  */
3096
  function getSFTPLog()
3097
  {
3112
  /**
3113
  * Returns all errors
3114
  *
3115
+ * @return array
3116
  * @access public
3117
  */
3118
  function getSFTPErrors()
3123
  /**
3124
  * Returns the last error
3125
  *
3126
+ * @return string
3127
  * @access public
3128
  */
3129
  function getLastSFTPError()
3134
  /**
3135
  * Get supported SFTP versions
3136
  *
3137
+ * @return array
3138
  * @access public
3139
  */
3140
  function getSupportedVersions()
3149
  /**
3150
  * Disconnect
3151
  *
3152
+ * @param int $reason
3153
+ * @return bool
3154
  * @access private
3155
  */
3156
  function _disconnect($reason)
phpseclib/Net/SSH2.php CHANGED
@@ -69,7 +69,7 @@
69
  /**#@+
70
  * Execution Bitmap Masks
71
  *
72
- * @see Net_SSH2::bitmap
73
  * @access private
74
  */
75
  define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
@@ -92,19 +92,19 @@ define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
92
  * open request, and 'sender channel' is the channel number allocated by
93
  * the other side.
94
  *
95
- * @see Net_SSH2::_send_channel_packet()
96
- * @see Net_SSH2::_get_channel_packet()
97
  * @access private
98
  */
99
- define('NET_SSH2_CHANNEL_EXEC', 0); // PuTTy uses 0x100
100
- define('NET_SSH2_CHANNEL_SHELL', 1);
101
- define('NET_SSH2_CHANNEL_SUBSYSTEM', 2);
102
- define('NET_SSH2_CHANNEL_AGENT_FORWARD', 3);
103
  /**#@-*/
104
 
105
  /**#@+
106
  * @access public
107
- * @see Net_SSH2::getLog()
108
  */
109
  /**
110
  * Returns the message numbers
@@ -122,11 +122,15 @@ define('NET_SSH2_LOG_REALTIME', 3);
122
  * Dumps the content real-time to a file
123
  */
124
  define('NET_SSH2_LOG_REALTIME_FILE', 4);
 
 
 
 
125
  /**#@-*/
126
 
127
  /**#@+
128
  * @access public
129
- * @see Net_SSH2::read()
130
  */
131
  /**
132
  * Returns when a string matching $expect exactly is found
@@ -137,9 +141,9 @@ define('NET_SSH2_READ_SIMPLE', 1);
137
  */
138
  define('NET_SSH2_READ_REGEX', 2);
139
  /**
140
- * Make sure that the log never gets larger than this
141
  */
142
- define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
143
  /**#@-*/
144
 
145
  /**
@@ -154,7 +158,7 @@ class Net_SSH2
154
  /**
155
  * The SSH identifier
156
  *
157
- * @var String
158
  * @access private
159
  */
160
  var $identifier;
@@ -162,7 +166,7 @@ class Net_SSH2
162
  /**
163
  * The Socket Object
164
  *
165
- * @var Object
166
  * @access private
167
  */
168
  var $fsock;
@@ -173,7 +177,7 @@ class Net_SSH2
173
  * The bits that are set represent functions that have been called already. This is used to determine
174
  * if a requisite function has been successfully executed. If not, an error should be thrown.
175
  *
176
- * @var Integer
177
  * @access private
178
  */
179
  var $bitmap = 0;
@@ -181,9 +185,9 @@ class Net_SSH2
181
  /**
182
  * Error information
183
  *
184
- * @see Net_SSH2::getErrors()
185
- * @see Net_SSH2::getLastError()
186
- * @var String
187
  * @access private
188
  */
189
  var $errors = array();
@@ -191,8 +195,8 @@ class Net_SSH2
191
  /**
192
  * Server Identifier
193
  *
194
- * @see Net_SSH2::getServerIdentification()
195
- * @var mixed false or Array
196
  * @access private
197
  */
198
  var $server_identifier = false;
@@ -200,17 +204,44 @@ class Net_SSH2
200
  /**
201
  * Key Exchange Algorithms
202
  *
203
- * @see Net_SSH2::getKexAlgorithims()
204
- * @var mixed false or Array
205
  * @access private
206
  */
207
  var $kex_algorithms = false;
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  /**
210
  * Server Host Key Algorithms
211
  *
212
- * @see Net_SSH2::getServerHostKeyAlgorithms()
213
- * @var mixed false or Array
214
  * @access private
215
  */
216
  var $server_host_key_algorithms = false;
@@ -218,8 +249,8 @@ class Net_SSH2
218
  /**
219
  * Encryption Algorithms: Client to Server
220
  *
221
- * @see Net_SSH2::getEncryptionAlgorithmsClient2Server()
222
- * @var mixed false or Array
223
  * @access private
224
  */
225
  var $encryption_algorithms_client_to_server = false;
@@ -227,8 +258,8 @@ class Net_SSH2
227
  /**
228
  * Encryption Algorithms: Server to Client
229
  *
230
- * @see Net_SSH2::getEncryptionAlgorithmsServer2Client()
231
- * @var mixed false or Array
232
  * @access private
233
  */
234
  var $encryption_algorithms_server_to_client = false;
@@ -236,8 +267,8 @@ class Net_SSH2
236
  /**
237
  * MAC Algorithms: Client to Server
238
  *
239
- * @see Net_SSH2::getMACAlgorithmsClient2Server()
240
- * @var mixed false or Array
241
  * @access private
242
  */
243
  var $mac_algorithms_client_to_server = false;
@@ -245,8 +276,8 @@ class Net_SSH2
245
  /**
246
  * MAC Algorithms: Server to Client
247
  *
248
- * @see Net_SSH2::getMACAlgorithmsServer2Client()
249
- * @var mixed false or Array
250
  * @access private
251
  */
252
  var $mac_algorithms_server_to_client = false;
@@ -254,8 +285,8 @@ class Net_SSH2
254
  /**
255
  * Compression Algorithms: Client to Server
256
  *
257
- * @see Net_SSH2::getCompressionAlgorithmsClient2Server()
258
- * @var mixed false or Array
259
  * @access private
260
  */
261
  var $compression_algorithms_client_to_server = false;
@@ -263,8 +294,8 @@ class Net_SSH2
263
  /**
264
  * Compression Algorithms: Server to Client
265
  *
266
- * @see Net_SSH2::getCompressionAlgorithmsServer2Client()
267
- * @var mixed false or Array
268
  * @access private
269
  */
270
  var $compression_algorithms_server_to_client = false;
@@ -272,8 +303,8 @@ class Net_SSH2
272
  /**
273
  * Languages: Server to Client
274
  *
275
- * @see Net_SSH2::getLanguagesServer2Client()
276
- * @var mixed false or Array
277
  * @access private
278
  */
279
  var $languages_server_to_client = false;
@@ -281,8 +312,8 @@ class Net_SSH2
281
  /**
282
  * Languages: Client to Server
283
  *
284
- * @see Net_SSH2::getLanguagesClient2Server()
285
- * @var mixed false or Array
286
  * @access private
287
  */
288
  var $languages_client_to_server = false;
@@ -297,9 +328,9 @@ class Net_SSH2
297
  *
298
  * -- http://tools.ietf.org/html/rfc4253#section-6
299
  *
300
- * @see Net_SSH2::Net_SSH2()
301
- * @see Net_SSH2::_send_binary_packet()
302
- * @var Integer
303
  * @access private
304
  */
305
  var $encrypt_block_size = 8;
@@ -307,9 +338,9 @@ class Net_SSH2
307
  /**
308
  * Block Size for Client to Server Encryption
309
  *
310
- * @see Net_SSH2::Net_SSH2()
311
- * @see Net_SSH2::_get_binary_packet()
312
- * @var Integer
313
  * @access private
314
  */
315
  var $decrypt_block_size = 8;
@@ -317,8 +348,8 @@ class Net_SSH2
317
  /**
318
  * Server to Client Encryption Object
319
  *
320
- * @see Net_SSH2::_get_binary_packet()
321
- * @var Object
322
  * @access private
323
  */
324
  var $decrypt = false;
@@ -326,8 +357,8 @@ class Net_SSH2
326
  /**
327
  * Client to Server Encryption Object
328
  *
329
- * @see Net_SSH2::_send_binary_packet()
330
- * @var Object
331
  * @access private
332
  */
333
  var $encrypt = false;
@@ -335,8 +366,8 @@ class Net_SSH2
335
  /**
336
  * Client to Server HMAC Object
337
  *
338
- * @see Net_SSH2::_send_binary_packet()
339
- * @var Object
340
  * @access private
341
  */
342
  var $hmac_create = false;
@@ -344,8 +375,8 @@ class Net_SSH2
344
  /**
345
  * Server to Client HMAC Object
346
  *
347
- * @see Net_SSH2::_get_binary_packet()
348
- * @var Object
349
  * @access private
350
  */
351
  var $hmac_check = false;
@@ -357,8 +388,8 @@ class Net_SSH2
357
  * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
358
  * append it.
359
  *
360
- * @see Net_SSH2::_get_binary_packet()
361
- * @var Integer
362
  * @access private
363
  */
364
  var $hmac_size = false;
@@ -366,14 +397,14 @@ class Net_SSH2
366
  /**
367
  * Server Public Host Key
368
  *
369
- * @see Net_SSH2::getServerPublicHostKey()
370
- * @var String
371
  * @access private
372
  */
373
  var $server_public_host_key;
374
 
375
  /**
376
- * Session identifer
377
  *
378
  * "The exchange hash H from the first key exchange is additionally
379
  * used as the session identifier, which is a unique identifier for
@@ -381,8 +412,8 @@ class Net_SSH2
381
  *
382
  * -- http://tools.ietf.org/html/rfc4253#section-7.2
383
  *
384
- * @see Net_SSH2::_key_exchange()
385
- * @var String
386
  * @access private
387
  */
388
  var $session_id = false;
@@ -392,8 +423,8 @@ class Net_SSH2
392
  *
393
  * The current exchange hash
394
  *
395
- * @see Net_SSH2::_key_exchange()
396
- * @var String
397
  * @access private
398
  */
399
  var $exchange_hash = false;
@@ -401,8 +432,8 @@ class Net_SSH2
401
  /**
402
  * Message Numbers
403
  *
404
- * @see Net_SSH2::Net_SSH2()
405
- * @var Array
406
  * @access private
407
  */
408
  var $message_numbers = array();
@@ -410,8 +441,8 @@ class Net_SSH2
410
  /**
411
  * Disconnection Message 'reason codes' defined in RFC4253
412
  *
413
- * @see Net_SSH2::Net_SSH2()
414
- * @var Array
415
  * @access private
416
  */
417
  var $disconnect_reasons = array();
@@ -419,8 +450,8 @@ class Net_SSH2
419
  /**
420
  * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
421
  *
422
- * @see Net_SSH2::Net_SSH2()
423
- * @var Array
424
  * @access private
425
  */
426
  var $channel_open_failure_reasons = array();
@@ -429,8 +460,8 @@ class Net_SSH2
429
  * Terminal Modes
430
  *
431
  * @link http://tools.ietf.org/html/rfc4254#section-8
432
- * @see Net_SSH2::Net_SSH2()
433
- * @var Array
434
  * @access private
435
  */
436
  var $terminal_modes = array();
@@ -439,8 +470,8 @@ class Net_SSH2
439
  * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
440
  *
441
  * @link http://tools.ietf.org/html/rfc4254#section-5.2
442
- * @see Net_SSH2::Net_SSH2()
443
- * @var Array
444
  * @access private
445
  */
446
  var $channel_extended_data_type_codes = array();
@@ -450,8 +481,8 @@ class Net_SSH2
450
  *
451
  * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
452
  *
453
- * @see Net_SSH2::_send_binary_packet()
454
- * @var Integer
455
  * @access private
456
  */
457
  var $send_seq_no = 0;
@@ -461,8 +492,8 @@ class Net_SSH2
461
  *
462
  * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
463
  *
464
- * @see Net_SSH2::_get_binary_packet()
465
- * @var Integer
466
  * @access private
467
  */
468
  var $get_seq_no = 0;
@@ -472,9 +503,9 @@ class Net_SSH2
472
  *
473
  * Maps client channels to server channels
474
  *
475
- * @see Net_SSH2::_get_channel_packet()
476
- * @see Net_SSH2::exec()
477
- * @var Array
478
  * @access private
479
  */
480
  var $server_channels = array();
@@ -485,9 +516,9 @@ class Net_SSH2
485
  * If a client requests a packet from one channel but receives two packets from another those packets should
486
  * be placed in a buffer
487
  *
488
- * @see Net_SSH2::_get_channel_packet()
489
- * @see Net_SSH2::exec()
490
- * @var Array
491
  * @access private
492
  */
493
  var $channel_buffers = array();
@@ -497,8 +528,8 @@ class Net_SSH2
497
  *
498
  * Contains the type of the last sent message
499
  *
500
- * @see Net_SSH2::_get_channel_packet()
501
- * @var Array
502
  * @access private
503
  */
504
  var $channel_status = array();
@@ -508,8 +539,8 @@ class Net_SSH2
508
  *
509
  * Maximum packet size indexed by channel
510
  *
511
- * @see Net_SSH2::_send_channel_packet()
512
- * @var Array
513
  * @access private
514
  */
515
  var $packet_size_client_to_server = array();
@@ -517,8 +548,8 @@ class Net_SSH2
517
  /**
518
  * Message Number Log
519
  *
520
- * @see Net_SSH2::getLog()
521
- * @var Array
522
  * @access private
523
  */
524
  var $message_number_log = array();
@@ -526,8 +557,8 @@ class Net_SSH2
526
  /**
527
  * Message Log
528
  *
529
- * @see Net_SSH2::getLog()
530
- * @var Array
531
  * @access private
532
  */
533
  var $message_log = array();
@@ -537,9 +568,9 @@ class Net_SSH2
537
  *
538
  * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
539
  *
540
- * @var Integer
541
- * @see Net_SSH2::_send_channel_packet()
542
- * @see Net_SSH2::exec()
543
  * @access private
544
  */
545
  var $window_size = 0x7FFFFFFF;
@@ -549,8 +580,8 @@ class Net_SSH2
549
  *
550
  * Window size indexed by channel
551
  *
552
- * @see Net_SSH2::_send_channel_packet()
553
- * @var Array
554
  * @access private
555
  */
556
  var $window_size_server_to_client = array();
@@ -560,8 +591,8 @@ class Net_SSH2
560
  *
561
  * Window size indexed by channel
562
  *
563
- * @see Net_SSH2::_get_channel_packet()
564
- * @var Array
565
  * @access private
566
  */
567
  var $window_size_client_to_server = array();
@@ -571,8 +602,8 @@ class Net_SSH2
571
  *
572
  * Verified against $this->session_id
573
  *
574
- * @see Net_SSH2::getServerPublicHostKey()
575
- * @var String
576
  * @access private
577
  */
578
  var $signature = '';
@@ -582,8 +613,8 @@ class Net_SSH2
582
  *
583
  * ssh-rsa or ssh-dss.
584
  *
585
- * @see Net_SSH2::getServerPublicHostKey()
586
- * @var String
587
  * @access private
588
  */
589
  var $signature_format = '';
@@ -591,8 +622,8 @@ class Net_SSH2
591
  /**
592
  * Interactive Buffer
593
  *
594
- * @see Net_SSH2::read()
595
- * @var Array
596
  * @access private
597
  */
598
  var $interactiveBuffer = '';
@@ -602,9 +633,9 @@ class Net_SSH2
602
  *
603
  * Should never exceed NET_SSH2_LOG_MAX_SIZE
604
  *
605
- * @see Net_SSH2::_send_binary_packet()
606
- * @see Net_SSH2::_get_binary_packet()
607
- * @var Integer
608
  * @access private
609
  */
610
  var $log_size;
@@ -612,7 +643,7 @@ class Net_SSH2
612
  /**
613
  * Timeout
614
  *
615
- * @see Net_SSH2::setTimeout()
616
  * @access private
617
  */
618
  var $timeout;
@@ -620,7 +651,7 @@ class Net_SSH2
620
  /**
621
  * Current Timeout
622
  *
623
- * @see Net_SSH2::_get_channel_packet()
624
  * @access private
625
  */
626
  var $curTimeout;
@@ -628,8 +659,8 @@ class Net_SSH2
628
  /**
629
  * Real-time log file pointer
630
  *
631
- * @see Net_SSH2::_append_log()
632
- * @var Resource
633
  * @access private
634
  */
635
  var $realtime_log_file;
@@ -637,8 +668,8 @@ class Net_SSH2
637
  /**
638
  * Real-time log file size
639
  *
640
- * @see Net_SSH2::_append_log()
641
- * @var Integer
642
  * @access private
643
  */
644
  var $realtime_log_size;
@@ -646,8 +677,8 @@ class Net_SSH2
646
  /**
647
  * Has the signature been validated?
648
  *
649
- * @see Net_SSH2::getServerPublicHostKey()
650
- * @var Boolean
651
  * @access private
652
  */
653
  var $signature_validated = false;
@@ -655,7 +686,7 @@ class Net_SSH2
655
  /**
656
  * Real-time log file wrap boolean
657
  *
658
- * @see Net_SSH2::_append_log()
659
  * @access private
660
  */
661
  var $realtime_log_wrap;
@@ -663,7 +694,7 @@ class Net_SSH2
663
  /**
664
  * Flag to suppress stderr from output
665
  *
666
- * @see Net_SSH2::enableQuietMode()
667
  * @access private
668
  */
669
  var $quiet_mode = false;
@@ -671,7 +702,7 @@ class Net_SSH2
671
  /**
672
  * Time of first network activity
673
  *
674
- * @var Integer
675
  * @access private
676
  */
677
  var $last_packet;
@@ -679,7 +710,7 @@ class Net_SSH2
679
  /**
680
  * Exit status returned from ssh if any
681
  *
682
- * @var Integer
683
  * @access private
684
  */
685
  var $exit_status;
@@ -687,8 +718,8 @@ class Net_SSH2
687
  /**
688
  * Flag to request a PTY when using exec()
689
  *
690
- * @var Boolean
691
- * @see Net_SSH2::enablePTY()
692
  * @access private
693
  */
694
  var $request_pty = false;
@@ -696,7 +727,7 @@ class Net_SSH2
696
  /**
697
  * Flag set while exec() is running when using enablePTY()
698
  *
699
- * @var Boolean
700
  * @access private
701
  */
702
  var $in_request_pty_exec = false;
@@ -704,7 +735,7 @@ class Net_SSH2
704
  /**
705
  * Flag set after startSubsystem() is called
706
  *
707
- * @var Boolean
708
  * @access private
709
  */
710
  var $in_subsystem;
@@ -712,7 +743,7 @@ class Net_SSH2
712
  /**
713
  * Contents of stdError
714
  *
715
- * @var String
716
  * @access private
717
  */
718
  var $stdErrorLog;
@@ -720,8 +751,8 @@ class Net_SSH2
720
  /**
721
  * The Last Interactive Response
722
  *
723
- * @see Net_SSH2::_keyboard_interactive_process()
724
- * @var String
725
  * @access private
726
  */
727
  var $last_interactive_response = '';
@@ -729,8 +760,8 @@ class Net_SSH2
729
  /**
730
  * Keyboard Interactive Request / Responses
731
  *
732
- * @see Net_SSH2::_keyboard_interactive_process()
733
- * @var Array
734
  * @access private
735
  */
736
  var $keyboard_requests_responses = array();
@@ -741,9 +772,9 @@ class Net_SSH2
741
  * Quoting from the RFC, "in some jurisdictions, sending a warning message before
742
  * authentication may be relevant for getting legal protection."
743
  *
744
- * @see Net_SSH2::_filter()
745
- * @see Net_SSH2::getBannerMessage()
746
- * @var String
747
  * @access private
748
  */
749
  var $banner_message = '';
@@ -751,8 +782,8 @@ class Net_SSH2
751
  /**
752
  * Did read() timeout or return normally?
753
  *
754
- * @see Net_SSH2::isTimeout()
755
- * @var Boolean
756
  * @access private
757
  */
758
  var $is_timeout = false;
@@ -760,8 +791,8 @@ class Net_SSH2
760
  /**
761
  * Log Boundary
762
  *
763
- * @see Net_SSH2::_format_log()
764
- * @var String
765
  * @access private
766
  */
767
  var $log_boundary = ':';
@@ -769,8 +800,8 @@ class Net_SSH2
769
  /**
770
  * Log Long Width
771
  *
772
- * @see Net_SSH2::_format_log()
773
- * @var Integer
774
  * @access private
775
  */
776
  var $log_long_width = 65;
@@ -778,8 +809,8 @@ class Net_SSH2
778
  /**
779
  * Log Short Width
780
  *
781
- * @see Net_SSH2::_format_log()
782
- * @var Integer
783
  * @access private
784
  */
785
  var $log_short_width = 16;
@@ -787,9 +818,9 @@ class Net_SSH2
787
  /**
788
  * Hostname
789
  *
790
- * @see Net_SSH2::Net_SSH2()
791
- * @see Net_SSH2::_connect()
792
- * @var String
793
  * @access private
794
  */
795
  var $host;
@@ -797,9 +828,9 @@ class Net_SSH2
797
  /**
798
  * Port Number
799
  *
800
- * @see Net_SSH2::Net_SSH2()
801
- * @see Net_SSH2::_connect()
802
- * @var Integer
803
  * @access private
804
  */
805
  var $port;
@@ -807,10 +838,10 @@ class Net_SSH2
807
  /**
808
  * Number of columns for terminal window size
809
  *
810
- * @see Net_SSH2::getWindowColumns()
811
- * @see Net_SSH2::setWindowColumns()
812
- * @see Net_SSH2::setWindowSize()
813
- * @var Integer
814
  * @access private
815
  */
816
  var $windowColumns = 80;
@@ -818,10 +849,10 @@ class Net_SSH2
818
  /**
819
  * Number of columns for terminal window size
820
  *
821
- * @see Net_SSH2::getWindowRows()
822
- * @see Net_SSH2::setWindowRows()
823
- * @see Net_SSH2::setWindowSize()
824
- * @var Integer
825
  * @access private
826
  */
827
  var $windowRows = 24;
@@ -829,9 +860,9 @@ class Net_SSH2
829
  /**
830
  * Crypto Engine
831
  *
832
- * @see Net_SSH2::setCryptoEngine()
833
- * @see Net_SSH2::_key_exchange()
834
- * @var Integer
835
  * @access private
836
  */
837
  var $crypto_engine = false;
@@ -844,17 +875,67 @@ class Net_SSH2
844
  */
845
  var $agent;
846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
  /**
848
  * Default Constructor.
849
  *
850
- * @param String $host
851
- * @param optional Integer $port
852
- * @param optional Integer $timeout
853
- * @see Net_SSH2::login()
 
 
854
  * @return Net_SSH2
855
  * @access public
856
  */
857
- function Net_SSH2($host, $port = 22, $timeout = 10)
858
  {
859
  // Include Math_BigInteger
860
  // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
@@ -942,12 +1023,39 @@ class Net_SSH2
942
  array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
943
  array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
944
  array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
945
- 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE')
 
 
 
 
 
 
946
  );
947
 
948
- $this->host = $host;
949
- $this->port = $port;
950
- $this->timeout = $timeout;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
  }
952
 
953
  /**
@@ -956,18 +1064,74 @@ class Net_SSH2
956
  * Possible $engine values:
957
  * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
958
  *
959
- * @param Integer $engine
960
- * @access private
961
  */
962
  function setCryptoEngine($engine)
963
  {
964
  $this->crypto_engine = $engine;
965
  }
966
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
967
  /**
968
  * Connect to an SSHv2 server
969
  *
970
- * @return Boolean
971
  * @access private
972
  */
973
  function _connect()
@@ -980,23 +1144,33 @@ class Net_SSH2
980
 
981
  $this->curTimeout = $this->timeout;
982
 
983
- $host = $this->host . ':' . $this->port;
984
-
985
  $this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
986
 
987
- $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
988
- $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
989
- if (!$this->fsock) {
990
- user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
991
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
992
  }
993
- $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
994
 
995
- $this->curTimeout-= $elapsed;
996
 
997
- if ($this->curTimeout <= 0) {
998
- $this->is_timeout = true;
999
- return false;
1000
  }
1001
 
1002
  /* According to the SSH2 specs,
@@ -1042,8 +1216,6 @@ class Net_SSH2
1042
  return false;
1043
  }
1044
 
1045
- $this->identifier = $this->_generate_identifier();
1046
-
1047
  if (defined('NET_SSH2_LOGGING')) {
1048
  $this->_append_log('<-', $extra . $temp);
1049
  $this->_append_log('->', $this->identifier . "\r\n");
@@ -1054,25 +1226,33 @@ class Net_SSH2
1054
  $this->errors[] = utf8_decode($extra);
1055
  }
1056
 
1057
- if ($matches[1] != '1.99' && $matches[1] != '2.0') {
1058
  user_error("Cannot connect to SSH $matches[1] servers");
1059
  return false;
1060
  }
1061
 
1062
- fputs($this->fsock, $this->identifier . "\r\n");
1063
-
1064
- $response = $this->_get_binary_packet();
1065
- if ($response === false) {
1066
- user_error('Connection closed by server');
1067
- return false;
1068
  }
1069
 
1070
- if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
1071
- user_error('Expected SSH_MSG_KEXINIT');
1072
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
1073
  }
1074
 
1075
- if (!$this->_key_exchange($response)) {
1076
  return false;
1077
  }
1078
 
@@ -1087,11 +1267,11 @@ class Net_SSH2
1087
  * You should overwrite this method in your own class if you want to use another identifier
1088
  *
1089
  * @access protected
1090
- * @return String
1091
  */
1092
  function _generate_identifier()
1093
  {
1094
- $identifier = 'SSH-2.0-phpseclib_0.3';
1095
 
1096
  $ext = array();
1097
  if (extension_loaded('openssl')) {
@@ -1116,14 +1296,16 @@ class Net_SSH2
1116
  /**
1117
  * Key Exchange
1118
  *
1119
- * @param String $kexinit_payload_server
1120
  * @access private
1121
  */
1122
- function _key_exchange($kexinit_payload_server)
1123
  {
1124
  static $kex_algorithms = array(
1125
  'diffie-hellman-group1-sha1', // REQUIRED
1126
- 'diffie-hellman-group14-sha1' // REQUIRED
 
 
1127
  );
1128
 
1129
  static $server_host_key_algorithms = array(
@@ -1228,8 +1410,9 @@ class Net_SSH2
1228
  );
1229
 
1230
  // some SSH servers have buggy implementations of some of the above algorithms
1231
- switch ($this->server_identifier) {
1232
- case 'SSH-2.0-SSHD':
 
1233
  $mac_algorithms = array_values(array_diff(
1234
  $mac_algorithms,
1235
  array('hmac-sha1-96', 'hmac-md5-96')
@@ -1250,188 +1433,244 @@ class Net_SSH2
1250
 
1251
  $client_cookie = crypt_random_string(16);
1252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1253
  $response = $kexinit_payload_server;
1254
  $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
1255
  $server_cookie = $this->_string_shift($response, 16);
1256
 
 
 
 
1257
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1258
  $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
1259
 
 
 
 
1260
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1261
  $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
1262
 
 
 
 
1263
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1264
  $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1265
 
 
 
 
1266
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1267
  $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1268
 
 
 
 
1269
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1270
  $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1271
 
 
 
 
1272
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1273
  $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1274
 
 
 
 
1275
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1276
  $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1277
 
 
 
 
1278
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1279
  $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1280
 
 
 
 
1281
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1282
  $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1283
 
 
 
 
1284
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1285
  $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1286
 
 
 
 
1287
  extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
1288
  $first_kex_packet_follows = $first_kex_packet_follows != 0;
1289
 
1290
- // the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
1291
- $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
1292
- NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms,
1293
- strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server),
1294
- $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client,
1295
- strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client),
1296
- $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server,
1297
- strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '',
1298
- 0, 0
1299
- );
1300
-
1301
- if (!$this->_send_binary_packet($kexinit_payload_client)) {
1302
  return false;
1303
  }
1304
- // here ends the second place.
1305
 
1306
  // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
1307
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
1308
- if ($i == count($encryption_algorithms)) {
1309
- user_error('No compatible server to client encryption algorithms found');
1310
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1311
- }
1312
-
1313
  // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
1314
  // diffie-hellman key exchange as fast as possible
1315
- $decrypt = $encryption_algorithms[$i];
1316
- switch ($decrypt) {
1317
- case '3des-cbc':
1318
- case '3des-ctr':
1319
- $decryptKeyLength = 24; // eg. 192 / 8
1320
- break;
1321
- case 'aes256-cbc':
1322
- case 'aes256-ctr':
1323
- case 'twofish-cbc':
1324
- case 'twofish256-cbc':
1325
- case 'twofish256-ctr':
1326
- $decryptKeyLength = 32; // eg. 256 / 8
1327
- break;
1328
- case 'aes192-cbc':
1329
- case 'aes192-ctr':
1330
- case 'twofish192-cbc':
1331
- case 'twofish192-ctr':
1332
- $decryptKeyLength = 24; // eg. 192 / 8
1333
- break;
1334
- case 'aes128-cbc':
1335
- case 'aes128-ctr':
1336
- case 'twofish128-cbc':
1337
- case 'twofish128-ctr':
1338
- case 'blowfish-cbc':
1339
- case 'blowfish-ctr':
1340
- $decryptKeyLength = 16; // eg. 128 / 8
1341
- break;
1342
- case 'arcfour':
1343
- case 'arcfour128':
1344
- $decryptKeyLength = 16; // eg. 128 / 8
1345
- break;
1346
- case 'arcfour256':
1347
- $decryptKeyLength = 32; // eg. 128 / 8
1348
- break;
1349
- case 'none':
1350
- $decryptKeyLength = 0;
1351
  }
1352
 
1353
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
1354
- if ($i == count($encryption_algorithms)) {
 
1355
  user_error('No compatible client to server encryption algorithms found');
1356
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1357
  }
1358
 
1359
- $encrypt = $encryption_algorithms[$i];
1360
- switch ($encrypt) {
1361
- case '3des-cbc':
1362
- case '3des-ctr':
1363
- $encryptKeyLength = 24;
1364
- break;
1365
- case 'aes256-cbc':
1366
- case 'aes256-ctr':
1367
- case 'twofish-cbc':
1368
- case 'twofish256-cbc':
1369
- case 'twofish256-ctr':
1370
- $encryptKeyLength = 32;
1371
- break;
1372
- case 'aes192-cbc':
1373
- case 'aes192-ctr':
1374
- case 'twofish192-cbc':
1375
- case 'twofish192-ctr':
1376
- $encryptKeyLength = 24;
1377
- break;
1378
- case 'aes128-cbc':
1379
- case 'aes128-ctr':
1380
- case 'twofish128-cbc':
1381
- case 'twofish128-ctr':
1382
- case 'blowfish-cbc':
1383
- case 'blowfish-ctr':
1384
- $encryptKeyLength = 16;
1385
- break;
1386
- case 'arcfour':
1387
- case 'arcfour128':
1388
- $encryptKeyLength = 16;
1389
- break;
1390
- case 'arcfour256':
1391
- $encryptKeyLength = 32;
1392
- break;
1393
- case 'none':
1394
- $encryptKeyLength = 0;
1395
- }
1396
-
1397
  $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
1398
 
1399
  // through diffie-hellman key exchange a symmetric key is obtained
1400
- for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
1401
- if ($i == count($kex_algorithms)) {
1402
  user_error('No compatible key exchange algorithms found');
1403
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1404
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1405
 
1406
- switch ($kex_algorithms[$i]) {
1407
- // see http://tools.ietf.org/html/rfc2409#section-6.2 and
1408
- // http://tools.ietf.org/html/rfc2412, appendex E
1409
- case 'diffie-hellman-group1-sha1':
1410
- $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
1411
- '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
1412
- '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
1413
- 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
1414
- break;
1415
- // see http://tools.ietf.org/html/rfc3526#section-3
1416
- case 'diffie-hellman-group14-sha1':
1417
- $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
1418
- '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
1419
- '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
1420
- 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
1421
- '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
1422
- '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
1423
- 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
1424
- '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1425
  break;
 
 
1426
  }
1427
 
1428
- // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
1429
- // the generator field element is 2 (decimal) and the hash function is sha1.
1430
- $g = new Math_BigInteger(2);
1431
- $prime = new Math_BigInteger($prime, 16);
1432
- $kexHash = new Crypt_Hash('sha1');
1433
- //$q = $p->bitwise_rightShift(1);
1434
-
1435
  /* To increase the speed of the key exchange, both client and server may
1436
  reduce the size of their private exponents. It should be at least
1437
  twice as long as the key material that is generated from the shared
@@ -1448,7 +1687,7 @@ class Net_SSH2
1448
  $e = $g->modPow($x, $prime);
1449
 
1450
  $eBytes = $e->toBytes(true);
1451
- $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
1452
 
1453
  if (!$this->_send_binary_packet($data)) {
1454
  user_error('Connection closed by server');
@@ -1460,37 +1699,69 @@ class Net_SSH2
1460
  user_error('Connection closed by server');
1461
  return false;
1462
  }
 
 
 
1463
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1464
 
1465
- if ($type != NET_SSH2_MSG_KEXDH_REPLY) {
1466
  user_error('Expected SSH_MSG_KEXDH_REPLY');
1467
  return false;
1468
  }
1469
 
 
 
 
1470
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1471
  $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
1472
 
 
 
 
1473
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
1474
  $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
1475
 
 
 
 
1476
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1477
  $fBytes = $this->_string_shift($response, $temp['length']);
1478
  $f = new Math_BigInteger($fBytes, -256);
1479
 
 
 
 
1480
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1481
  $this->signature = $this->_string_shift($response, $temp['length']);
1482
 
 
 
 
1483
  $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
1484
  $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
1485
 
1486
  $key = $f->modPow($x, $prime);
1487
  $keyBytes = $key->toBytes(true);
1488
 
1489
- $this->exchange_hash = pack('Na*Na*Na*Na*Na*Na*Na*Na*',
1490
- strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier,
1491
- strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server),
1492
- $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes),
1493
- $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1494
  );
1495
 
1496
  $this->exchange_hash = $kexHash->hash($this->exchange_hash);
@@ -1499,18 +1770,19 @@ class Net_SSH2
1499
  $this->session_id = $this->exchange_hash;
1500
  }
1501
 
1502
- for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
1503
- if ($i == count($server_host_key_algorithms)) {
1504
  user_error('No compatible server host key algorithms found');
1505
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1506
  }
1507
 
1508
- if ($public_key_format != $server_host_key_algorithms[$i] || $this->signature_format != $server_host_key_algorithms[$i]) {
1509
  user_error('Server Host Key Algorithm Mismatch');
1510
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1511
  }
1512
 
1513
- $packet = pack('C',
 
1514
  NET_SSH2_MSG_NEWKEYS
1515
  );
1516
 
@@ -1525,6 +1797,9 @@ class Net_SSH2
1525
  return false;
1526
  }
1527
 
 
 
 
1528
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1529
 
1530
  if ($type != NET_SSH2_MSG_NEWKEYS) {
@@ -1686,6 +1961,8 @@ class Net_SSH2
1686
  //$this->decrypt = new Crypt_Null();
1687
  }
1688
 
 
 
1689
  $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
1690
 
1691
  if ($this->encrypt) {
@@ -1742,14 +2019,14 @@ class Net_SSH2
1742
  $this->decrypt->decrypt(str_repeat("\0", 1536));
1743
  }
1744
 
1745
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
1746
- if ($i == count($mac_algorithms)) {
1747
  user_error('No compatible client to server message authentication algorithms found');
1748
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1749
  }
1750
 
1751
- $createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
1752
- switch ($mac_algorithms[$i]) {
1753
  case 'hmac-sha2-256':
1754
  $this->hmac_create = new Crypt_Hash('sha256');
1755
  $createKeyLength = 32;
@@ -1771,15 +2048,15 @@ class Net_SSH2
1771
  $createKeyLength = 16;
1772
  }
1773
 
1774
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
1775
- if ($i == count($mac_algorithms)) {
1776
  user_error('No compatible server to client message authentication algorithms found');
1777
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1778
  }
1779
 
1780
  $checkKeyLength = 0;
1781
  $this->hmac_size = 0;
1782
- switch ($mac_algorithms[$i]) {
1783
  case 'hmac-sha2-256':
1784
  $this->hmac_check = new Crypt_Hash('sha256');
1785
  $checkKeyLength = 32;
@@ -1818,21 +2095,85 @@ class Net_SSH2
1818
  }
1819
  $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
1820
 
1821
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
1822
- if ($i == count($compression_algorithms)) {
1823
  user_error('No compatible server to client compression algorithms found');
1824
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1825
  }
1826
- $this->decompress = $compression_algorithms[$i] == 'zlib';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1827
 
1828
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
1829
- if ($i == count($compression_algorithms)) {
1830
- user_error('No compatible client to server compression algorithms found');
1831
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
 
 
 
 
 
 
 
 
 
 
 
 
1832
  }
1833
- $this->compress = $compression_algorithms[$i] == 'zlib';
1834
 
1835
- return true;
1836
  }
1837
 
1838
  /**
@@ -1840,11 +2181,11 @@ class Net_SSH2
1840
  *
1841
  * The $password parameter can be a plaintext password, a Crypt_RSA object or an array
1842
  *
1843
- * @param String $username
1844
- * @param Mixed $password
1845
- * @param Mixed $...
1846
- * @return Boolean
1847
- * @see _login
1848
  * @access public
1849
  */
1850
  function login($username)
@@ -1856,11 +2197,11 @@ class Net_SSH2
1856
  /**
1857
  * Login Helper
1858
  *
1859
- * @param String $username
1860
- * @param Mixed $password
1861
- * @param Mixed $...
1862
- * @return Boolean
1863
- * @see _login_helper
1864
  * @access private
1865
  */
1866
  function _login($username)
@@ -1887,9 +2228,9 @@ class Net_SSH2
1887
  /**
1888
  * Login Helper
1889
  *
1890
- * @param String $username
1891
- * @param optional String $password
1892
- * @return Boolean
1893
  * @access private
1894
  * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
1895
  * by sending dummy SSH_MSG_IGNORE messages.
@@ -1901,8 +2242,11 @@ class Net_SSH2
1901
  }
1902
 
1903
  if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) {
1904
- $packet = pack('CNa*',
1905
- NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
 
 
 
1906
  );
1907
 
1908
  if (!$this->_send_binary_packet($packet)) {
@@ -1911,10 +2255,20 @@ class Net_SSH2
1911
 
1912
  $response = $this->_get_binary_packet();
1913
  if ($response === false) {
 
 
 
 
 
 
 
1914
  user_error('Connection closed by server');
1915
  return false;
1916
  }
1917
 
 
 
 
1918
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1919
 
1920
  if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
@@ -1947,9 +2301,15 @@ class Net_SSH2
1947
  }
1948
 
1949
  if (!isset($password)) {
1950
- $packet = pack('CNa*Na*Na*',
1951
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
1952
- strlen('none'), 'none'
 
 
 
 
 
 
1953
  );
1954
 
1955
  if (!$this->_send_binary_packet($packet)) {
@@ -1962,6 +2322,9 @@ class Net_SSH2
1962
  return false;
1963
  }
1964
 
 
 
 
1965
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1966
 
1967
  switch ($type) {
@@ -1974,18 +2337,36 @@ class Net_SSH2
1974
  }
1975
  }
1976
 
1977
- $packet = pack('CNa*Na*Na*CNa*',
1978
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
1979
- strlen('password'), 'password', 0, strlen($password), $password
 
 
 
 
 
 
 
 
 
1980
  );
1981
 
1982
  // remove the username and password from the logged packet
1983
  if (!defined('NET_SSH2_LOGGING')) {
1984
  $logged = null;
1985
  } else {
1986
- $logged = pack('CNa*Na*Na*CNa*',
1987
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection',
1988
- strlen('password'), 'password', 0, strlen('password'), 'password'
 
 
 
 
 
 
 
 
 
1989
  );
1990
  }
1991
 
@@ -1999,6 +2380,9 @@ class Net_SSH2
1999
  return false;
2000
  }
2001
 
 
 
 
2002
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2003
 
2004
  switch ($type) {
@@ -2006,14 +2390,23 @@ class Net_SSH2
2006
  if (defined('NET_SSH2_LOGGING')) {
2007
  $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ';
2008
  }
 
 
 
2009
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2010
  $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode($this->_string_shift($response, $length));
2011
  return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
2012
  case NET_SSH2_MSG_USERAUTH_FAILURE:
2013
  // can we use keyboard-interactive authentication? if not then either the login is bad or the server employees
2014
  // multi-factor authentication
 
 
 
2015
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2016
  $auth_methods = explode(',', $this->_string_shift($response, $length));
 
 
 
2017
  extract(unpack('Cpartial_success', $this->_string_shift($response, 1)));
2018
  $partial_success = $partial_success != 0;
2019
 
@@ -2038,16 +2431,26 @@ class Net_SSH2
2038
  *
2039
  * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator.
2040
  *
2041
- * @param String $username
2042
- * @param String $password
2043
- * @return Boolean
2044
  * @access private
2045
  */
2046
  function _keyboard_interactive_login($username, $password)
2047
  {
2048
- $packet = pack('CNa*Na*Na*Na*Na*',
2049
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
2050
- strlen('keyboard-interactive'), 'keyboard-interactive', 0, '', 0, ''
 
 
 
 
 
 
 
 
 
 
2051
  );
2052
 
2053
  if (!$this->_send_binary_packet($packet)) {
@@ -2060,8 +2463,8 @@ class Net_SSH2
2060
  /**
2061
  * Handle the keyboard-interactive requests / responses.
2062
  *
2063
- * @param String $responses...
2064
- * @return Boolean
2065
  * @access private
2066
  */
2067
  function _keyboard_interactive_process()
@@ -2078,16 +2481,31 @@ class Net_SSH2
2078
  }
2079
  }
2080
 
 
 
 
2081
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2082
 
2083
  switch ($type) {
2084
  case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
 
 
 
2085
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2086
  $this->_string_shift($response, $length); // name; may be empty
 
 
 
2087
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2088
  $this->_string_shift($response, $length); // instruction; may be empty
 
 
 
2089
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2090
  $this->_string_shift($response, $length); // language tag; may be empty
 
 
 
2091
  extract(unpack('Nnum_prompts', $this->_string_shift($response, 4)));
2092
 
2093
  for ($i = 0; $i < count($responses); $i++) {
@@ -2102,6 +2520,9 @@ class Net_SSH2
2102
 
2103
  if (isset($this->keyboard_requests_responses)) {
2104
  for ($i = 0; $i < $num_prompts; $i++) {
 
 
 
2105
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2106
  // prompt - ie. "Password: "; must not be empty
2107
  $prompt = $this->_string_shift($response, $length);
@@ -2118,7 +2539,7 @@ class Net_SSH2
2118
  // see http://tools.ietf.org/html/rfc4256#section-3.2
2119
  if (strlen($this->last_interactive_response)) {
2120
  $this->last_interactive_response = '';
2121
- } else if (defined('NET_SSH2_LOGGING')) {
2122
  $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
2123
  'UNKNOWN',
2124
  'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
@@ -2174,9 +2595,9 @@ class Net_SSH2
2174
  /**
2175
  * Login with an ssh-agent provided key
2176
  *
2177
- * @param String $username
2178
  * @param System_SSH_Agent $agent
2179
- * @return Boolean
2180
  * @access private
2181
  */
2182
  function _ssh_agent_login($username, $agent)
@@ -2195,9 +2616,9 @@ class Net_SSH2
2195
  /**
2196
  * Login with an RSA private key
2197
  *
2198
- * @param String $username
2199
  * @param Crypt_RSA $password
2200
- * @return Boolean
2201
  * @access private
2202
  * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
2203
  * by sending dummy SSH_MSG_IGNORE messages.
@@ -2214,13 +2635,25 @@ class Net_SSH2
2214
  'e' => $publickey['e']->toBytes(true),
2215
  'n' => $publickey['n']->toBytes(true)
2216
  );
2217
- $publickey = pack('Na*Na*Na*',
2218
- strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey['e']), $publickey['e'], strlen($publickey['n']), $publickey['n']
 
 
 
 
 
 
2219
  );
2220
 
2221
- $part1 = pack('CNa*Na*Na*',
2222
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
2223
- strlen('publickey'), 'publickey'
 
 
 
 
 
 
2224
  );
2225
  $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey);
2226
 
@@ -2235,10 +2668,16 @@ class Net_SSH2
2235
  return false;
2236
  }
2237
 
 
 
 
2238
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2239
 
2240
  switch ($type) {
2241
  case NET_SSH2_MSG_USERAUTH_FAILURE:
 
 
 
2242
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2243
  $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
2244
  return false;
@@ -2270,6 +2709,9 @@ class Net_SSH2
2270
  return false;
2271
  }
2272
 
 
 
 
2273
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2274
 
2275
  switch ($type) {
@@ -2290,7 +2732,7 @@ class Net_SSH2
2290
  * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
2291
  * Setting $timeout to false or 0 will mean there is no timeout.
2292
  *
2293
- * @param Mixed $timeout
2294
  * @access public
2295
  */
2296
  function setTimeout($timeout)
@@ -2314,9 +2756,9 @@ class Net_SSH2
2314
  * If $callback is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
2315
  * In all likelihood, this is not a feature you want to be taking advantage of.
2316
  *
2317
- * @param String $command
2318
- * @param optional Callback $callback
2319
- * @return String
2320
  * @access public
2321
  */
2322
  function exec($command, $callback = null)
@@ -2325,21 +2767,33 @@ class Net_SSH2
2325
  $this->is_timeout = false;
2326
  $this->stdErrorLog = '';
2327
 
2328
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
 
 
 
 
 
2329
  return false;
2330
  }
2331
 
2332
  // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
2333
  // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
2334
- // honestly, if you're transfering more than 2GB, you probably shouldn't be using phpseclib, anyway.
2335
  // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
2336
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size;
2337
  // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
2338
  // uses 0x4000, that's what will be used here, as well.
2339
  $packet_size = 0x4000;
2340
 
2341
- $packet = pack('CNa*N3',
2342
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_EXEC, $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC], $packet_size);
 
 
 
 
 
 
 
2343
 
2344
  if (!$this->_send_binary_packet($packet)) {
2345
  return false;
@@ -2354,9 +2808,22 @@ class Net_SSH2
2354
 
2355
  if ($this->request_pty === true) {
2356
  $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
2357
- $packet = pack('CNNa*CNa*N5a*',
2358
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
2359
- $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
 
 
 
 
 
 
 
 
 
 
 
 
 
2360
 
2361
  if (!$this->_send_binary_packet($packet)) {
2362
  return false;
@@ -2368,6 +2835,9 @@ class Net_SSH2
2368
  return false;
2369
  }
2370
 
 
 
 
2371
  list(, $type) = unpack('C', $this->_string_shift($response, 1));
2372
 
2373
  switch ($type) {
@@ -2390,8 +2860,16 @@ class Net_SSH2
2390
  // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
2391
  // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
2392
  // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
2393
- $packet = pack('CNNa*CNa*',
2394
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command);
 
 
 
 
 
 
 
 
2395
 
2396
  if (!$this->_send_binary_packet($packet)) {
2397
  return false;
@@ -2434,9 +2912,9 @@ class Net_SSH2
2434
  /**
2435
  * Creates an interactive shell
2436
  *
2437
- * @see Net_SSH2::read()
2438
- * @see Net_SSH2::write()
2439
- * @return Boolean
2440
  * @access private
2441
  */
2442
  function _initShell()
@@ -2448,8 +2926,15 @@ class Net_SSH2
2448
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size;
2449
  $packet_size = 0x4000;
2450
 
2451
- $packet = pack('CNa*N3',
2452
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SHELL, $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL], $packet_size);
 
 
 
 
 
 
 
2453
 
2454
  if (!$this->_send_binary_packet($packet)) {
2455
  return false;
@@ -2463,9 +2948,22 @@ class Net_SSH2
2463
  }
2464
 
2465
  $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
2466
- $packet = pack('CNNa*CNa*N5a*',
2467
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
2468
- $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
 
 
 
 
 
 
 
 
 
 
 
 
 
2469
 
2470
  if (!$this->_send_binary_packet($packet)) {
2471
  return false;
@@ -2477,6 +2975,9 @@ class Net_SSH2
2477
  return false;
2478
  }
2479
 
 
 
 
2480
  list(, $type) = unpack('C', $this->_string_shift($response, 1));
2481
 
2482
  switch ($type) {
@@ -2489,8 +2990,14 @@ class Net_SSH2
2489
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
2490
  }
2491
 
2492
- $packet = pack('CNNa*C',
2493
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('shell'), 'shell', 1);
 
 
 
 
 
 
2494
  if (!$this->_send_binary_packet($packet)) {
2495
  return false;
2496
  }
@@ -2512,9 +3019,9 @@ class Net_SSH2
2512
  /**
2513
  * Return the channel to be used with read() / write()
2514
  *
2515
- * @see Net_SSH2::read()
2516
- * @see Net_SSH2::write()
2517
- * @return Integer
2518
  * @access public
2519
  */
2520
  function _get_interactive_channel()
@@ -2532,7 +3039,7 @@ class Net_SSH2
2532
  /**
2533
  * Return an available open channel
2534
  *
2535
- * @return Integer
2536
  * @access public
2537
  */
2538
  function _get_open_channel()
@@ -2553,10 +3060,10 @@ class Net_SSH2
2553
  * Returns when there's a match for $expect, which can take the form of a string literal or,
2554
  * if $mode == NET_SSH2_READ_REGEX, a regular expression.
2555
  *
2556
- * @see Net_SSH2::write()
2557
- * @param String $expect
2558
- * @param Integer $mode
2559
- * @return String
2560
  * @access public
2561
  */
2562
  function read($expect = '', $mode = NET_SSH2_READ_SIMPLE)
@@ -2564,7 +3071,7 @@ class Net_SSH2
2564
  $this->curTimeout = $this->timeout;
2565
  $this->is_timeout = false;
2566
 
2567
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
2568
  user_error('Operation disallowed prior to login()');
2569
  return false;
2570
  }
@@ -2576,10 +3083,14 @@ class Net_SSH2
2576
 
2577
  $channel = $this->_get_interactive_channel();
2578
 
 
 
 
 
2579
  $match = $expect;
2580
  while (true) {
2581
  if ($mode == NET_SSH2_READ_REGEX) {
2582
- preg_match($expect, $this->interactiveBuffer, $matches);
2583
  $match = isset($matches[0]) ? $matches[0] : '';
2584
  }
2585
  $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
@@ -2599,14 +3110,14 @@ class Net_SSH2
2599
  /**
2600
  * Inputs a command into an interactive shell.
2601
  *
2602
- * @see Net_SSH2::read()
2603
- * @param String $cmd
2604
- * @return Boolean
2605
  * @access public
2606
  */
2607
  function write($cmd)
2608
  {
2609
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
2610
  user_error('Operation disallowed prior to login()');
2611
  return false;
2612
  }
@@ -2628,17 +3139,24 @@ class Net_SSH2
2628
  * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
2629
  * if there's sufficient demand for such a feature.
2630
  *
2631
- * @see Net_SSH2::stopSubsystem()
2632
- * @param String $subsystem
2633
- * @return Boolean
2634
  * @access public
2635
  */
2636
  function startSubsystem($subsystem)
2637
  {
2638
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_SUBSYSTEM] = $this->window_size;
2639
 
2640
- $packet = pack('CNa*N3',
2641
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SUBSYSTEM, $this->window_size, 0x4000);
 
 
 
 
 
 
 
2642
 
2643
  if (!$this->_send_binary_packet($packet)) {
2644
  return false;
@@ -2651,8 +3169,16 @@ class Net_SSH2
2651
  return false;
2652
  }
2653
 
2654
- $packet = pack('CNNa*CNa*',
2655
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SUBSYSTEM], strlen('subsystem'), 'subsystem', 1, strlen($subsystem), $subsystem);
 
 
 
 
 
 
 
 
2656
  if (!$this->_send_binary_packet($packet)) {
2657
  return false;
2658
  }
@@ -2662,7 +3188,7 @@ class Net_SSH2
2662
  $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
2663
 
2664
  if ($response === false) {
2665
- return false;
2666
  }
2667
 
2668
  $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
@@ -2676,8 +3202,8 @@ class Net_SSH2
2676
  /**
2677
  * Stops a subsystem.
2678
  *
2679
- * @see Net_SSH2::startSubsystem()
2680
- * @return Boolean
2681
  * @access public
2682
  */
2683
  function stopSubsystem()
@@ -2740,7 +3266,7 @@ class Net_SSH2
2740
  /**
2741
  * Is the connection still active?
2742
  *
2743
- * @return boolean
2744
  * @access public
2745
  */
2746
  function isConnected()
@@ -2748,16 +3274,45 @@ class Net_SSH2
2748
  return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
2749
  }
2750
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2751
  /**
2752
  * Gets Binary Packets
2753
  *
2754
  * See '6. Binary Packet Protocol' of rfc4253 for more info.
2755
  *
2756
- * @see Net_SSH2::_send_binary_packet()
2757
- * @return String
2758
  * @access private
2759
  */
2760
- function _get_binary_packet()
2761
  {
2762
  if (!is_resource($this->fsock) || feof($this->fsock)) {
2763
  user_error('Connection closed prematurely');
@@ -2780,6 +3335,9 @@ class Net_SSH2
2780
  return false;
2781
  }
2782
 
 
 
 
2783
  extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
2784
 
2785
  $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
@@ -2788,6 +3346,11 @@ class Net_SSH2
2788
  // "implementations SHOULD check that the packet length is reasonable"
2789
  // PuTTY uses 0x9000 as the actual max packet size and so to shall we
2790
  if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
 
 
 
 
 
2791
  user_error('Invalid size');
2792
  return false;
2793
  }
@@ -2803,6 +3366,7 @@ class Net_SSH2
2803
  $buffer.= $temp;
2804
  $remaining_length-= strlen($temp);
2805
  }
 
2806
  $stop = strtok(microtime(), ' ') + strtok('');
2807
  if (strlen($buffer)) {
2808
  $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
@@ -2838,7 +3402,7 @@ class Net_SSH2
2838
  $this->last_packet = $current;
2839
  }
2840
 
2841
- return $this->_filter($payload);
2842
  }
2843
 
2844
  /**
@@ -2846,52 +3410,76 @@ class Net_SSH2
2846
  *
2847
  * Because some binary packets need to be ignored...
2848
  *
2849
- * @see Net_SSH2::_get_binary_packet()
2850
- * @return String
2851
  * @access private
2852
  */
2853
- function _filter($payload)
2854
  {
2855
  switch (ord($payload[0])) {
2856
  case NET_SSH2_MSG_DISCONNECT:
2857
  $this->_string_shift($payload, 1);
 
 
 
2858
  extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
2859
  $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length));
2860
  $this->bitmap = 0;
2861
  return false;
2862
  case NET_SSH2_MSG_IGNORE:
2863
- $payload = $this->_get_binary_packet();
2864
  break;
2865
  case NET_SSH2_MSG_DEBUG:
2866
  $this->_string_shift($payload, 2);
 
 
 
2867
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
2868
  $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length));
2869
- $payload = $this->_get_binary_packet();
2870
  break;
2871
  case NET_SSH2_MSG_UNIMPLEMENTED:
2872
  return false;
2873
  case NET_SSH2_MSG_KEXINIT:
2874
  if ($this->session_id !== false) {
 
2875
  if (!$this->_key_exchange($payload)) {
2876
  $this->bitmap = 0;
2877
  return false;
2878
  }
2879
- $payload = $this->_get_binary_packet();
2880
  }
2881
  }
2882
 
2883
  // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
2884
- if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
2885
  $this->_string_shift($payload, 1);
 
 
 
2886
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
2887
  $this->banner_message = utf8_decode($this->_string_shift($payload, $length));
2888
  $payload = $this->_get_binary_packet();
2889
  }
2890
 
2891
  // only called when we've already logged in
2892
- if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) {
2893
  switch (ord($payload[0])) {
 
 
 
 
 
 
 
 
 
 
 
2894
  case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
 
 
 
2895
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
2896
  $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
2897
 
@@ -2899,55 +3487,81 @@ class Net_SSH2
2899
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
2900
  }
2901
 
2902
- $payload = $this->_get_binary_packet();
2903
  break;
2904
  case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
2905
  $this->_string_shift($payload, 1);
 
 
 
2906
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
2907
  $data = $this->_string_shift($payload, $length);
 
 
 
2908
  extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
2909
- switch($data) {
2910
  case 'auth-agent':
2911
  case 'auth-agent@openssh.com':
2912
  if (isset($this->agent)) {
2913
- $new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD;
2914
-
2915
- extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
2916
- extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
2917
-
2918
- $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
2919
- $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
2920
- $this->window_size_client_to_server[$new_channel] = $this->window_size;
2921
-
2922
- $packet_size = 0x4000;
2923
-
2924
- $packet = pack('CN4',
2925
- NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size);
2926
-
2927
- $this->server_channels[$new_channel] = $server_channel;
2928
- $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
2929
- if (!$this->_send_binary_packet($packet)) {
2930
- return false;
2931
- }
 
 
 
 
 
 
 
 
 
2932
  }
2933
  break;
2934
  default:
2935
- $packet = pack('CN3a*Na*',
2936
- NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
 
 
 
 
 
 
 
 
2937
 
2938
  if (!$this->_send_binary_packet($packet)) {
2939
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
2940
  }
2941
  }
2942
- $payload = $this->_get_binary_packet();
2943
  break;
2944
  case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
2945
  $this->_string_shift($payload, 1);
 
 
 
2946
  extract(unpack('Nchannel', $this->_string_shift($payload, 4)));
2947
  extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
2948
  $this->window_size_client_to_server[$channel]+= $window_size;
2949
 
2950
- $payload = ($this->bitmap & NET_SSH2_MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet();
2951
  }
2952
  }
2953
 
@@ -2981,11 +3595,11 @@ class Net_SSH2
2981
  /**
2982
  * Returns whether Quiet Mode is enabled or not
2983
  *
2984
- * @see Net_SSH2::enableQuietMode()
2985
- * @see Net_SSH2::disableQuietMode()
2986
  *
2987
  * @access public
2988
- * @return boolean
2989
  */
2990
  function isQuietModeEnabled()
2991
  {
@@ -3009,17 +3623,21 @@ class Net_SSH2
3009
  */
3010
  function disablePTY()
3011
  {
 
 
 
 
3012
  $this->request_pty = false;
3013
  }
3014
 
3015
  /**
3016
  * Returns whether request-pty is enabled or not
3017
  *
3018
- * @see Net_SSH2::enablePTY()
3019
- * @see Net_SSH2::disablePTY()
3020
  *
3021
  * @access public
3022
- * @return boolean
3023
  */
3024
  function isPTYEnabled()
3025
  {
@@ -3032,7 +3650,7 @@ class Net_SSH2
3032
  * Returns the data as a string if it's available and false if not.
3033
  *
3034
  * @param $client_channel
3035
- * @return Mixed
3036
  * @access private
3037
  */
3038
  function _get_channel_packet($client_channel, $skip_extended = false)
@@ -3042,32 +3660,38 @@ class Net_SSH2
3042
  }
3043
 
3044
  while (true) {
3045
- if ($this->curTimeout) {
3046
- if ($this->curTimeout < 0) {
3047
- $this->is_timeout = true;
3048
- return true;
3049
- }
 
 
 
 
3050
 
3051
- $read = array($this->fsock);
3052
- $write = $except = null;
3053
 
3054
- $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
3055
- $sec = floor($this->curTimeout);
3056
- $usec = 1000000 * ($this->curTimeout - $sec);
3057
- // on windows this returns a "Warning: Invalid CRT parameters detected" error
3058
- if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
3059
- $this->is_timeout = true;
3060
- return true;
 
 
 
3061
  }
3062
- $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
3063
- $this->curTimeout-= $elapsed;
3064
- }
3065
 
3066
- $response = $this->_get_binary_packet();
3067
- if ($response === false) {
3068
- user_error('Connection closed by server');
3069
- return false;
 
3070
  }
 
3071
  if ($client_channel == -1 && $response === true) {
3072
  return true;
3073
  }
@@ -3075,8 +3699,14 @@ class Net_SSH2
3075
  return '';
3076
  }
3077
 
 
 
 
3078
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
3079
 
 
 
 
3080
  if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
3081
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3082
  } else {
@@ -3096,14 +3726,54 @@ class Net_SSH2
3096
  $this->window_size_server_to_client[$channel]+= $this->window_size;
3097
  }
3098
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3099
  switch ($this->channel_status[$channel]) {
3100
  case NET_SSH2_MSG_CHANNEL_OPEN:
3101
  switch ($type) {
3102
  case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
 
 
 
3103
  extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
3104
  $this->server_channels[$channel] = $server_channel;
 
 
 
3105
  extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
 
 
 
 
3106
  $this->window_size_client_to_server[$channel] = $window_size;
 
 
 
3107
  $temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
3108
  $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
3109
  $result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
@@ -3143,6 +3813,9 @@ class Net_SSH2
3143
  $this->_send_channel_packet($channel, chr(0));
3144
  }
3145
  */
 
 
 
3146
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3147
  $data = $this->_string_shift($response, $length);
3148
 
@@ -3154,27 +3827,6 @@ class Net_SSH2
3154
  break;
3155
  }
3156
 
3157
- if ($client_channel == $channel) {
3158
- return $data;
3159
- }
3160
- if (!isset($this->channel_buffers[$channel])) {
3161
- $this->channel_buffers[$channel] = array();
3162
- }
3163
- $this->channel_buffers[$channel][] = $data;
3164
- break;
3165
- case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
3166
- /*
3167
- if ($client_channel == NET_SSH2_CHANNEL_EXEC) {
3168
- $this->_send_channel_packet($client_channel, chr(0));
3169
- }
3170
- */
3171
- // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
3172
- extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
3173
- $data = $this->_string_shift($response, $length);
3174
- $this->stdErrorLog.= $data;
3175
- if ($skip_extended || $this->quiet_mode) {
3176
- break;
3177
- }
3178
  if ($client_channel == $channel) {
3179
  return $data;
3180
  }
@@ -3184,14 +3836,23 @@ class Net_SSH2
3184
  $this->channel_buffers[$channel][] = $data;
3185
  break;
3186
  case NET_SSH2_MSG_CHANNEL_REQUEST:
 
 
 
3187
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3188
  $value = $this->_string_shift($response, $length);
3189
  switch ($value) {
3190
  case 'exit-signal':
3191
  $this->_string_shift($response, 1);
 
 
 
3192
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3193
  $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
3194
  $this->_string_shift($response, 1);
 
 
 
3195
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3196
  if ($length) {
3197
  $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
@@ -3204,6 +3865,9 @@ class Net_SSH2
3204
 
3205
  break;
3206
  case 'exit-status':
 
 
 
3207
  extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
3208
  $this->exit_status = $exit_status;
3209
 
@@ -3228,7 +3892,9 @@ class Net_SSH2
3228
  }
3229
 
3230
  $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
3231
- return true;
 
 
3232
  case NET_SSH2_MSG_CHANNEL_EOF:
3233
  break;
3234
  default:
@@ -3243,10 +3909,10 @@ class Net_SSH2
3243
  *
3244
  * See '6. Binary Packet Protocol' of rfc4253 for more info.
3245
  *
3246
- * @param String $data
3247
- * @param optional String $logged
3248
- * @see Net_SSH2::_get_binary_packet()
3249
- * @return Boolean
3250
  * @access private
3251
  */
3252
  function _send_binary_packet($data, $logged = null)
@@ -3304,7 +3970,7 @@ class Net_SSH2
3304
  *
3305
  * Makes sure that only the last 1MB worth of packets will be logged
3306
  *
3307
- * @param String $data
3308
  * @access private
3309
  */
3310
  function _append_log($message_number, $message)
@@ -3380,9 +4046,9 @@ class Net_SSH2
3380
  *
3381
  * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
3382
  *
3383
- * @param Integer $client_channel
3384
- * @param String $data
3385
- * @return Boolean
3386
  * @access private
3387
  */
3388
  function _send_channel_packet($client_channel, $data)
@@ -3405,7 +4071,8 @@ class Net_SSH2
3405
  );
3406
 
3407
  $temp = $this->_string_shift($data, $max_size);
3408
- $packet = pack('CN2a*',
 
3409
  NET_SSH2_MSG_CHANNEL_DATA,
3410
  $this->server_channels[$client_channel],
3411
  strlen($temp),
@@ -3427,9 +4094,9 @@ class Net_SSH2
3427
  * and for SFTP channels are presumably closed when the client disconnects. This functions is intended
3428
  * for SCP more than anything.
3429
  *
3430
- * @param Integer $client_channel
3431
- * @param Boolean $want_reply
3432
- * @return Boolean
3433
  * @access private
3434
  */
3435
  function _close_channel($client_channel, $want_reply = false)
@@ -3446,7 +4113,8 @@ class Net_SSH2
3446
 
3447
  $this->curTimeout = 0;
3448
 
3449
- while (!is_bool($this->_get_channel_packet($client_channel)));
 
3450
 
3451
  if ($want_reply) {
3452
  $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
@@ -3460,8 +4128,8 @@ class Net_SSH2
3460
  /**
3461
  * Disconnect
3462
  *
3463
- * @param Integer $reason
3464
- * @return Boolean
3465
  * @access private
3466
  */
3467
  function _disconnect($reason)
@@ -3480,9 +4148,9 @@ class Net_SSH2
3480
  *
3481
  * Inspired by array_shift
3482
  *
3483
- * @param String $string
3484
- * @param optional Integer $index
3485
- * @return String
3486
  * @access private
3487
  */
3488
  function _string_shift(&$string, $index = 1)
@@ -3499,14 +4167,14 @@ class Net_SSH2
3499
  * named constants from it, using the value as the name of the constant and the index as the value of the constant.
3500
  * If any of the constants that would be defined already exists, none of the constants will be defined.
3501
  *
3502
- * @param Array $array
3503
  * @access private
3504
  */
3505
  function _define_array()
3506
  {
3507
  $args = func_get_args();
3508
  foreach ($args as $arg) {
3509
- foreach ($arg as $key=>$value) {
3510
  if (!defined($value)) {
3511
  define($value, $key);
3512
  } else {
@@ -3522,7 +4190,7 @@ class Net_SSH2
3522
  * Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
3523
  *
3524
  * @access public
3525
- * @return String or Array
3526
  */
3527
  function getLog()
3528
  {
@@ -3533,10 +4201,9 @@ class Net_SSH2
3533
  switch (NET_SSH2_LOGGING) {
3534
  case NET_SSH2_LOG_SIMPLE:
3535
  return $this->message_number_log;
3536
- break;
3537
  case NET_SSH2_LOG_COMPLEX:
3538
- return $this->_format_log($this->message_log, $this->message_number_log);
3539
- break;
3540
  default:
3541
  return false;
3542
  }
@@ -3545,10 +4212,10 @@ class Net_SSH2
3545
  /**
3546
  * Formats a log for printing
3547
  *
3548
- * @param Array $message_log
3549
- * @param Array $message_number_log
3550
  * @access private
3551
- * @return String
3552
  */
3553
  function _format_log($message_log, $message_number_log)
3554
  {
@@ -3581,9 +4248,9 @@ class Net_SSH2
3581
  *
3582
  * For use with preg_replace_callback()
3583
  *
3584
- * @param Array $matches
3585
  * @access private
3586
- * @return String
3587
  */
3588
  function _format_log_helper($matches)
3589
  {
@@ -3606,10 +4273,29 @@ class Net_SSH2
3606
  }
3607
  }
3608
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3609
  /**
3610
  * Returns all errors
3611
  *
3612
- * @return String
3613
  * @access public
3614
  */
3615
  function getErrors()
@@ -3620,18 +4306,22 @@ class Net_SSH2
3620
  /**
3621
  * Returns the last error
3622
  *
3623
- * @return String
3624
  * @access public
3625
  */
3626
  function getLastError()
3627
  {
3628
- return $this->errors[count($this->errors) - 1];
 
 
 
 
3629
  }
3630
 
3631
  /**
3632
  * Return the server identification.
3633
  *
3634
- * @return String
3635
  * @access public
3636
  */
3637
  function getServerIdentification()
@@ -3644,7 +4334,7 @@ class Net_SSH2
3644
  /**
3645
  * Return a list of the key exchange algorithms the server supports.
3646
  *
3647
- * @return Array
3648
  * @access public
3649
  */
3650
  function getKexAlgorithms()
@@ -3657,7 +4347,7 @@ class Net_SSH2
3657
  /**
3658
  * Return a list of the host key (public key) algorithms the server supports.
3659
  *
3660
- * @return Array
3661
  * @access public
3662
  */
3663
  function getServerHostKeyAlgorithms()
@@ -3670,7 +4360,7 @@ class Net_SSH2
3670
  /**
3671
  * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
3672
  *
3673
- * @return Array
3674
  * @access public
3675
  */
3676
  function getEncryptionAlgorithmsClient2Server()
@@ -3683,7 +4373,7 @@ class Net_SSH2
3683
  /**
3684
  * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
3685
  *
3686
- * @return Array
3687
  * @access public
3688
  */
3689
  function getEncryptionAlgorithmsServer2Client()
@@ -3696,7 +4386,7 @@ class Net_SSH2
3696
  /**
3697
  * Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
3698
  *
3699
- * @return Array
3700
  * @access public
3701
  */
3702
  function getMACAlgorithmsClient2Server()
@@ -3709,7 +4399,7 @@ class Net_SSH2
3709
  /**
3710
  * Return a list of the MAC algorithms the server supports, when sending stuff to the client.
3711
  *
3712
- * @return Array
3713
  * @access public
3714
  */
3715
  function getMACAlgorithmsServer2Client()
@@ -3722,7 +4412,7 @@ class Net_SSH2
3722
  /**
3723
  * Return a list of the compression algorithms the server supports, when receiving stuff from the client.
3724
  *
3725
- * @return Array
3726
  * @access public
3727
  */
3728
  function getCompressionAlgorithmsClient2Server()
@@ -3735,7 +4425,7 @@ class Net_SSH2
3735
  /**
3736
  * Return a list of the compression algorithms the server supports, when sending stuff to the client.
3737
  *
3738
- * @return Array
3739
  * @access public
3740
  */
3741
  function getCompressionAlgorithmsServer2Client()
@@ -3748,7 +4438,7 @@ class Net_SSH2
3748
  /**
3749
  * Return a list of the languages the server supports, when sending stuff to the client.
3750
  *
3751
- * @return Array
3752
  * @access public
3753
  */
3754
  function getLanguagesServer2Client()
@@ -3761,7 +4451,7 @@ class Net_SSH2
3761
  /**
3762
  * Return a list of the languages the server supports, when receiving stuff from the client.
3763
  *
3764
- * @return Array
3765
  * @access public
3766
  */
3767
  function getLanguagesClient2Server()
@@ -3777,7 +4467,7 @@ class Net_SSH2
3777
  * Quoting from the RFC, "in some jurisdictions, sending a warning message before
3778
  * authentication may be relevant for getting legal protection."
3779
  *
3780
- * @return String
3781
  * @access public
3782
  */
3783
  function getBannerMessage()
@@ -3791,7 +4481,7 @@ class Net_SSH2
3791
  * Caching this the first time you connect to a server and checking the result on subsequent connections
3792
  * is recommended. Returns false if the server signature is not signed correctly with the public host key.
3793
  *
3794
- * @return Mixed
3795
  * @access public
3796
  */
3797
  function getServerPublicHostKey()
@@ -3805,6 +4495,9 @@ class Net_SSH2
3805
  $signature = $this->signature;
3806
  $server_public_host_key = $this->server_public_host_key;
3807
 
 
 
 
3808
  extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4)));
3809
  $this->_string_shift($server_public_host_key, $length);
3810
 
@@ -3820,15 +4513,27 @@ class Net_SSH2
3820
  case 'ssh-dss':
3821
  $zero = new Math_BigInteger();
3822
 
 
 
 
3823
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3824
  $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
3825
 
 
 
 
3826
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3827
  $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
3828
 
 
 
 
3829
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3830
  $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
3831
 
 
 
 
3832
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3833
  $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
3834
 
@@ -3875,15 +4580,24 @@ class Net_SSH2
3875
 
3876
  break;
3877
  case 'ssh-rsa':
 
 
 
3878
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3879
  $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
3880
 
 
 
 
3881
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
3882
  $rawN = $this->_string_shift($server_public_host_key, $temp['length']);
3883
  $n = new Math_BigInteger($rawN, -256);
3884
  $nLength = strlen(ltrim($rawN, "\0"));
3885
 
3886
  /*
 
 
 
3887
  $temp = unpack('Nlength', $this->_string_shift($signature, 4));
3888
  $signature = $this->_string_shift($signature, $temp['length']);
3889
 
@@ -3900,6 +4614,9 @@ class Net_SSH2
3900
  }
3901
  */
3902
 
 
 
 
3903
  $temp = unpack('Nlength', $this->_string_shift($signature, 4));
3904
  $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
3905
 
@@ -3936,7 +4653,7 @@ class Net_SSH2
3936
  /**
3937
  * Returns the exit status of an SSH command or false.
3938
  *
3939
- * @return Integer or false
3940
  * @access public
3941
  */
3942
  function getExitStatus()
@@ -3950,7 +4667,7 @@ class Net_SSH2
3950
  /**
3951
  * Returns the number of columns for the terminal window size.
3952
  *
3953
- * @return Integer
3954
  * @access public
3955
  */
3956
  function getWindowColumns()
@@ -3961,7 +4678,7 @@ class Net_SSH2
3961
  /**
3962
  * Returns the number of rows for the terminal window size.
3963
  *
3964
- * @return Integer
3965
  * @access public
3966
  */
3967
  function getWindowRows()
@@ -3972,7 +4689,7 @@ class Net_SSH2
3972
  /**
3973
  * Sets the number of columns for the terminal window size.
3974
  *
3975
- * @param Integer $value
3976
  * @access public
3977
  */
3978
  function setWindowColumns($value)
@@ -3983,7 +4700,7 @@ class Net_SSH2
3983
  /**
3984
  * Sets the number of rows for the terminal window size.
3985
  *
3986
- * @param Integer $value
3987
  * @access public
3988
  */
3989
  function setWindowRows($value)
@@ -3994,8 +4711,8 @@ class Net_SSH2
3994
  /**
3995
  * Sets the number of columns and rows for the terminal window size.
3996
  *
3997
- * @param Integer $columns
3998
- * @param Integer $rows
3999
  * @access public
4000
  */
4001
  function setWindowSize($columns = 80, $rows = 24)
69
  /**#@+
70
  * Execution Bitmap Masks
71
  *
72
+ * @see self::bitmap
73
  * @access private
74
  */
75
  define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
92
  * open request, and 'sender channel' is the channel number allocated by
93
  * the other side.
94
  *
95
+ * @see self::_send_channel_packet()
96
+ * @see self::_get_channel_packet()
97
  * @access private
98
  */
99
+ define('NET_SSH2_CHANNEL_EXEC', 1); // PuTTy uses 0x100
100
+ define('NET_SSH2_CHANNEL_SHELL', 2);
101
+ define('NET_SSH2_CHANNEL_SUBSYSTEM', 3);
102
+ define('NET_SSH2_CHANNEL_AGENT_FORWARD', 4);
103
  /**#@-*/
104
 
105
  /**#@+
106
  * @access public
107
+ * @see self::getLog()
108
  */
109
  /**
110
  * Returns the message numbers
122
  * Dumps the content real-time to a file
123
  */
124
  define('NET_SSH2_LOG_REALTIME_FILE', 4);
125
+ /**
126
+ * Make sure that the log never gets larger than this
127
+ */
128
+ define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
129
  /**#@-*/
130
 
131
  /**#@+
132
  * @access public
133
+ * @see self::read()
134
  */
135
  /**
136
  * Returns when a string matching $expect exactly is found
141
  */
142
  define('NET_SSH2_READ_REGEX', 2);
143
  /**
144
+ * Returns when a string matching the regular expression $expect is found
145
  */
146
+ define('NET_SSH2_READ_NEXT', 3);
147
  /**#@-*/
148
 
149
  /**
158
  /**
159
  * The SSH identifier
160
  *
161
+ * @var string
162
  * @access private
163
  */
164
  var $identifier;
166
  /**
167
  * The Socket Object
168
  *
169
+ * @var object
170
  * @access private
171
  */
172
  var $fsock;
177
  * The bits that are set represent functions that have been called already. This is used to determine
178
  * if a requisite function has been successfully executed. If not, an error should be thrown.
179
  *
180
+ * @var int
181
  * @access private
182
  */
183
  var $bitmap = 0;
185
  /**
186
  * Error information
187
  *
188
+ * @see self::getErrors()
189
+ * @see self::getLastError()
190
+ * @var string
191
  * @access private
192
  */
193
  var $errors = array();
195
  /**
196
  * Server Identifier
197
  *
198
+ * @see self::getServerIdentification()
199
+ * @var array|false
200
  * @access private
201
  */
202
  var $server_identifier = false;
204
  /**
205
  * Key Exchange Algorithms
206
  *
207
+ * @see self::getKexAlgorithims()
208
+ * @var array|false
209
  * @access private
210
  */
211
  var $kex_algorithms = false;
212
 
213
+ /**
214
+ * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
215
+ *
216
+ * @see self::_key_exchange()
217
+ * @var int
218
+ * @access private
219
+ */
220
+ var $kex_dh_group_size_min = 1536;
221
+
222
+ /**
223
+ * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
224
+ *
225
+ * @see self::_key_exchange()
226
+ * @var int
227
+ * @access private
228
+ */
229
+ var $kex_dh_group_size_preferred = 2048;
230
+
231
+ /**
232
+ * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
233
+ *
234
+ * @see self::_key_exchange()
235
+ * @var int
236
+ * @access private
237
+ */
238
+ var $kex_dh_group_size_max = 4096;
239
+
240
  /**
241
  * Server Host Key Algorithms
242
  *
243
+ * @see self::getServerHostKeyAlgorithms()
244
+ * @var array|false
245
  * @access private
246
  */
247
  var $server_host_key_algorithms = false;
249
  /**
250
  * Encryption Algorithms: Client to Server
251
  *
252
+ * @see self::getEncryptionAlgorithmsClient2Server()
253
+ * @var array|false
254
  * @access private
255
  */
256
  var $encryption_algorithms_client_to_server = false;
258
  /**
259
  * Encryption Algorithms: Server to Client
260
  *
261
+ * @see self::getEncryptionAlgorithmsServer2Client()
262
+ * @var array|false
263
  * @access private
264
  */
265
  var $encryption_algorithms_server_to_client = false;
267
  /**
268
  * MAC Algorithms: Client to Server
269
  *
270
+ * @see self::getMACAlgorithmsClient2Server()
271
+ * @var array|false
272
  * @access private
273
  */
274
  var $mac_algorithms_client_to_server = false;
276
  /**
277
  * MAC Algorithms: Server to Client
278
  *
279
+ * @see self::getMACAlgorithmsServer2Client()
280
+ * @var array|false
281
  * @access private
282
  */
283
  var $mac_algorithms_server_to_client = false;
285
  /**
286
  * Compression Algorithms: Client to Server
287
  *
288
+ * @see self::getCompressionAlgorithmsClient2Server()
289
+ * @var array|false
290
  * @access private
291
  */
292
  var $compression_algorithms_client_to_server = false;
294
  /**
295
  * Compression Algorithms: Server to Client
296
  *
297
+ * @see self::getCompressionAlgorithmsServer2Client()
298
+ * @var array|false
299
  * @access private
300
  */
301
  var $compression_algorithms_server_to_client = false;
303
  /**
304
  * Languages: Server to Client
305
  *
306
+ * @see self::getLanguagesServer2Client()
307
+ * @var array|false
308
  * @access private
309
  */
310
  var $languages_server_to_client = false;
312
  /**
313
  * Languages: Client to Server
314
  *
315
+ * @see self::getLanguagesClient2Server()
316
+ * @var array|false
317
  * @access private
318
  */
319
  var $languages_client_to_server = false;
328
  *
329
  * -- http://tools.ietf.org/html/rfc4253#section-6
330
  *
331
+ * @see self::Net_SSH2()
332
+ * @see self::_send_binary_packet()
333
+ * @var int
334
  * @access private
335
  */
336
  var $encrypt_block_size = 8;
338
  /**
339
  * Block Size for Client to Server Encryption
340
  *
341
+ * @see self::Net_SSH2()
342
+ * @see self::_get_binary_packet()
343
+ * @var int
344
  * @access private
345
  */
346
  var $decrypt_block_size = 8;
348
  /**
349
  * Server to Client Encryption Object
350
  *
351
+ * @see self::_get_binary_packet()
352
+ * @var object
353
  * @access private
354
  */
355
  var $decrypt = false;
357
  /**
358
  * Client to Server Encryption Object
359
  *
360
+ * @see self::_send_binary_packet()
361
+ * @var object
362
  * @access private
363
  */
364
  var $encrypt = false;
366
  /**
367
  * Client to Server HMAC Object
368
  *
369
+ * @see self::_send_binary_packet()
370
+ * @var object
371
  * @access private
372
  */
373
  var $hmac_create = false;
375
  /**
376
  * Server to Client HMAC Object
377
  *
378
+ * @see self::_get_binary_packet()
379
+ * @var object
380
  * @access private
381
  */
382
  var $hmac_check = false;
388
  * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
389
  * append it.
390
  *
391
+ * @see self::_get_binary_packet()
392
+ * @var int
393
  * @access private
394
  */
395
  var $hmac_size = false;
397
  /**
398
  * Server Public Host Key
399
  *
400
+ * @see self::getServerPublicHostKey()
401
+ * @var string
402
  * @access private
403
  */
404
  var $server_public_host_key;
405
 
406
  /**
407
+ * Session identifier
408
  *
409
  * "The exchange hash H from the first key exchange is additionally
410
  * used as the session identifier, which is a unique identifier for
412
  *
413
  * -- http://tools.ietf.org/html/rfc4253#section-7.2
414
  *
415
+ * @see self::_key_exchange()
416
+ * @var string
417
  * @access private
418
  */
419
  var $session_id = false;
423
  *
424
  * The current exchange hash
425
  *
426
+ * @see self::_key_exchange()
427
+ * @var string
428
  * @access private
429
  */
430
  var $exchange_hash = false;
432
  /**
433
  * Message Numbers
434
  *
435
+ * @see self::Net_SSH2()
436
+ * @var array
437
  * @access private
438
  */
439
  var $message_numbers = array();
441
  /**
442
  * Disconnection Message 'reason codes' defined in RFC4253
443
  *
444
+ * @see self::Net_SSH2()
445
+ * @var array
446
  * @access private
447
  */
448
  var $disconnect_reasons = array();
450
  /**
451
  * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
452
  *
453
+ * @see self::Net_SSH2()
454
+ * @var array
455
  * @access private
456
  */
457
  var $channel_open_failure_reasons = array();
460
  * Terminal Modes
461
  *
462
  * @link http://tools.ietf.org/html/rfc4254#section-8
463
+ * @see self::Net_SSH2()
464
+ * @var array
465
  * @access private
466
  */
467
  var $terminal_modes = array();
470
  * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
471
  *
472
  * @link http://tools.ietf.org/html/rfc4254#section-5.2
473
+ * @see self::Net_SSH2()
474
+ * @var array
475
  * @access private
476
  */
477
  var $channel_extended_data_type_codes = array();
481
  *
482
  * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
483
  *
484
+ * @see self::_send_binary_packet()
485
+ * @var int
486
  * @access private
487
  */
488
  var $send_seq_no = 0;
492
  *
493
  * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
494
  *
495
+ * @see self::_get_binary_packet()
496
+ * @var int
497
  * @access private
498
  */
499
  var $get_seq_no = 0;
503
  *
504
  * Maps client channels to server channels
505
  *
506
+ * @see self::_get_channel_packet()
507
+ * @see self::exec()
508
+ * @var array
509
  * @access private
510
  */
511
  var $server_channels = array();
516
  * If a client requests a packet from one channel but receives two packets from another those packets should
517
  * be placed in a buffer
518
  *
519
+ * @see self::_get_channel_packet()
520
+ * @see self::exec()
521
+ * @var array
522
  * @access private
523
  */
524
  var $channel_buffers = array();
528
  *
529
  * Contains the type of the last sent message
530
  *
531
+ * @see self::_get_channel_packet()
532
+ * @var array
533
  * @access private
534
  */
535
  var $channel_status = array();
539
  *
540
  * Maximum packet size indexed by channel
541
  *
542
+ * @see self::_send_channel_packet()
543
+ * @var array
544
  * @access private
545
  */
546
  var $packet_size_client_to_server = array();
548
  /**
549
  * Message Number Log
550
  *
551
+ * @see self::getLog()
552
+ * @var array
553
  * @access private
554
  */
555
  var $message_number_log = array();
557
  /**
558
  * Message Log
559
  *
560
+ * @see self::getLog()
561
+ * @var array
562
  * @access private
563
  */
564
  var $message_log = array();
568
  *
569
  * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
570
  *
571
+ * @var int
572
+ * @see self::_send_channel_packet()
573
+ * @see self::exec()
574
  * @access private
575
  */
576
  var $window_size = 0x7FFFFFFF;
580
  *
581
  * Window size indexed by channel
582
  *
583
+ * @see self::_send_channel_packet()
584
+ * @var array
585
  * @access private
586
  */
587
  var $window_size_server_to_client = array();
591
  *
592
  * Window size indexed by channel
593
  *
594
+ * @see self::_get_channel_packet()
595
+ * @var array
596
  * @access private
597
  */
598
  var $window_size_client_to_server = array();
602
  *
603
  * Verified against $this->session_id
604
  *
605
+ * @see self::getServerPublicHostKey()
606
+ * @var string
607
  * @access private
608
  */
609
  var $signature = '';
613
  *
614
  * ssh-rsa or ssh-dss.
615
  *
616
+ * @see self::getServerPublicHostKey()
617
+ * @var string
618
  * @access private
619
  */
620
  var $signature_format = '';
622
  /**
623
  * Interactive Buffer
624
  *
625
+ * @see self::read()
626
+ * @var array
627
  * @access private
628
  */
629
  var $interactiveBuffer = '';
633
  *
634
  * Should never exceed NET_SSH2_LOG_MAX_SIZE
635
  *
636
+ * @see self::_send_binary_packet()
637
+ * @see self::_get_binary_packet()
638
+ * @var int
639
  * @access private
640
  */
641
  var $log_size;
643
  /**
644
  * Timeout
645
  *
646
+ * @see self::setTimeout()
647
  * @access private
648
  */
649
  var $timeout;
651
  /**
652
  * Current Timeout
653
  *
654
+ * @see self::_get_channel_packet()
655
  * @access private
656
  */
657
  var $curTimeout;
659
  /**
660
  * Real-time log file pointer
661
  *
662
+ * @see self::_append_log()
663
+ * @var resource
664
  * @access private
665
  */
666
  var $realtime_log_file;
668
  /**
669
  * Real-time log file size
670
  *
671
+ * @see self::_append_log()
672
+ * @var int
673
  * @access private
674
  */
675
  var $realtime_log_size;
677
  /**
678
  * Has the signature been validated?
679
  *
680
+ * @see self::getServerPublicHostKey()
681
+ * @var bool
682
  * @access private
683
  */
684
  var $signature_validated = false;
686
  /**
687
  * Real-time log file wrap boolean
688
  *
689
+ * @see self::_append_log()
690
  * @access private
691
  */
692
  var $realtime_log_wrap;
694
  /**
695
  * Flag to suppress stderr from output
696
  *
697
+ * @see self::enableQuietMode()
698
  * @access private
699
  */
700
  var $quiet_mode = false;
702
  /**
703
  * Time of first network activity
704
  *
705
+ * @var int
706
  * @access private
707
  */
708
  var $last_packet;
710
  /**
711
  * Exit status returned from ssh if any
712
  *
713
+ * @var int
714
  * @access private
715
  */
716
  var $exit_status;
718
  /**
719
  * Flag to request a PTY when using exec()
720
  *
721
+ * @var bool
722
+ * @see self::enablePTY()
723
  * @access private
724
  */
725
  var $request_pty = false;
727
  /**
728
  * Flag set while exec() is running when using enablePTY()
729
  *
730
+ * @var bool
731
  * @access private
732
  */
733
  var $in_request_pty_exec = false;
735
  /**
736
  * Flag set after startSubsystem() is called
737
  *
738
+ * @var bool
739
  * @access private
740
  */
741
  var $in_subsystem;
743
  /**
744
  * Contents of stdError
745
  *
746
+ * @var string
747
  * @access private
748
  */
749
  var $stdErrorLog;
751
  /**
752
  * The Last Interactive Response
753
  *
754
+ * @see self::_keyboard_interactive_process()
755
+ * @var string
756
  * @access private
757
  */
758
  var $last_interactive_response = '';
760
  /**
761
  * Keyboard Interactive Request / Responses
762
  *
763
+ * @see self::_keyboard_interactive_process()
764
+ * @var array
765
  * @access private
766
  */
767
  var $keyboard_requests_responses = array();
772
  * Quoting from the RFC, "in some jurisdictions, sending a warning message before
773
  * authentication may be relevant for getting legal protection."
774
  *
775
+ * @see self::_filter()
776
+ * @see self::getBannerMessage()
777
+ * @var string
778
  * @access private
779
  */
780
  var $banner_message = '';
782
  /**
783
  * Did read() timeout or return normally?
784
  *
785
+ * @see self::isTimeout()
786
+ * @var bool
787
  * @access private
788
  */
789
  var $is_timeout = false;
791
  /**
792
  * Log Boundary
793
  *
794
+ * @see self::_format_log()
795
+ * @var string
796
  * @access private
797
  */
798
  var $log_boundary = ':';
800
  /**
801
  * Log Long Width
802
  *
803
+ * @see self::_format_log()
804
+ * @var int
805
  * @access private
806
  */
807
  var $log_long_width = 65;
809
  /**
810
  * Log Short Width
811
  *
812
+ * @see self::_format_log()
813
+ * @var int
814
  * @access private
815
  */
816
  var $log_short_width = 16;
818
  /**
819
  * Hostname
820
  *
821
+ * @see self::Net_SSH2()
822
+ * @see self::_connect()
823
+ * @var string
824
  * @access private
825
  */
826
  var $host;
828
  /**
829
  * Port Number
830
  *
831
+ * @see self::Net_SSH2()
832
+ * @see self::_connect()
833
+ * @var int
834
  * @access private
835
  */
836
  var $port;
838
  /**
839
  * Number of columns for terminal window size
840
  *
841
+ * @see self::getWindowColumns()
842
+ * @see self::setWindowColumns()
843
+ * @see self::setWindowSize()
844
+ * @var int
845
  * @access private
846
  */
847
  var $windowColumns = 80;
849
  /**
850
  * Number of columns for terminal window size
851
  *
852
+ * @see self::getWindowRows()
853
+ * @see self::setWindowRows()
854
+ * @see self::setWindowSize()
855
+ * @var int
856
  * @access private
857
  */
858
  var $windowRows = 24;
860
  /**
861
  * Crypto Engine
862
  *
863
+ * @see self::setCryptoEngine()
864
+ * @see self::_key_exchange()
865
+ * @var int
866
  * @access private
867
  */
868
  var $crypto_engine = false;
875
  */
876
  var $agent;
877
 
878
+ /**
879
+ * Send the identification string first?
880
+ *
881
+ * @var bool
882
+ * @access private
883
+ */
884
+ var $send_id_string_first = true;
885
+
886
+ /**
887
+ * Send the key exchange initiation packet first?
888
+ *
889
+ * @var bool
890
+ * @access private
891
+ */
892
+ var $send_kex_first = true;
893
+
894
+ /**
895
+ * Some versions of OpenSSH incorrectly calculate the key size
896
+ *
897
+ * @var bool
898
+ * @access private
899
+ */
900
+ var $bad_key_size_fix = false;
901
+
902
+ /**
903
+ * The selected decryption algorithm
904
+ *
905
+ * @var string
906
+ * @access private
907
+ */
908
+ var $decrypt_algorithm = '';
909
+
910
+ /**
911
+ * Should we try to re-connect to re-establish keys?
912
+ *
913
+ * @var bool
914
+ * @access private
915
+ */
916
+ var $retry_connect = false;
917
+
918
+ /**
919
+ * Binary Packet Buffer
920
+ *
921
+ * @var string|false
922
+ * @access private
923
+ */
924
+ var $binary_packet_buffer = false;
925
+
926
  /**
927
  * Default Constructor.
928
  *
929
+ * $host can either be a string, representing the host, or a stream resource.
930
+ *
931
+ * @param mixed $host
932
+ * @param int $port
933
+ * @param int $timeout
934
+ * @see self::login()
935
  * @return Net_SSH2
936
  * @access public
937
  */
938
+ function __construct($host, $port = 22, $timeout = 10)
939
  {
940
  // Include Math_BigInteger
941
  // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
1023
  array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'),
1024
  array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'),
1025
  array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
1026
+ 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'),
1027
+ // RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
1028
+ array(30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD',
1029
+ 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
1030
+ 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
1031
+ 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
1032
+ 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST')
1033
  );
1034
 
1035
+ if (is_resource($host)) {
1036
+ $this->fsock = $host;
1037
+ return;
1038
+ }
1039
+
1040
+ if (is_string($host)) {
1041
+ $this->host = $host;
1042
+ $this->port = $port;
1043
+ $this->timeout = $timeout;
1044
+ }
1045
+ }
1046
+
1047
+ /**
1048
+ * PHP4 compatible Default Constructor.
1049
+ *
1050
+ * @see self::__construct()
1051
+ * @param mixed $host
1052
+ * @param int $port
1053
+ * @param int $timeout
1054
+ * @access public
1055
+ */
1056
+ function Net_SSH2($host, $port = 22, $timeout = 10)
1057
+ {
1058
+ $this->__construct($host, $port, $timeout);
1059
  }
1060
 
1061
  /**
1064
  * Possible $engine values:
1065
  * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
1066
  *
1067
+ * @param int $engine
1068
+ * @access public
1069
  */
1070
  function setCryptoEngine($engine)
1071
  {
1072
  $this->crypto_engine = $engine;
1073
  }
1074
 
1075
+ /**
1076
+ * Send Identification String First
1077
+ *
1078
+ * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
1079
+ * both sides MUST send an identification string". It does not say which side sends it first. In
1080
+ * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
1081
+ *
1082
+ * @access public
1083
+ */
1084
+ function sendIdentificationStringFirst()
1085
+ {
1086
+ $this->send_id_string_first = true;
1087
+ }
1088
+
1089
+ /**
1090
+ * Send Identification String Last
1091
+ *
1092
+ * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
1093
+ * both sides MUST send an identification string". It does not say which side sends it first. In
1094
+ * theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
1095
+ *
1096
+ * @access public
1097
+ */
1098
+ function sendIdentificationStringLast()
1099
+ {
1100
+ $this->send_id_string_first = false;
1101
+ }
1102
+
1103
+ /**
1104
+ * Send SSH_MSG_KEXINIT First
1105
+ *
1106
+ * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
1107
+ * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
1108
+ * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
1109
+ *
1110
+ * @access public
1111
+ */
1112
+ function sendKEXINITFirst()
1113
+ {
1114
+ $this->send_kex_first = true;
1115
+ }
1116
+
1117
+ /**
1118
+ * Send SSH_MSG_KEXINIT Last
1119
+ *
1120
+ * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
1121
+ * sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
1122
+ * it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
1123
+ *
1124
+ * @access public
1125
+ */
1126
+ function sendKEXINITLast()
1127
+ {
1128
+ $this->send_kex_first = false;
1129
+ }
1130
+
1131
  /**
1132
  * Connect to an SSHv2 server
1133
  *
1134
+ * @return bool
1135
  * @access private
1136
  */
1137
  function _connect()
1144
 
1145
  $this->curTimeout = $this->timeout;
1146
 
 
 
1147
  $this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
1148
 
1149
+ if (!is_resource($this->fsock)) {
1150
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
1151
+ // with stream_select a timeout of 0 means that no timeout takes place;
1152
+ // with fsockopen a timeout of 0 means that you instantly timeout
1153
+ // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0
1154
+ $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout);
1155
+ if (!$this->fsock) {
1156
+ $host = $this->host . ':' . $this->port;
1157
+ user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
1158
+ return false;
1159
+ }
1160
+ $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
1161
+
1162
+ $this->curTimeout-= $elapsed;
1163
+
1164
+ if ($this->curTimeout <= 0) {
1165
+ $this->is_timeout = true;
1166
+ return false;
1167
+ }
1168
  }
 
1169
 
1170
+ $this->identifier = $this->_generate_identifier();
1171
 
1172
+ if ($this->send_id_string_first) {
1173
+ fputs($this->fsock, $this->identifier . "\r\n");
 
1174
  }
1175
 
1176
  /* According to the SSH2 specs,
1216
  return false;
1217
  }
1218
 
 
 
1219
  if (defined('NET_SSH2_LOGGING')) {
1220
  $this->_append_log('<-', $extra . $temp);
1221
  $this->_append_log('->', $this->identifier . "\r\n");
1226
  $this->errors[] = utf8_decode($extra);
1227
  }
1228
 
1229
+ if (version_compare($matches[1], '1.99', '<')) {
1230
  user_error("Cannot connect to SSH $matches[1] servers");
1231
  return false;
1232
  }
1233
 
1234
+ if (!$this->send_id_string_first) {
1235
+ fputs($this->fsock, $this->identifier . "\r\n");
 
 
 
 
1236
  }
1237
 
1238
+ if (!$this->send_kex_first) {
1239
+ $response = $this->_get_binary_packet();
1240
+ if ($response === false) {
1241
+ user_error('Connection closed by server');
1242
+ return false;
1243
+ }
1244
+
1245
+ if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
1246
+ user_error('Expected SSH_MSG_KEXINIT');
1247
+ return false;
1248
+ }
1249
+
1250
+ if (!$this->_key_exchange($response)) {
1251
+ return false;
1252
+ }
1253
  }
1254
 
1255
+ if ($this->send_kex_first && !$this->_key_exchange()) {
1256
  return false;
1257
  }
1258
 
1267
  * You should overwrite this method in your own class if you want to use another identifier
1268
  *
1269
  * @access protected
1270
+ * @return string
1271
  */
1272
  function _generate_identifier()
1273
  {
1274
+ $identifier = 'SSH-2.0-phpseclib_1.0';
1275
 
1276
  $ext = array();
1277
  if (extension_loaded('openssl')) {
1296
  /**
1297
  * Key Exchange
1298
  *
1299
+ * @param string $kexinit_payload_server optional
1300
  * @access private
1301
  */
1302
+ function _key_exchange($kexinit_payload_server = false)
1303
  {
1304
  static $kex_algorithms = array(
1305
  'diffie-hellman-group1-sha1', // REQUIRED
1306
+ 'diffie-hellman-group14-sha1', // REQUIRED
1307
+ 'diffie-hellman-group-exchange-sha1', // RFC 4419
1308
+ 'diffie-hellman-group-exchange-sha256', // RFC 4419
1309
  );
1310
 
1311
  static $server_host_key_algorithms = array(
1410
  );
1411
 
1412
  // some SSH servers have buggy implementations of some of the above algorithms
1413
+ switch (true) {
1414
+ case $this->server_identifier == 'SSH-2.0-SSHD':
1415
+ case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
1416
  $mac_algorithms = array_values(array_diff(
1417
  $mac_algorithms,
1418
  array('hmac-sha1-96', 'hmac-md5-96')
1433
 
1434
  $client_cookie = crypt_random_string(16);
1435
 
1436
+ $kexinit_payload_client = pack(
1437
+ 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
1438
+ NET_SSH2_MSG_KEXINIT,
1439
+ $client_cookie,
1440
+ strlen($str_kex_algorithms),
1441
+ $str_kex_algorithms,
1442
+ strlen($str_server_host_key_algorithms),
1443
+ $str_server_host_key_algorithms,
1444
+ strlen($encryption_algorithms_client_to_server),
1445
+ $encryption_algorithms_client_to_server,
1446
+ strlen($encryption_algorithms_server_to_client),
1447
+ $encryption_algorithms_server_to_client,
1448
+ strlen($mac_algorithms_client_to_server),
1449
+ $mac_algorithms_client_to_server,
1450
+ strlen($mac_algorithms_server_to_client),
1451
+ $mac_algorithms_server_to_client,
1452
+ strlen($compression_algorithms_client_to_server),
1453
+ $compression_algorithms_client_to_server,
1454
+ strlen($compression_algorithms_server_to_client),
1455
+ $compression_algorithms_server_to_client,
1456
+ 0,
1457
+ '',
1458
+ 0,
1459
+ '',
1460
+ 0,
1461
+ 0
1462
+ );
1463
+
1464
+ if ($this->send_kex_first) {
1465
+ if (!$this->_send_binary_packet($kexinit_payload_client)) {
1466
+ return false;
1467
+ }
1468
+
1469
+ $kexinit_payload_server = $this->_get_binary_packet();
1470
+ if ($kexinit_payload_server === false) {
1471
+ user_error('Connection closed by server');
1472
+ return false;
1473
+ }
1474
+
1475
+ if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
1476
+ user_error('Expected SSH_MSG_KEXINIT');
1477
+ return false;
1478
+ }
1479
+ }
1480
+
1481
  $response = $kexinit_payload_server;
1482
  $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
1483
  $server_cookie = $this->_string_shift($response, 16);
1484
 
1485
+ if (strlen($response) < 4) {
1486
+ return false;
1487
+ }
1488
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1489
  $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
1490
 
1491
+ if (strlen($response) < 4) {
1492
+ return false;
1493
+ }
1494
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1495
  $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
1496
 
1497
+ if (strlen($response) < 4) {
1498
+ return false;
1499
+ }
1500
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1501
  $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1502
 
1503
+ if (strlen($response) < 4) {
1504
+ return false;
1505
+ }
1506
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1507
  $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1508
 
1509
+ if (strlen($response) < 4) {
1510
+ return false;
1511
+ }
1512
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1513
  $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1514
 
1515
+ if (strlen($response) < 4) {
1516
+ return false;
1517
+ }
1518
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1519
  $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1520
 
1521
+ if (strlen($response) < 4) {
1522
+ return false;
1523
+ }
1524
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1525
  $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1526
 
1527
+ if (strlen($response) < 4) {
1528
+ return false;
1529
+ }
1530
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1531
  $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1532
 
1533
+ if (strlen($response) < 4) {
1534
+ return false;
1535
+ }
1536
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1537
  $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
1538
 
1539
+ if (strlen($response) < 4) {
1540
+ return false;
1541
+ }
1542
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1543
  $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
1544
 
1545
+ if (!strlen($response)) {
1546
+ return false;
1547
+ }
1548
  extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
1549
  $first_kex_packet_follows = $first_kex_packet_follows != 0;
1550
 
1551
+ if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) {
 
 
 
 
 
 
 
 
 
 
 
1552
  return false;
1553
  }
 
1554
 
1555
  // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
 
 
 
 
 
 
1556
  // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
1557
  // diffie-hellman key exchange as fast as possible
1558
+ $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
1559
+ $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
1560
+ if ($decryptKeyLength === null) {
1561
+ user_error('No compatible server to client encryption algorithms found');
1562
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1563
  }
1564
 
1565
+ $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
1566
+ $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
1567
+ if ($encryptKeyLength === null) {
1568
  user_error('No compatible client to server encryption algorithms found');
1569
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1570
  }
1571
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1572
  $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
1573
 
1574
  // through diffie-hellman key exchange a symmetric key is obtained
1575
+ $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
1576
+ if ($kex_algorithm === false) {
1577
  user_error('No compatible key exchange algorithms found');
1578
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1579
  }
1580
+ if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
1581
+ $dh_group_sizes_packed = pack(
1582
+ 'NNN',
1583
+ $this->kex_dh_group_size_min,
1584
+ $this->kex_dh_group_size_preferred,
1585
+ $this->kex_dh_group_size_max
1586
+ );
1587
+ $packet = pack(
1588
+ 'Ca*',
1589
+ NET_SSH2_MSG_KEXDH_GEX_REQUEST,
1590
+ $dh_group_sizes_packed
1591
+ );
1592
+ if (!$this->_send_binary_packet($packet)) {
1593
+ return false;
1594
+ }
1595
 
1596
+ $response = $this->_get_binary_packet();
1597
+ if ($response === false) {
1598
+ user_error('Connection closed by server');
1599
+ return false;
1600
+ }
1601
+ if (!strlen($response)) {
1602
+ return false;
1603
+ }
1604
+ extract(unpack('Ctype', $this->_string_shift($response, 1)));
1605
+ if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
1606
+ user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
1607
+ return false;
1608
+ }
1609
+
1610
+ if (strlen($response) < 4) {
1611
+ return false;
1612
+ }
1613
+ extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
1614
+ $primeBytes = $this->_string_shift($response, $primeLength);
1615
+ $prime = new Math_BigInteger($primeBytes, -256);
1616
+
1617
+ if (strlen($response) < 4) {
1618
+ return false;
1619
+ }
1620
+ extract(unpack('NgLength', $this->_string_shift($response, 4)));
1621
+ $gBytes = $this->_string_shift($response, $gLength);
1622
+ $g = new Math_BigInteger($gBytes, -256);
1623
+
1624
+ $exchange_hash_rfc4419 = pack(
1625
+ 'a*Na*Na*',
1626
+ $dh_group_sizes_packed,
1627
+ $primeLength,
1628
+ $primeBytes,
1629
+ $gLength,
1630
+ $gBytes
1631
+ );
1632
+
1633
+ $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
1634
+ $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
1635
+ } else {
1636
+ switch ($kex_algorithm) {
1637
+ // see http://tools.ietf.org/html/rfc2409#section-6.2 and
1638
+ // http://tools.ietf.org/html/rfc2412, appendex E
1639
+ case 'diffie-hellman-group1-sha1':
1640
+ $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
1641
+ '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
1642
+ '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
1643
+ 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
1644
+ break;
1645
+ // see http://tools.ietf.org/html/rfc3526#section-3
1646
+ case 'diffie-hellman-group14-sha1':
1647
+ $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
1648
+ '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
1649
+ '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
1650
+ 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
1651
+ '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
1652
+ '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
1653
+ 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
1654
+ '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
1655
+ break;
1656
+ }
1657
+ // For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
1658
+ // the generator field element is 2 (decimal) and the hash function is sha1.
1659
+ $g = new Math_BigInteger(2);
1660
+ $prime = new Math_BigInteger($prime, 16);
1661
+ $exchange_hash_rfc4419 = '';
1662
+ $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
1663
+ $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
1664
+ }
1665
+
1666
+ switch ($kex_algorithm) {
1667
+ case 'diffie-hellman-group-exchange-sha256':
1668
+ $kexHash = new Crypt_Hash('sha256');
1669
  break;
1670
+ default:
1671
+ $kexHash = new Crypt_Hash('sha1');
1672
  }
1673
 
 
 
 
 
 
 
 
1674
  /* To increase the speed of the key exchange, both client and server may
1675
  reduce the size of their private exponents. It should be at least
1676
  twice as long as the key material that is generated from the shared
1687
  $e = $g->modPow($x, $prime);
1688
 
1689
  $eBytes = $e->toBytes(true);
1690
+ $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
1691
 
1692
  if (!$this->_send_binary_packet($data)) {
1693
  user_error('Connection closed by server');
1699
  user_error('Connection closed by server');
1700
  return false;
1701
  }
1702
+ if (!strlen($response)) {
1703
+ return false;
1704
+ }
1705
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1706
 
1707
+ if ($type != $serverKexReplyMessage) {
1708
  user_error('Expected SSH_MSG_KEXDH_REPLY');
1709
  return false;
1710
  }
1711
 
1712
+ if (strlen($response) < 4) {
1713
+ return false;
1714
+ }
1715
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1716
  $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
1717
 
1718
+ if (strlen($server_public_host_key) < 4) {
1719
+ return false;
1720
+ }
1721
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
1722
  $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
1723
 
1724
+ if (strlen($response) < 4) {
1725
+ return false;
1726
+ }
1727
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1728
  $fBytes = $this->_string_shift($response, $temp['length']);
1729
  $f = new Math_BigInteger($fBytes, -256);
1730
 
1731
+ if (strlen($response) < 4) {
1732
+ return false;
1733
+ }
1734
  $temp = unpack('Nlength', $this->_string_shift($response, 4));
1735
  $this->signature = $this->_string_shift($response, $temp['length']);
1736
 
1737
+ if (strlen($this->signature) < 4) {
1738
+ return false;
1739
+ }
1740
  $temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
1741
  $this->signature_format = $this->_string_shift($this->signature, $temp['length']);
1742
 
1743
  $key = $f->modPow($x, $prime);
1744
  $keyBytes = $key->toBytes(true);
1745
 
1746
+ $this->exchange_hash = pack(
1747
+ 'Na*Na*Na*Na*Na*a*Na*Na*Na*',
1748
+ strlen($this->identifier),
1749
+ $this->identifier,
1750
+ strlen($this->server_identifier),
1751
+ $this->server_identifier,
1752
+ strlen($kexinit_payload_client),
1753
+ $kexinit_payload_client,
1754
+ strlen($kexinit_payload_server),
1755
+ $kexinit_payload_server,
1756
+ strlen($this->server_public_host_key),
1757
+ $this->server_public_host_key,
1758
+ $exchange_hash_rfc4419,
1759
+ strlen($eBytes),
1760
+ $eBytes,
1761
+ strlen($fBytes),
1762
+ $fBytes,
1763
+ strlen($keyBytes),
1764
+ $keyBytes
1765
  );
1766
 
1767
  $this->exchange_hash = $kexHash->hash($this->exchange_hash);
1770
  $this->session_id = $this->exchange_hash;
1771
  }
1772
 
1773
+ $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
1774
+ if ($server_host_key_algorithm === false) {
1775
  user_error('No compatible server host key algorithms found');
1776
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1777
  }
1778
 
1779
+ if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
1780
  user_error('Server Host Key Algorithm Mismatch');
1781
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
1782
  }
1783
 
1784
+ $packet = pack(
1785
+ 'C',
1786
  NET_SSH2_MSG_NEWKEYS
1787
  );
1788
 
1797
  return false;
1798
  }
1799
 
1800
+ if (!strlen($response)) {
1801
+ return false;
1802
+ }
1803
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
1804
 
1805
  if ($type != NET_SSH2_MSG_NEWKEYS) {
1961
  //$this->decrypt = new Crypt_Null();
1962
  }
1963
 
1964
+ $this->decrypt_algorithm = $decrypt;
1965
+
1966
  $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
1967
 
1968
  if ($this->encrypt) {
2019
  $this->decrypt->decrypt(str_repeat("\0", 1536));
2020
  }
2021
 
2022
+ $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
2023
+ if ($mac_algorithm === false) {
2024
  user_error('No compatible client to server message authentication algorithms found');
2025
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
2026
  }
2027
 
2028
+ $createKeyLength = 0; // ie. $mac_algorithm == 'none'
2029
+ switch ($mac_algorithm) {
2030
  case 'hmac-sha2-256':
2031
  $this->hmac_create = new Crypt_Hash('sha256');
2032
  $createKeyLength = 32;
2048
  $createKeyLength = 16;
2049
  }
2050
 
2051
+ $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
2052
+ if ($mac_algorithm === false) {
2053
  user_error('No compatible server to client message authentication algorithms found');
2054
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
2055
  }
2056
 
2057
  $checkKeyLength = 0;
2058
  $this->hmac_size = 0;
2059
+ switch ($mac_algorithm) {
2060
  case 'hmac-sha2-256':
2061
  $this->hmac_check = new Crypt_Hash('sha256');
2062
  $checkKeyLength = 32;
2095
  }
2096
  $this->hmac_check->setKey(substr($key, 0, $checkKeyLength));
2097
 
2098
+ $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
2099
+ if ($compression_algorithm === false) {
2100
  user_error('No compatible server to client compression algorithms found');
2101
  return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
2102
  }
2103
+ $this->decompress = $compression_algorithm == 'zlib';
2104
+
2105
+ $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
2106
+ if ($compression_algorithm === false) {
2107
+ user_error('No compatible client to server compression algorithms found');
2108
+ return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
2109
+ }
2110
+ $this->compress = $compression_algorithm == 'zlib';
2111
+
2112
+ return true;
2113
+ }
2114
+
2115
+ /**
2116
+ * Maps an encryption algorithm name to the number of key bytes.
2117
+ *
2118
+ * @param string $algorithm Name of the encryption algorithm
2119
+ * @return int|null Number of bytes as an integer or null for unknown
2120
+ * @access private
2121
+ */
2122
+ function _encryption_algorithm_to_key_size($algorithm)
2123
+ {
2124
+ if ($this->bad_key_size_fix && $this->_bad_algorithm_candidate($algorithm)) {
2125
+ return 16;
2126
+ }
2127
+
2128
+ switch ($algorithm) {
2129
+ case 'none':
2130
+ return 0;
2131
+ case 'aes128-cbc':
2132
+ case 'aes128-ctr':
2133
+ case 'arcfour':
2134
+ case 'arcfour128':
2135
+ case 'blowfish-cbc':
2136
+ case 'blowfish-ctr':
2137
+ case 'twofish128-cbc':
2138
+ case 'twofish128-ctr':
2139
+ return 16;
2140
+ case '3des-cbc':
2141
+ case '3des-ctr':
2142
+ case 'aes192-cbc':
2143
+ case 'aes192-ctr':
2144
+ case 'twofish192-cbc':
2145
+ case 'twofish192-ctr':
2146
+ return 24;
2147
+ case 'aes256-cbc':
2148
+ case 'aes256-ctr':
2149
+ case 'arcfour256':
2150
+ case 'twofish-cbc':
2151
+ case 'twofish256-cbc':
2152
+ case 'twofish256-ctr':
2153
+ return 32;
2154
+ }
2155
+ return null;
2156
+ }
2157
 
2158
+ /**
2159
+ * Tests whether or not proposed algorithm has a potential for issues
2160
+ *
2161
+ * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
2162
+ * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291
2163
+ * @param string $algorithm Name of the encryption algorithm
2164
+ * @return bool
2165
+ * @access private
2166
+ */
2167
+ function _bad_algorithm_candidate($algorithm)
2168
+ {
2169
+ switch ($algorithm) {
2170
+ case 'arcfour256':
2171
+ case 'aes192-ctr':
2172
+ case 'aes256-ctr':
2173
+ return true;
2174
  }
 
2175
 
2176
+ return false;
2177
  }
2178
 
2179
  /**
2181
  *
2182
  * The $password parameter can be a plaintext password, a Crypt_RSA object or an array
2183
  *
2184
+ * @param string $username
2185
+ * @param mixed $password
2186
+ * @param mixed $...
2187
+ * @return bool
2188
+ * @see self::_login()
2189
  * @access public
2190
  */
2191
  function login($username)
2197
  /**
2198
  * Login Helper
2199
  *
2200
+ * @param string $username
2201
+ * @param mixed $password
2202
+ * @param mixed $...
2203
+ * @return bool
2204
+ * @see self::_login_helper()
2205
  * @access private
2206
  */
2207
  function _login($username)
2228
  /**
2229
  * Login Helper
2230
  *
2231
+ * @param string $username
2232
+ * @param string $password
2233
+ * @return bool
2234
  * @access private
2235
  * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
2236
  * by sending dummy SSH_MSG_IGNORE messages.
2242
  }
2243
 
2244
  if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) {
2245
+ $packet = pack(
2246
+ 'CNa*',
2247
+ NET_SSH2_MSG_SERVICE_REQUEST,
2248
+ strlen('ssh-userauth'),
2249
+ 'ssh-userauth'
2250
  );
2251
 
2252
  if (!$this->_send_binary_packet($packet)) {
2255
 
2256
  $response = $this->_get_binary_packet();
2257
  if ($response === false) {
2258
+ if ($this->retry_connect) {
2259
+ $this->retry_connect = false;
2260
+ if (!$this->_connect()) {
2261
+ return false;
2262
+ }
2263
+ return $this->_login_helper($username, $password);
2264
+ }
2265
  user_error('Connection closed by server');
2266
  return false;
2267
  }
2268
 
2269
+ if (strlen($response) < 4) {
2270
+ return false;
2271
+ }
2272
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2273
 
2274
  if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
2301
  }
2302
 
2303
  if (!isset($password)) {
2304
+ $packet = pack(
2305
+ 'CNa*Na*Na*',
2306
+ NET_SSH2_MSG_USERAUTH_REQUEST,
2307
+ strlen($username),
2308
+ $username,
2309
+ strlen('ssh-connection'),
2310
+ 'ssh-connection',
2311
+ strlen('none'),
2312
+ 'none'
2313
  );
2314
 
2315
  if (!$this->_send_binary_packet($packet)) {
2322
  return false;
2323
  }
2324
 
2325
+ if (!strlen($response)) {
2326
+ return false;
2327
+ }
2328
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2329
 
2330
  switch ($type) {
2337
  }
2338
  }
2339
 
2340
+ $packet = pack(
2341
+ 'CNa*Na*Na*CNa*',
2342
+ NET_SSH2_MSG_USERAUTH_REQUEST,
2343
+ strlen($username),
2344
+ $username,
2345
+ strlen('ssh-connection'),
2346
+ 'ssh-connection',
2347
+ strlen('password'),
2348
+ 'password',
2349
+ 0,
2350
+ strlen($password),
2351
+ $password
2352
  );
2353
 
2354
  // remove the username and password from the logged packet
2355
  if (!defined('NET_SSH2_LOGGING')) {
2356
  $logged = null;
2357
  } else {
2358
+ $logged = pack(
2359
+ 'CNa*Na*Na*CNa*',
2360
+ NET_SSH2_MSG_USERAUTH_REQUEST,
2361
+ strlen('username'),
2362
+ 'username',
2363
+ strlen('ssh-connection'),
2364
+ 'ssh-connection',
2365
+ strlen('password'),
2366
+ 'password',
2367
+ 0,
2368
+ strlen('password'),
2369
+ 'password'
2370
  );
2371
  }
2372
 
2380
  return false;
2381
  }
2382
 
2383
+ if (!strlen($response)) {
2384
+ return false;
2385
+ }
2386
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2387
 
2388
  switch ($type) {
2390
  if (defined('NET_SSH2_LOGGING')) {
2391
  $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ';
2392
  }
2393
+ if (strlen($response) < 4) {
2394
+ return false;
2395
+ }
2396
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2397
  $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode($this->_string_shift($response, $length));
2398
  return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
2399
  case NET_SSH2_MSG_USERAUTH_FAILURE:
2400
  // can we use keyboard-interactive authentication? if not then either the login is bad or the server employees
2401
  // multi-factor authentication
2402
+ if (strlen($response) < 4) {
2403
+ return false;
2404
+ }
2405
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2406
  $auth_methods = explode(',', $this->_string_shift($response, $length));
2407
+ if (!strlen($response)) {
2408
+ return false;
2409
+ }
2410
  extract(unpack('Cpartial_success', $this->_string_shift($response, 1)));
2411
  $partial_success = $partial_success != 0;
2412
 
2431
  *
2432
  * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator.
2433
  *
2434
+ * @param string $username
2435
+ * @param string $password
2436
+ * @return bool
2437
  * @access private
2438
  */
2439
  function _keyboard_interactive_login($username, $password)
2440
  {
2441
+ $packet = pack(
2442
+ 'CNa*Na*Na*Na*Na*',
2443
+ NET_SSH2_MSG_USERAUTH_REQUEST,
2444
+ strlen($username),
2445
+ $username,
2446
+ strlen('ssh-connection'),
2447
+ 'ssh-connection',
2448
+ strlen('keyboard-interactive'),
2449
+ 'keyboard-interactive',
2450
+ 0,
2451
+ '',
2452
+ 0,
2453
+ ''
2454
  );
2455
 
2456
  if (!$this->_send_binary_packet($packet)) {
2463
  /**
2464
  * Handle the keyboard-interactive requests / responses.
2465
  *
2466
+ * @param string $responses...
2467
+ * @return bool
2468
  * @access private
2469
  */
2470
  function _keyboard_interactive_process()
2481
  }
2482
  }
2483
 
2484
+ if (!strlen($response)) {
2485
+ return false;
2486
+ }
2487
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2488
 
2489
  switch ($type) {
2490
  case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
2491
+ if (strlen($response) < 4) {
2492
+ return false;
2493
+ }
2494
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2495
  $this->_string_shift($response, $length); // name; may be empty
2496
+ if (strlen($response) < 4) {
2497
+ return false;
2498
+ }
2499
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2500
  $this->_string_shift($response, $length); // instruction; may be empty
2501
+ if (strlen($response) < 4) {
2502
+ return false;
2503
+ }
2504
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2505
  $this->_string_shift($response, $length); // language tag; may be empty
2506
+ if (strlen($response) < 4) {
2507
+ return false;
2508
+ }
2509
  extract(unpack('Nnum_prompts', $this->_string_shift($response, 4)));
2510
 
2511
  for ($i = 0; $i < count($responses); $i++) {
2520
 
2521
  if (isset($this->keyboard_requests_responses)) {
2522
  for ($i = 0; $i < $num_prompts; $i++) {
2523
+ if (strlen($response) < 4) {
2524
+ return false;
2525
+ }
2526
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2527
  // prompt - ie. "Password: "; must not be empty
2528
  $prompt = $this->_string_shift($response, $length);
2539
  // see http://tools.ietf.org/html/rfc4256#section-3.2
2540
  if (strlen($this->last_interactive_response)) {
2541
  $this->last_interactive_response = '';
2542
+ } elseif (defined('NET_SSH2_LOGGING')) {
2543
  $this->message_number_log[count($this->message_number_log) - 1] = str_replace(
2544
  'UNKNOWN',
2545
  'NET_SSH2_MSG_USERAUTH_INFO_REQUEST',
2595
  /**
2596
  * Login with an ssh-agent provided key
2597
  *
2598
+ * @param string $username
2599
  * @param System_SSH_Agent $agent
2600
+ * @return bool
2601
  * @access private
2602
  */
2603
  function _ssh_agent_login($username, $agent)
2616
  /**
2617
  * Login with an RSA private key
2618
  *
2619
+ * @param string $username
2620
  * @param Crypt_RSA $password
2621
+ * @return bool
2622
  * @access private
2623
  * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
2624
  * by sending dummy SSH_MSG_IGNORE messages.
2635
  'e' => $publickey['e']->toBytes(true),
2636
  'n' => $publickey['n']->toBytes(true)
2637
  );
2638
+ $publickey = pack(
2639
+ 'Na*Na*Na*',
2640
+ strlen('ssh-rsa'),
2641
+ 'ssh-rsa',
2642
+ strlen($publickey['e']),
2643
+ $publickey['e'],
2644
+ strlen($publickey['n']),
2645
+ $publickey['n']
2646
  );
2647
 
2648
+ $part1 = pack(
2649
+ 'CNa*Na*Na*',
2650
+ NET_SSH2_MSG_USERAUTH_REQUEST,
2651
+ strlen($username),
2652
+ $username,
2653
+ strlen('ssh-connection'),
2654
+ 'ssh-connection',
2655
+ strlen('publickey'),
2656
+ 'publickey'
2657
  );
2658
  $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey);
2659
 
2668
  return false;
2669
  }
2670
 
2671
+ if (!strlen($response)) {
2672
+ return false;
2673
+ }
2674
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2675
 
2676
  switch ($type) {
2677
  case NET_SSH2_MSG_USERAUTH_FAILURE:
2678
+ if (strlen($response) < 4) {
2679
+ return false;
2680
+ }
2681
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
2682
  $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length);
2683
  return false;
2709
  return false;
2710
  }
2711
 
2712
+ if (!strlen($response)) {
2713
+ return false;
2714
+ }
2715
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
2716
 
2717
  switch ($type) {
2732
  * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout.
2733
  * Setting $timeout to false or 0 will mean there is no timeout.
2734
  *
2735
+ * @param mixed $timeout
2736
  * @access public
2737
  */
2738
  function setTimeout($timeout)
2756
  * If $callback is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
2757
  * In all likelihood, this is not a feature you want to be taking advantage of.
2758
  *
2759
+ * @param string $command
2760
+ * @param Callback $callback
2761
+ * @return string
2762
  * @access public
2763
  */
2764
  function exec($command, $callback = null)
2767
  $this->is_timeout = false;
2768
  $this->stdErrorLog = '';
2769
 
2770
+ if (!$this->isAuthenticated()) {
2771
+ return false;
2772
+ }
2773
+
2774
+ if ($this->in_request_pty_exec) {
2775
+ user_error('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
2776
  return false;
2777
  }
2778
 
2779
  // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
2780
  // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
2781
+ // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
2782
  // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
2783
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size;
2784
  // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
2785
  // uses 0x4000, that's what will be used here, as well.
2786
  $packet_size = 0x4000;
2787
 
2788
+ $packet = pack(
2789
+ 'CNa*N3',
2790
+ NET_SSH2_MSG_CHANNEL_OPEN,
2791
+ strlen('session'),
2792
+ 'session',
2793
+ NET_SSH2_CHANNEL_EXEC,
2794
+ $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC],
2795
+ $packet_size
2796
+ );
2797
 
2798
  if (!$this->_send_binary_packet($packet)) {
2799
  return false;
2808
 
2809
  if ($this->request_pty === true) {
2810
  $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
2811
+ $packet = pack(
2812
+ 'CNNa*CNa*N5a*',
2813
+ NET_SSH2_MSG_CHANNEL_REQUEST,
2814
+ $this->server_channels[NET_SSH2_CHANNEL_EXEC],
2815
+ strlen('pty-req'),
2816
+ 'pty-req',
2817
+ 1,
2818
+ strlen('vt100'),
2819
+ 'vt100',
2820
+ $this->windowColumns,
2821
+ $this->windowRows,
2822
+ 0,
2823
+ 0,
2824
+ strlen($terminal_modes),
2825
+ $terminal_modes
2826
+ );
2827
 
2828
  if (!$this->_send_binary_packet($packet)) {
2829
  return false;
2835
  return false;
2836
  }
2837
 
2838
+ if (!strlen($response)) {
2839
+ return false;
2840
+ }
2841
  list(, $type) = unpack('C', $this->_string_shift($response, 1));
2842
 
2843
  switch ($type) {
2860
  // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
2861
  // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
2862
  // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates.
2863
+ $packet = pack(
2864
+ 'CNNa*CNa*',
2865
+ NET_SSH2_MSG_CHANNEL_REQUEST,
2866
+ $this->server_channels[NET_SSH2_CHANNEL_EXEC],
2867
+ strlen('exec'),
2868
+ 'exec',
2869
+ 1,
2870
+ strlen($command),
2871
+ $command
2872
+ );
2873
 
2874
  if (!$this->_send_binary_packet($packet)) {
2875
  return false;
2912
  /**
2913
  * Creates an interactive shell
2914
  *
2915
+ * @see self::read()
2916
+ * @see self::write()
2917
+ * @return bool
2918
  * @access private
2919
  */
2920
  function _initShell()
2926
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size;
2927
  $packet_size = 0x4000;
2928
 
2929
+ $packet = pack(
2930
+ 'CNa*N3',
2931
+ NET_SSH2_MSG_CHANNEL_OPEN,
2932
+ strlen('session'),
2933
+ 'session',
2934
+ NET_SSH2_CHANNEL_SHELL,
2935
+ $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL],
2936
+ $packet_size
2937
+ );
2938
 
2939
  if (!$this->_send_binary_packet($packet)) {
2940
  return false;
2948
  }
2949
 
2950
  $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
2951
+ $packet = pack(
2952
+ 'CNNa*CNa*N5a*',
2953
+ NET_SSH2_MSG_CHANNEL_REQUEST,
2954
+ $this->server_channels[NET_SSH2_CHANNEL_SHELL],
2955
+ strlen('pty-req'),
2956
+ 'pty-req',
2957
+ 1,
2958
+ strlen('vt100'),
2959
+ 'vt100',
2960
+ $this->windowColumns,
2961
+ $this->windowRows,
2962
+ 0,
2963
+ 0,
2964
+ strlen($terminal_modes),
2965
+ $terminal_modes
2966
+ );
2967
 
2968
  if (!$this->_send_binary_packet($packet)) {
2969
  return false;
2975
  return false;
2976
  }
2977
 
2978
+ if (!strlen($response)) {
2979
+ return false;
2980
+ }
2981
  list(, $type) = unpack('C', $this->_string_shift($response, 1));
2982
 
2983
  switch ($type) {
2990
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
2991
  }
2992
 
2993
+ $packet = pack(
2994
+ 'CNNa*C',
2995
+ NET_SSH2_MSG_CHANNEL_REQUEST,
2996
+ $this->server_channels[NET_SSH2_CHANNEL_SHELL],
2997
+ strlen('shell'),
2998
+ 'shell',
2999
+ 1
3000
+ );
3001
  if (!$this->_send_binary_packet($packet)) {
3002
  return false;
3003
  }
3019
  /**
3020
  * Return the channel to be used with read() / write()
3021
  *
3022
+ * @see self::read()
3023
+ * @see self::write()
3024
+ * @return int
3025
  * @access public
3026
  */
3027
  function _get_interactive_channel()
3039
  /**
3040
  * Return an available open channel
3041
  *
3042
+ * @return int
3043
  * @access public
3044
  */
3045
  function _get_open_channel()
3060
  * Returns when there's a match for $expect, which can take the form of a string literal or,
3061
  * if $mode == NET_SSH2_READ_REGEX, a regular expression.
3062
  *
3063
+ * @see self::write()
3064
+ * @param string $expect
3065
+ * @param int $mode
3066
+ * @return string
3067
  * @access public
3068
  */
3069
  function read($expect = '', $mode = NET_SSH2_READ_SIMPLE)
3071
  $this->curTimeout = $this->timeout;
3072
  $this->is_timeout = false;
3073
 
3074
+ if (!$this->isAuthenticated()) {
3075
  user_error('Operation disallowed prior to login()');
3076
  return false;
3077
  }
3083
 
3084
  $channel = $this->_get_interactive_channel();
3085
 
3086
+ if ($mode == NET_SSH2_READ_NEXT) {
3087
+ return $this->_get_channel_packet($channel);
3088
+ }
3089
+
3090
  $match = $expect;
3091
  while (true) {
3092
  if ($mode == NET_SSH2_READ_REGEX) {
3093
+ preg_match($expect, substr($this->interactiveBuffer, -1024), $matches);
3094
  $match = isset($matches[0]) ? $matches[0] : '';
3095
  }
3096
  $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
3110
  /**
3111
  * Inputs a command into an interactive shell.
3112
  *
3113
+ * @see self::read()
3114
+ * @param string $cmd
3115
+ * @return bool
3116
  * @access public
3117
  */
3118
  function write($cmd)
3119
  {
3120
+ if (!$this->isAuthenticated()) {
3121
  user_error('Operation disallowed prior to login()');
3122
  return false;
3123
  }
3139
  * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
3140
  * if there's sufficient demand for such a feature.
3141
  *
3142
+ * @see self::stopSubsystem()
3143
+ * @param string $subsystem
3144
+ * @return bool
3145
  * @access public
3146
  */
3147
  function startSubsystem($subsystem)
3148
  {
3149
  $this->window_size_server_to_client[NET_SSH2_CHANNEL_SUBSYSTEM] = $this->window_size;
3150
 
3151
+ $packet = pack(
3152
+ 'CNa*N3',
3153
+ NET_SSH2_MSG_CHANNEL_OPEN,
3154
+ strlen('session'),
3155
+ 'session',
3156
+ NET_SSH2_CHANNEL_SUBSYSTEM,
3157
+ $this->window_size,
3158
+ 0x4000
3159
+ );
3160
 
3161
  if (!$this->_send_binary_packet($packet)) {
3162
  return false;
3169
  return false;
3170
  }
3171
 
3172
+ $packet = pack(
3173
+ 'CNNa*CNa*',
3174
+ NET_SSH2_MSG_CHANNEL_REQUEST,
3175
+ $this->server_channels[NET_SSH2_CHANNEL_SUBSYSTEM],
3176
+ strlen('subsystem'),
3177
+ 'subsystem',
3178
+ 1,
3179
+ strlen($subsystem),
3180
+ $subsystem
3181
+ );
3182
  if (!$this->_send_binary_packet($packet)) {
3183
  return false;
3184
  }
3188
  $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM);
3189
 
3190
  if ($response === false) {
3191
+ return false;
3192
  }
3193
 
3194
  $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
3202
  /**
3203
  * Stops a subsystem.
3204
  *
3205
+ * @see self::startSubsystem()
3206
+ * @return bool
3207
  * @access public
3208
  */
3209
  function stopSubsystem()
3266
  /**
3267
  * Is the connection still active?
3268
  *
3269
+ * @return bool
3270
  * @access public
3271
  */
3272
  function isConnected()
3274
  return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
3275
  }
3276
 
3277
+ /**
3278
+ * Have you successfully been logged in?
3279
+ *
3280
+ * @return bool
3281
+ * @access public
3282
+ */
3283
+ function isAuthenticated()
3284
+ {
3285
+ return (bool) ($this->bitmap & NET_SSH2_MASK_LOGIN);
3286
+ }
3287
+
3288
+ /**
3289
+ * Resets a connection for re-use
3290
+ *
3291
+ * @param int $reason
3292
+ * @access private
3293
+ */
3294
+ function _reset_connection($reason)
3295
+ {
3296
+ $this->_disconnect($reason);
3297
+ $this->decrypt = $this->encrypt = false;
3298
+ $this->decrypt_block_size = $this->encrypt_block_size = 8;
3299
+ $this->hmac_check = $this->hmac_create = false;
3300
+ $this->hmac_size = false;
3301
+ $this->session_id = false;
3302
+ $this->retry_connect = true;
3303
+ $this->get_seq_no = $this->send_seq_no = 0;
3304
+ }
3305
+
3306
  /**
3307
  * Gets Binary Packets
3308
  *
3309
  * See '6. Binary Packet Protocol' of rfc4253 for more info.
3310
  *
3311
+ * @see self::_send_binary_packet()
3312
+ * @return string
3313
  * @access private
3314
  */
3315
+ function _get_binary_packet($skip_channel_filter = false)
3316
  {
3317
  if (!is_resource($this->fsock) || feof($this->fsock)) {
3318
  user_error('Connection closed prematurely');
3335
  return false;
3336
  }
3337
 
3338
+ if (strlen($raw) < 5) {
3339
+ return false;
3340
+ }
3341
  extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
3342
 
3343
  $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
3346
  // "implementations SHOULD check that the packet length is reasonable"
3347
  // PuTTY uses 0x9000 as the actual max packet size and so to shall we
3348
  if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
3349
+ if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & NET_SSH2_MASK_LOGIN)) {
3350
+ $this->bad_key_size_fix = true;
3351
+ $this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
3352
+ return false;
3353
+ }
3354
  user_error('Invalid size');
3355
  return false;
3356
  }
3366
  $buffer.= $temp;
3367
  $remaining_length-= strlen($temp);
3368
  }
3369
+
3370
  $stop = strtok(microtime(), ' ') + strtok('');
3371
  if (strlen($buffer)) {
3372
  $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
3402
  $this->last_packet = $current;
3403
  }
3404
 
3405
+ return $this->_filter($payload, $skip_channel_filter);
3406
  }
3407
 
3408
  /**
3410
  *
3411
  * Because some binary packets need to be ignored...
3412
  *
3413
+ * @see self::_get_binary_packet()
3414
+ * @return string
3415
  * @access private
3416
  */
3417
+ function _filter($payload, $skip_channel_filter)
3418
  {
3419
  switch (ord($payload[0])) {
3420
  case NET_SSH2_MSG_DISCONNECT:
3421
  $this->_string_shift($payload, 1);
3422
+ if (strlen($payload) < 8) {
3423
+ return false;
3424
+ }
3425
  extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8)));
3426
  $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length));
3427
  $this->bitmap = 0;
3428
  return false;
3429
  case NET_SSH2_MSG_IGNORE:
3430
+ $payload = $this->_get_binary_packet($skip_channel_filter);
3431
  break;
3432
  case NET_SSH2_MSG_DEBUG:
3433
  $this->_string_shift($payload, 2);
3434
+ if (strlen($payload) < 4) {
3435
+ return false;
3436
+ }
3437
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
3438
  $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length));
3439
+ $payload = $this->_get_binary_packet($skip_channel_filter);
3440
  break;
3441
  case NET_SSH2_MSG_UNIMPLEMENTED:
3442
  return false;
3443
  case NET_SSH2_MSG_KEXINIT:
3444
  if ($this->session_id !== false) {
3445
+ $this->send_kex_first = false;
3446
  if (!$this->_key_exchange($payload)) {
3447
  $this->bitmap = 0;
3448
  return false;
3449
  }
3450
+ $payload = $this->_get_binary_packet($skip_channel_filter);
3451
  }
3452
  }
3453
 
3454
  // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
3455
+ if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
3456
  $this->_string_shift($payload, 1);
3457
+ if (strlen($payload) < 4) {
3458
+ return false;
3459
+ }
3460
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
3461
  $this->banner_message = utf8_decode($this->_string_shift($payload, $length));
3462
  $payload = $this->_get_binary_packet();
3463
  }
3464
 
3465
  // only called when we've already logged in
3466
+ if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && $this->isAuthenticated()) {
3467
  switch (ord($payload[0])) {
3468
+ case NET_SSH2_MSG_CHANNEL_DATA:
3469
+ case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
3470
+ case NET_SSH2_MSG_CHANNEL_REQUEST:
3471
+ case NET_SSH2_MSG_CHANNEL_CLOSE:
3472
+ case NET_SSH2_MSG_CHANNEL_EOF:
3473
+ if (!$skip_channel_filter && !empty($this->server_channels)) {
3474
+ $this->binary_packet_buffer = $payload;
3475
+ $this->_get_channel_packet(true);
3476
+ $payload = $this->_get_binary_packet();
3477
+ }
3478
+ break;
3479
  case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
3480
+ if (strlen($payload) < 4) {
3481
+ return false;
3482
+ }
3483
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
3484
  $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length);
3485
 
3487
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
3488
  }
3489
 
3490
+ $payload = $this->_get_binary_packet($skip_channel_filter);
3491
  break;
3492
  case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
3493
  $this->_string_shift($payload, 1);
3494
+ if (strlen($payload) < 4) {
3495
+ return false;
3496
+ }
3497
  extract(unpack('Nlength', $this->_string_shift($payload, 4)));
3498
  $data = $this->_string_shift($payload, $length);
3499
+ if (strlen($payload) < 4) {
3500
+ return false;
3501
+ }
3502
  extract(unpack('Nserver_channel', $this->_string_shift($payload, 4)));
3503
+ switch ($data) {
3504
  case 'auth-agent':
3505
  case 'auth-agent@openssh.com':
3506
  if (isset($this->agent)) {
3507
+ $new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD;
3508
+
3509
+ if (strlen($payload) < 8) {
3510
+ return false;
3511
+ }
3512
+ extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4)));
3513
+ extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4)));
3514
+
3515
+ $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
3516
+ $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
3517
+ $this->window_size_client_to_server[$new_channel] = $this->window_size;
3518
+
3519
+ $packet_size = 0x4000;
3520
+
3521
+ $packet = pack(
3522
+ 'CN4',
3523
+ NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
3524
+ $server_channel,
3525
+ $new_channel,
3526
+ $packet_size,
3527
+ $packet_size
3528
+ );
3529
+
3530
+ $this->server_channels[$new_channel] = $server_channel;
3531
+ $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
3532
+ if (!$this->_send_binary_packet($packet)) {
3533
+ return false;
3534
+ }
3535
  }
3536
  break;
3537
  default:
3538
+ $packet = pack(
3539
+ 'CN3a*Na*',
3540
+ NET_SSH2_MSG_REQUEST_FAILURE,
3541
+ $server_channel,
3542
+ NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
3543
+ 0,
3544
+ '',
3545
+ 0,
3546
+ ''
3547
+ );
3548
 
3549
  if (!$this->_send_binary_packet($packet)) {
3550
  return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
3551
  }
3552
  }
3553
+ $payload = $this->_get_binary_packet($skip_channel_filter);
3554
  break;
3555
  case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
3556
  $this->_string_shift($payload, 1);
3557
+ if (strlen($payload) < 8) {
3558
+ return false;
3559
+ }
3560
  extract(unpack('Nchannel', $this->_string_shift($payload, 4)));
3561
  extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
3562
  $this->window_size_client_to_server[$channel]+= $window_size;
3563
 
3564
+ $payload = ($this->bitmap & NET_SSH2_MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet($skip_channel_filter);
3565
  }
3566
  }
3567
 
3595
  /**
3596
  * Returns whether Quiet Mode is enabled or not
3597
  *
3598
+ * @see self::enableQuietMode()
3599
+ * @see self::disableQuietMode()
3600
  *
3601
  * @access public
3602
+ * @return bool
3603
  */
3604
  function isQuietModeEnabled()
3605
  {
3623
  */
3624
  function disablePTY()
3625
  {
3626
+ if ($this->in_request_pty_exec) {
3627
+ $this->_close_channel(NET_SSH2_CHANNEL_EXEC);
3628
+ $this->in_request_pty_exec = false;
3629
+ }
3630
  $this->request_pty = false;
3631
  }
3632
 
3633
  /**
3634
  * Returns whether request-pty is enabled or not
3635
  *
3636
+ * @see self::enablePTY()
3637
+ * @see self::disablePTY()
3638
  *
3639
  * @access public
3640
+ * @return bool
3641
  */
3642
  function isPTYEnabled()
3643
  {
3650
  * Returns the data as a string if it's available and false if not.
3651
  *
3652
  * @param $client_channel
3653
+ * @return mixed
3654
  * @access private
3655
  */
3656
  function _get_channel_packet($client_channel, $skip_extended = false)
3660
  }
3661
 
3662
  while (true) {
3663
+ if ($this->binary_packet_buffer !== false) {
3664
+ $response = $this->binary_packet_buffer;
3665
+ $this->binary_packet_buffer = false;
3666
+ } else {
3667
+ if ($this->curTimeout) {
3668
+ if ($this->curTimeout < 0) {
3669
+ $this->is_timeout = true;
3670
+ return true;
3671
+ }
3672
 
3673
+ $read = array($this->fsock);
3674
+ $write = $except = null;
3675
 
3676
+ $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
3677
+ $sec = floor($this->curTimeout);
3678
+ $usec = 1000000 * ($this->curTimeout - $sec);
3679
+ // on windows this returns a "Warning: Invalid CRT parameters detected" error
3680
+ if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
3681
+ $this->is_timeout = true;
3682
+ return true;
3683
+ }
3684
+ $elapsed = strtok(microtime(), ' ') + strtok('') - $start;
3685
+ $this->curTimeout-= $elapsed;
3686
  }
 
 
 
3687
 
3688
+ $response = $this->_get_binary_packet(true);
3689
+ if ($response === false) {
3690
+ user_error('Connection closed by server');
3691
+ return false;
3692
+ }
3693
  }
3694
+
3695
  if ($client_channel == -1 && $response === true) {
3696
  return true;
3697
  }
3699
  return '';
3700
  }
3701
 
3702
+ if (!strlen($response)) {
3703
+ return false;
3704
+ }
3705
  extract(unpack('Ctype', $this->_string_shift($response, 1)));
3706
 
3707
+ if (strlen($response) < 4) {
3708
+ return false;
3709
+ }
3710
  if ($type == NET_SSH2_MSG_CHANNEL_OPEN) {
3711
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3712
  } else {
3726
  $this->window_size_server_to_client[$channel]+= $this->window_size;
3727
  }
3728
 
3729
+ if ($type == NET_SSH2_MSG_CHANNEL_EXTENDED_DATA) {
3730
+ /*
3731
+ if ($client_channel == NET_SSH2_CHANNEL_EXEC) {
3732
+ $this->_send_channel_packet($client_channel, chr(0));
3733
+ }
3734
+ */
3735
+ // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
3736
+ if (strlen($response) < 8) {
3737
+ return false;
3738
+ }
3739
+ extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
3740
+ $data = $this->_string_shift($response, $length);
3741
+ $this->stdErrorLog.= $data;
3742
+ if ($skip_extended || $this->quiet_mode) {
3743
+ continue;
3744
+ }
3745
+ if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
3746
+ return $data;
3747
+ }
3748
+ if (!isset($this->channel_buffers[$channel])) {
3749
+ $this->channel_buffers[$channel] = array();
3750
+ }
3751
+ $this->channel_buffers[$channel][] = $data;
3752
+
3753
+ continue;
3754
+ }
3755
+
3756
  switch ($this->channel_status[$channel]) {
3757
  case NET_SSH2_MSG_CHANNEL_OPEN:
3758
  switch ($type) {
3759
  case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
3760
+ if (strlen($response) < 4) {
3761
+ return false;
3762
+ }
3763
  extract(unpack('Nserver_channel', $this->_string_shift($response, 4)));
3764
  $this->server_channels[$channel] = $server_channel;
3765
+ if (strlen($response) < 4) {
3766
+ return false;
3767
+ }
3768
  extract(unpack('Nwindow_size', $this->_string_shift($response, 4)));
3769
+ if ($window_size < 0) {
3770
+ $window_size&= 0x7FFFFFFF;
3771
+ $window_size+= 0x80000000;
3772
+ }
3773
  $this->window_size_client_to_server[$channel] = $window_size;
3774
+ if (strlen($response) < 4) {
3775
+ return false;
3776
+ }
3777
  $temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4));
3778
  $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server'];
3779
  $result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended);
3813
  $this->_send_channel_packet($channel, chr(0));
3814
  }
3815
  */
3816
+ if (strlen($response) < 4) {
3817
+ return false;
3818
+ }
3819
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3820
  $data = $this->_string_shift($response, $length);
3821
 
3827
  break;
3828
  }
3829
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3830
  if ($client_channel == $channel) {
3831
  return $data;
3832
  }
3836
  $this->channel_buffers[$channel][] = $data;
3837
  break;
3838
  case NET_SSH2_MSG_CHANNEL_REQUEST:
3839
+ if (strlen($response) < 4) {
3840
+ return false;
3841
+ }
3842
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3843
  $value = $this->_string_shift($response, $length);
3844
  switch ($value) {
3845
  case 'exit-signal':
3846
  $this->_string_shift($response, 1);
3847
+ if (strlen($response) < 4) {
3848
+ return false;
3849
+ }
3850
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3851
  $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
3852
  $this->_string_shift($response, 1);
3853
+ if (strlen($response) < 4) {
3854
+ return false;
3855
+ }
3856
  extract(unpack('Nlength', $this->_string_shift($response, 4)));
3857
  if ($length) {
3858
  $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
3865
 
3866
  break;
3867
  case 'exit-status':
3868
+ if (strlen($response) < 5) {
3869
+ return false;
3870
+ }
3871
  extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
3872
  $this->exit_status = $exit_status;
3873
 
3892
  }
3893
 
3894
  $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
3895
+ if ($client_channel == $channel) {
3896
+ return true;
3897
+ }
3898
  case NET_SSH2_MSG_CHANNEL_EOF:
3899
  break;
3900
  default:
3909
  *
3910
  * See '6. Binary Packet Protocol' of rfc4253 for more info.
3911
  *
3912
+ * @param string $data
3913
+ * @param string $logged
3914
+ * @see self::_get_binary_packet()
3915
+ * @return bool
3916
  * @access private
3917
  */
3918
  function _send_binary_packet($data, $logged = null)
3970
  *
3971
  * Makes sure that only the last 1MB worth of packets will be logged
3972
  *
3973
+ * @param string $data
3974
  * @access private
3975
  */
3976
  function _append_log($message_number, $message)
4046
  *
4047
  * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
4048
  *
4049
+ * @param int $client_channel
4050
+ * @param string $data
4051
+ * @return bool
4052
  * @access private
4053
  */
4054
  function _send_channel_packet($client_channel, $data)
4071
  );
4072
 
4073
  $temp = $this->_string_shift($data, $max_size);
4074
+ $packet = pack(
4075
+ 'CN2a*',
4076
  NET_SSH2_MSG_CHANNEL_DATA,
4077
  $this->server_channels[$client_channel],
4078
  strlen($temp),
4094
  * and for SFTP channels are presumably closed when the client disconnects. This functions is intended
4095
  * for SCP more than anything.
4096
  *
4097
+ * @param int $client_channel
4098
+ * @param bool $want_reply
4099
+ * @return bool
4100
  * @access private
4101
  */
4102
  function _close_channel($client_channel, $want_reply = false)
4113
 
4114
  $this->curTimeout = 0;
4115
 
4116
+ while (!is_bool($this->_get_channel_packet($client_channel))) {
4117
+ }
4118
 
4119
  if ($want_reply) {
4120
  $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
4128
  /**
4129
  * Disconnect
4130
  *
4131
+ * @param int $reason
4132
+ * @return bool
4133
  * @access private
4134
  */
4135
  function _disconnect($reason)
4148
  *
4149
  * Inspired by array_shift
4150
  *
4151
+ * @param string $string
4152
+ * @param int $index
4153
+ * @return string
4154
  * @access private
4155
  */
4156
  function _string_shift(&$string, $index = 1)
4167
  * named constants from it, using the value as the name of the constant and the index as the value of the constant.
4168
  * If any of the constants that would be defined already exists, none of the constants will be defined.
4169
  *
4170
+ * @param array $array
4171
  * @access private
4172
  */
4173
  function _define_array()
4174
  {
4175
  $args = func_get_args();
4176
  foreach ($args as $arg) {
4177
+ foreach ($arg as $key => $value) {
4178
  if (!defined($value)) {
4179
  define($value, $key);
4180
  } else {
4190
  * Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
4191
  *
4192
  * @access public
4193
+ * @return array|false|string
4194
  */
4195
  function getLog()
4196
  {
4201
  switch (NET_SSH2_LOGGING) {
4202
  case NET_SSH2_LOG_SIMPLE:
4203
  return $this->message_number_log;
 
4204
  case NET_SSH2_LOG_COMPLEX:
4205
+ $log = $this->_format_log($this->message_log, $this->message_number_log);
4206
+ return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>';
4207
  default:
4208
  return false;
4209
  }
4212
  /**
4213
  * Formats a log for printing
4214
  *
4215
+ * @param array $message_log
4216
+ * @param array $message_number_log
4217
  * @access private
4218
+ * @return string
4219
  */
4220
  function _format_log($message_log, $message_number_log)
4221
  {
4248
  *
4249
  * For use with preg_replace_callback()
4250
  *
4251
+ * @param array $matches
4252
  * @access private
4253
+ * @return string
4254
  */
4255
  function _format_log_helper($matches)
4256
  {
4273
  }
4274
  }
4275
 
4276
+ /**
4277
+ * Returns the first value of the intersection of two arrays or false if
4278
+ * the intersection is empty. The order is defined by the first parameter.
4279
+ *
4280
+ * @param array $array1
4281
+ * @param array $array2
4282
+ * @return mixed False if intersection is empty, else intersected value.
4283
+ * @access private
4284
+ */
4285
+ function _array_intersect_first($array1, $array2)
4286
+ {
4287
+ foreach ($array1 as $value) {
4288
+ if (in_array($value, $array2)) {
4289
+ return $value;
4290
+ }
4291
+ }
4292
+ return false;
4293
+ }
4294
+
4295
  /**
4296
  * Returns all errors
4297
  *
4298
+ * @return string[]
4299
  * @access public
4300
  */
4301
  function getErrors()
4306
  /**
4307
  * Returns the last error
4308
  *
4309
+ * @return string
4310
  * @access public
4311
  */
4312
  function getLastError()
4313
  {
4314
+ $count = count($this->errors);
4315
+
4316
+ if ($count > 0) {
4317
+ return $this->errors[$count - 1];
4318
+ }
4319
  }
4320
 
4321
  /**
4322
  * Return the server identification.
4323
  *
4324
+ * @return string
4325
  * @access public
4326
  */
4327
  function getServerIdentification()
4334
  /**
4335
  * Return a list of the key exchange algorithms the server supports.
4336
  *
4337
+ * @return array
4338
  * @access public
4339
  */
4340
  function getKexAlgorithms()
4347
  /**
4348
  * Return a list of the host key (public key) algorithms the server supports.
4349
  *
4350
+ * @return array
4351
  * @access public
4352
  */
4353
  function getServerHostKeyAlgorithms()
4360
  /**
4361
  * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
4362
  *
4363
+ * @return array
4364
  * @access public
4365
  */
4366
  function getEncryptionAlgorithmsClient2Server()
4373
  /**
4374
  * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
4375
  *
4376
+ * @return array
4377
  * @access public
4378
  */
4379
  function getEncryptionAlgorithmsServer2Client()
4386
  /**
4387
  * Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
4388
  *
4389
+ * @return array
4390
  * @access public
4391
  */
4392
  function getMACAlgorithmsClient2Server()
4399
  /**
4400
  * Return a list of the MAC algorithms the server supports, when sending stuff to the client.
4401
  *
4402
+ * @return array
4403
  * @access public
4404
  */
4405
  function getMACAlgorithmsServer2Client()
4412
  /**
4413
  * Return a list of the compression algorithms the server supports, when receiving stuff from the client.
4414
  *
4415
+ * @return array
4416
  * @access public
4417
  */
4418
  function getCompressionAlgorithmsClient2Server()
4425
  /**
4426
  * Return a list of the compression algorithms the server supports, when sending stuff to the client.
4427
  *
4428
+ * @return array
4429
  * @access public
4430
  */
4431
  function getCompressionAlgorithmsServer2Client()
4438
  /**
4439
  * Return a list of the languages the server supports, when sending stuff to the client.
4440
  *
4441
+ * @return array
4442
  * @access public
4443
  */
4444
  function getLanguagesServer2Client()
4451
  /**
4452
  * Return a list of the languages the server supports, when receiving stuff from the client.
4453
  *
4454
+ * @return array
4455
  * @access public
4456
  */
4457
  function getLanguagesClient2Server()
4467
  * Quoting from the RFC, "in some jurisdictions, sending a warning message before
4468
  * authentication may be relevant for getting legal protection."
4469
  *
4470
+ * @return string
4471
  * @access public
4472
  */
4473
  function getBannerMessage()
4481
  * Caching this the first time you connect to a server and checking the result on subsequent connections
4482
  * is recommended. Returns false if the server signature is not signed correctly with the public host key.
4483
  *
4484
+ * @return mixed
4485
  * @access public
4486
  */
4487
  function getServerPublicHostKey()
4495
  $signature = $this->signature;
4496
  $server_public_host_key = $this->server_public_host_key;
4497
 
4498
+ if (strlen($server_public_host_key) < 4) {
4499
+ return false;
4500
+ }
4501
  extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4)));
4502
  $this->_string_shift($server_public_host_key, $length);
4503
 
4513
  case 'ssh-dss':
4514
  $zero = new Math_BigInteger();
4515
 
4516
+ if (strlen($server_public_host_key) < 4) {
4517
+ return false;
4518
+ }
4519
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4520
  $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
4521
 
4522
+ if (strlen($server_public_host_key) < 4) {
4523
+ return false;
4524
+ }
4525
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4526
  $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
4527
 
4528
+ if (strlen($server_public_host_key) < 4) {
4529
+ return false;
4530
+ }
4531
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4532
  $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
4533
 
4534
+ if (strlen($server_public_host_key) < 4) {
4535
+ return false;
4536
+ }
4537
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4538
  $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
4539
 
4580
 
4581
  break;
4582
  case 'ssh-rsa':
4583
+ if (strlen($server_public_host_key) < 4) {
4584
+ return false;
4585
+ }
4586
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4587
  $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
4588
 
4589
+ if (strlen($server_public_host_key) < 4) {
4590
+ return false;
4591
+ }
4592
  $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
4593
  $rawN = $this->_string_shift($server_public_host_key, $temp['length']);
4594
  $n = new Math_BigInteger($rawN, -256);
4595
  $nLength = strlen(ltrim($rawN, "\0"));
4596
 
4597
  /*
4598
+ if (strlen($signature) < 4) {
4599
+ return false;
4600
+ }
4601
  $temp = unpack('Nlength', $this->_string_shift($signature, 4));
4602
  $signature = $this->_string_shift($signature, $temp['length']);
4603
 
4614
  }
4615
  */
4616
 
4617
+ if (strlen($signature) < 4) {
4618
+ return false;
4619
+ }
4620
  $temp = unpack('Nlength', $this->_string_shift($signature, 4));
4621
  $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256);
4622
 
4653
  /**
4654
  * Returns the exit status of an SSH command or false.
4655
  *
4656
+ * @return false|int
4657
  * @access public
4658
  */
4659
  function getExitStatus()
4667
  /**
4668
  * Returns the number of columns for the terminal window size.
4669
  *
4670
+ * @return int
4671
  * @access public
4672
  */
4673
  function getWindowColumns()
4678
  /**
4679
  * Returns the number of rows for the terminal window size.
4680
  *
4681
+ * @return int
4682
  * @access public
4683
  */
4684
  function getWindowRows()
4689
  /**
4690
  * Sets the number of columns for the terminal window size.
4691
  *
4692
+ * @param int $value
4693
  * @access public
4694
  */
4695
  function setWindowColumns($value)
4700
  /**
4701
  * Sets the number of rows for the terminal window size.
4702
  *
4703
+ * @param int $value
4704
  * @access public
4705
  */
4706
  function setWindowRows($value)
4711
  /**
4712
  * Sets the number of columns and rows for the terminal window size.
4713
  *
4714
+ * @param int $columns
4715
+ * @param int $rows
4716
  * @access public
4717
  */
4718
  function setWindowSize($columns = 80, $rows = 24)
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: TerraFrost
3
  Donate link: http://sourceforge.net/donate/index.php?group_id=198487
4
  Tags: ssh, sftp
5
  Requires at least: 3.1
6
- Tested up to: 4.2
7
- Stable tag: 0.7.1
8
 
9
  "SSH SFTP Updater Support" is the easiest way to keep your Wordpress installation up-to-date with SFTP.
10
 
@@ -19,37 +19,40 @@ Keeping your Wordpress install up-to-date and installing plugins in a hassle-fre
19
 
20
  == Changelog ==
21
 
22
- = 0.1 =
23
- * Initial Release
24
-
25
- = 0.2 =
26
- * recursive deletes weren't working correctly (directories never got deleted - just files)
27
- * use SFTP for recursive chmod instead of SSH / exec
28
- * fix plugin for people using custom WP_CONTENT_DIR values (thanks, dd32!)
29
- * plugin prevented non-SFTP install methods from being used
30
- * make it so private keys can be uploaded in addition to being copy / pasted
31
 
32
- = 0.3 =
33
- * update phpseclib to latest SVN
34
- * read file when FTP_PRIKEY is defined (thanks, lkraav!)
35
 
36
- = 0.4 =
37
- * fix an E_NOTICE (thanks, runblip!)
38
- * make it so keys that are copy / pasted in are saved with HTML5's localStorage (thanks, kkzk!)
39
- * update phpseclib to latest Git
40
 
41
- = 0.5 =
42
- * update phpseclib to latest version
43
 
44
  = 0.6 =
45
  * update phpseclib to latest version
46
  * make plugin work with 4.2's new modal dialog
47
 
48
- = 0.6.1 =
49
- * fix a few compatibility issues with 4.2
50
 
51
- = 0.7.0 =
52
- * disable modal dialog and use full screen real page when prompting for information
 
 
53
 
54
- = 0.7.1 =
55
- * remove deprecated function
 
 
 
 
 
 
 
 
 
 
 
3
  Donate link: http://sourceforge.net/donate/index.php?group_id=198487
4
  Tags: ssh, sftp
5
  Requires at least: 3.1
6
+ Tested up to: 4.9.1
7
+ Stable tag: 0.7.2
8
 
9
  "SSH SFTP Updater Support" is the easiest way to keep your Wordpress installation up-to-date with SFTP.
10
 
19
 
20
  == Changelog ==
21
 
22
+ = 0.7.2 =
23
+ * update phpseclib to latest version
 
 
 
 
 
 
 
24
 
25
+ = 0.7.1 =
26
+ * remove deprecated function
 
27
 
28
+ = 0.7.0 =
29
+ * disable modal dialog and use full screen real page when prompting for information
 
 
30
 
31
+ = 0.6.1 =
32
+ * fix a few compatibility issues with 4.2
33
 
34
  = 0.6 =
35
  * update phpseclib to latest version
36
  * make plugin work with 4.2's new modal dialog
37
 
38
+ = 0.5 =
39
+ * update phpseclib to latest version
40
 
41
+ = 0.4 =
42
+ * fix an E_NOTICE (thanks, runblip!)
43
+ * make it so keys that are copy / pasted in are saved with HTML5's localStorage (thanks, kkzk!)
44
+ * update phpseclib to latest Git
45
 
46
+ = 0.3 =
47
+ * update phpseclib to latest SVN
48
+ * read file when FTP_PRIKEY is defined (thanks, lkraav!)
49
+
50
+ = 0.2 =
51
+ * recursive deletes weren't working correctly (directories never got deleted - just files)
52
+ * use SFTP for recursive chmod instead of SSH / exec
53
+ * fix plugin for people using custom WP_CONTENT_DIR values (thanks, dd32!)
54
+ * plugin prevented non-SFTP install methods from being used
55
+ * make it so private keys can be uploaded in addition to being copy / pasted
56
+
57
+ = 0.1 =
58
+ * Initial Release
sftp.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: SSH SFTP Updater Support
4
  Plugin URI: http://phpseclib.sourceforge.net/wordpress.htm
5
  Description: Update your Wordpress blog / plugins via SFTP without libssh2
6
- Version: 0.7.1
7
  Author: TerraFrost
8
  Author URI: http://phpseclib.sourceforge.net/
9
  */
3
  Plugin Name: SSH SFTP Updater Support
4
  Plugin URI: http://phpseclib.sourceforge.net/wordpress.htm
5
  Description: Update your Wordpress blog / plugins via SFTP without libssh2
6
+ Version: 0.7.2
7
  Author: TerraFrost
8
  Author URI: http://phpseclib.sourceforge.net/
9
  */