Update phpseclib

This commit is contained in:
Michel Roux 2015-08-13 15:21:19 +02:00
parent c39f3168ee
commit 5fac4abbd7
23 changed files with 2839 additions and 1491 deletions

View File

@ -7,6 +7,10 @@
* *
* PHP versions 4 and 5 * PHP versions 4 and 5
* *
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()} * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
@ -56,7 +60,7 @@
* @category Crypt * @category Crypt
* @package Crypt_AES * @package Crypt_AES
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVIII Jim Wigginton * @copyright 2008 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -107,20 +111,6 @@ define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of AES. * Pure-PHP implementation of AES.
* *
@ -201,7 +191,7 @@ class Crypt_AES extends Crypt_Rijndael
default: default:
$this->key_size = 32; $this->key_size = 32;
} }
$this->_setupEngine(); $this->_setEngine();
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@
* @package Crypt_Blowfish * @package Crypt_Blowfish
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com> * @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -101,20 +101,6 @@ define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_BLOWFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of Blowfish. * Pure-PHP implementation of Blowfish.
* *
@ -174,7 +160,7 @@ class Crypt_Blowfish extends Crypt_Base
/** /**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
* *
* S-Box 1 * S-Box 0
* *
* @access private * @access private
* @var array * @var array
@ -340,7 +326,7 @@ class Crypt_Blowfish extends Crypt_Base
/** /**
* P-Array consists of 18 32-bit subkeys * P-Array consists of 18 32-bit subkeys
* *
* @var array $parray * @var array
* @access private * @access private
*/ */
var $parray = array( var $parray = array(
@ -354,7 +340,7 @@ class Crypt_Blowfish extends Crypt_Base
* *
* Holds the expanded key [p] and the key-depended s-boxes [sb] * Holds the expanded key [p] and the key-depended s-boxes [sb]
* *
* @var array $bctx * @var array
* @access private * @access private
*/ */
var $bctx; var $bctx;
@ -395,6 +381,29 @@ class Crypt_Blowfish extends Crypt_Base
parent::setKey($key); parent::setKey($key);
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
if (strlen($this->key) != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'bf-ecb';
$this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/** /**
* Setup the key (expansion) * Setup the key (expansion)
* *
@ -472,17 +481,17 @@ class Crypt_Blowfish extends Crypt_Base
$r = $in[2]; $r = $in[2];
for ($i = 0; $i < 16; $i+= 2) { for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i]; $l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] + $r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^ $sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) + $sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]; $sb_3[$l & 0xff];
$r^= $p[$i + 1]; $r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] + $l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^ $sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) + $sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]; $sb_3[$r & 0xff];
} }
return pack("N*", $r ^ $p[17], $l ^ $p[16]); return pack("N*", $r ^ $p[17], $l ^ $p[16]);
} }
@ -519,7 +528,6 @@ class Crypt_Blowfish extends Crypt_Base
$sb_2[$r >> 8 & 0xff]) + $sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]; $sb_3[$r & 0xff];
} }
return pack("N*", $r ^ $p[0], $l ^ $p[1]); return pack("N*", $r ^ $p[0], $l ^ $p[1]);
} }
@ -534,15 +542,14 @@ class Crypt_Blowfish extends Crypt_Base
$lambda_functions =& Crypt_Blowfish::_getLambdaFunctions(); $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10); $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) { // Generation of a unique hash for our generated code
case $gen_hi_opt_code: $code_hash = "Crypt_Blowfish, {$this->mode}";
$code_hash = md5(str_pad("Crypt_Blowfish, {$this->mode}, ", 32, "\0") . $this->key); if ($gen_hi_opt_code) {
break; $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
default:
$code_hash = "Crypt_Blowfish, {$this->mode}";
} }
if (!isset($lambda_functions[$code_hash])) { if (!isset($lambda_functions[$code_hash])) {

View File

@ -53,7 +53,7 @@
* @category Crypt * @category Crypt
* @package Crypt_DES * @package Crypt_DES
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -121,20 +121,6 @@ define('CRYPT_DES_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_DES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_DES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of DES. * Pure-PHP implementation of DES.
* *
@ -191,6 +177,21 @@ class Crypt_DES extends Crypt_Base
*/ */
var $cipher_name_mcrypt = 'des'; var $cipher_name_mcrypt = 'des';
/**
* The OpenSSL names of the cipher / modes
*
* @see Crypt_Base::openssl_mode_names
* @var Array
* @access private
*/
var $openssl_mode_names = array(
CRYPT_MODE_ECB => 'des-ecb',
CRYPT_MODE_CBC => 'des-cbc',
CRYPT_MODE_CFB => 'des-cfb',
CRYPT_MODE_OFB => 'des-ofb'
// CRYPT_MODE_CTR is undefined for DES
);
/** /**
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
@ -661,6 +662,28 @@ class Crypt_DES extends Crypt_Base
0x00000820, 0x00020020, 0x08000000, 0x08020800 0x00000820, 0x00020020, 0x08000000, 0x08020800
); );
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($this->key_size_max == 8) {
if ($engine == CRYPT_ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ecb';
$this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
}
}
return parent::isValidEngine($engine);
}
/** /**
* Sets the key. * Sets the key.
* *
@ -1358,21 +1381,20 @@ class Crypt_DES extends Crypt_Base
$des_rounds = $this->des_rounds; $des_rounds = $this->des_rounds;
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
// (Currently, for Crypt_TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
// Generation of a uniqe hash for our generated code // Generation of a uniqe hash for our generated code
switch (true) { $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
case $gen_hi_opt_code: if ($gen_hi_opt_code) {
// For hi-optimized code, we create for each combination of // For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function. // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
$code_hash = md5(str_pad("Crypt_DES, $des_rounds, {$this->mode}, ", 32, "\0") . $this->key); // After max 10 hi-optimized functions, we create generic
break; // (still very fast.. but not ultra) functions for each $mode/$des_rounds
default: // Currently 2 * 5 generic functions will be then max. possible.
// After max 10 hi-optimized functions, we create generic $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
} }
// Is there a re-usable $lambda_functions in there? If not, we have to create it. // Is there a re-usable $lambda_functions in there? If not, we have to create it.
@ -1427,7 +1449,6 @@ class Crypt_DES extends Crypt_Base
// Creating code for en- and decryption. // Creating code for en- and decryption.
$crypt_block = array(); $crypt_block = array();
foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) { foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) {
/* Do the initial IP permutation. */ /* Do the initial IP permutation. */
$crypt_block[$c] = ' $crypt_block[$c] = '
$in = unpack("N*", $in); $in = unpack("N*", $in);

View File

@ -49,7 +49,7 @@
* @category Crypt * @category Crypt
* @package Crypt_Hash * @package Crypt_Hash
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -153,7 +153,7 @@ class Crypt_Hash
*/ */
function Crypt_Hash($hash = 'sha1') function Crypt_Hash($hash = 'sha1')
{ {
if ( !defined('CRYPT_HASH_MODE') ) { if (!defined('CRYPT_HASH_MODE')) {
switch (true) { switch (true) {
case extension_loaded('hash'): case extension_loaded('hash'):
define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH); define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
@ -242,7 +242,7 @@ class Crypt_Hash
$mode = CRYPT_HASH_MODE; $mode = CRYPT_HASH_MODE;
} }
switch ( $mode ) { switch ($mode) {
case CRYPT_HASH_MODE_MHASH: case CRYPT_HASH_MODE_MHASH:
switch ($hash) { switch ($hash) {
case 'md5': case 'md5':
@ -276,26 +276,26 @@ class Crypt_Hash
switch ($hash) { switch ($hash) {
case 'md2': case 'md2':
$this->b = 16; $this->b = 16;
$this->hash = array($this, '_md2'); $this->hash = array($this, '_md2');
break; break;
case 'md5': case 'md5':
$this->b = 64; $this->b = 64;
$this->hash = array($this, '_md5'); $this->hash = array($this, '_md5');
break; break;
case 'sha256': case 'sha256':
$this->b = 64; $this->b = 64;
$this->hash = array($this, '_sha256'); $this->hash = array($this, '_sha256');
break; break;
case 'sha384': case 'sha384':
case 'sha512': case 'sha512':
$this->b = 128; $this->b = 128;
$this->hash = array($this, '_sha512'); $this->hash = array($this, '_sha512');
break; break;
case 'sha1': case 'sha1':
default: default:
$this->b = 64; $this->b = 64;
$this->hash = array($this, '_sha1'); $this->hash = array($this, '_sha1');
} }
$this->ipad = str_repeat(chr(0x36), $this->b); $this->ipad = str_repeat(chr(0x36), $this->b);
@ -314,7 +314,7 @@ class Crypt_Hash
$mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
if (!empty($this->key) || is_string($this->key)) { if (!empty($this->key) || is_string($this->key)) {
switch ( $mode ) { switch ($mode) {
case CRYPT_HASH_MODE_MHASH: case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text, $this->key); $output = mhash($this->hash, $text, $this->key);
break; break;
@ -337,7 +337,7 @@ class Crypt_Hash
$output = call_user_func($this->hash, $output); // step 7 $output = call_user_func($this->hash, $output); // step 7
} }
} else { } else {
switch ( $mode ) { switch ($mode) {
case CRYPT_HASH_MODE_MHASH: case CRYPT_HASH_MODE_MHASH:
$output = mhash($this->hash, $text); $output = mhash($this->hash, $text);
break; break;
@ -511,12 +511,14 @@ class Crypt_Hash
// Extend the sixteen 32-bit words into sixty-four 32-bit words // Extend the sixteen 32-bit words into sixty-four 32-bit words
for ($i = 16; $i < 64; $i++) { for ($i = 16; $i < 64; $i++) {
// @codingStandardsIgnoreStart
$s0 = $this->_rightRotate($w[$i - 15], 7) ^ $s0 = $this->_rightRotate($w[$i - 15], 7) ^
$this->_rightRotate($w[$i - 15], 18) ^ $this->_rightRotate($w[$i - 15], 18) ^
$this->_rightShift( $w[$i - 15], 3); $this->_rightShift( $w[$i - 15], 3);
$s1 = $this->_rightRotate($w[$i - 2], 17) ^ $s1 = $this->_rightRotate($w[$i - 2], 17) ^
$this->_rightRotate($w[$i - 2], 19) ^ $this->_rightRotate($w[$i - 2], 19) ^
$this->_rightShift( $w[$i - 2], 10); $this->_rightShift( $w[$i - 2], 10);
// @codingStandardsIgnoreEnd
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
} }

View File

@ -99,20 +99,6 @@ define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_RC2::Crypt_RC2()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC2_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of RC2. * Pure-PHP implementation of RC2.
* *
@ -138,7 +124,19 @@ class Crypt_RC2 extends Crypt_Base
* @var String * @var String
* @access private * @access private
*/ */
var $key = "\0"; var $key;
/**
* The Original (unpadded) Key
*
* @see Crypt_Base::key
* @see setKey()
* @see encrypt()
* @see decrypt()
* @var String
* @access private
*/
var $orig_key;
/** /**
* The default password key_size used by setPassword() * The default password key_size used by setPassword()
@ -189,6 +187,17 @@ class Crypt_RC2 extends Crypt_Base
*/ */
var $default_key_length = 1024; var $default_key_length = 1024;
/**
* The key length in bits.
*
* @see Crypt_RC2::isValidEnine()
* @see Crypt_RC2::setKey()
* @var Integer
* @access private
* @internal Should be in range [1..1024].
*/
var $current_key_length;
/** /**
* The Key Schedule * The Key Schedule
* *
@ -341,7 +350,30 @@ class Crypt_RC2 extends Crypt_Base
function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC) function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC)
{ {
parent::Crypt_Base($mode); parent::Crypt_Base($mode);
$this->setKey(''); }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'rc2-ecb';
$this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
} }
/** /**
@ -375,15 +407,18 @@ class Crypt_RC2 extends Crypt_Base
* @see Crypt_Base::setKey() * @see Crypt_Base::setKey()
* @access public * @access public
* @param String $key * @param String $key
* @param Integer $t1 optional Effective key length in bits. * @param Integer $t1 optional Effective key length in bits.
*/ */
function setKey($key, $t1 = 0) function setKey($key, $t1 = 0)
{ {
$this->orig_key = $key;
if ($t1 <= 0) { if ($t1 <= 0) {
$t1 = $this->default_key_length; $t1 = $this->default_key_length;
} else if ($t1 > 1024) { } elseif ($t1 > 1024) {
$t1 = 1024; $t1 = 1024;
} }
$this->current_key_length = $t1;
// Key byte count should be 1..128. // Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128) : "\x00"; $key = strlen($key) ? substr($key, 0, 128) : "\x00";
$t = strlen($key); $t = strlen($key);
@ -416,6 +451,52 @@ class Crypt_RC2 extends Crypt_Base
parent::setKey(call_user_func_array('pack', $l)); parent::setKey(call_user_func_array('pack', $l));
} }
/**
* Encrypts a message.
*
* Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code
*
* @see decrypt()
* @access public
* @param String $plaintext
* @return String $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine == CRYPT_ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::encrypt($plaintext);
$this->key = $temp;
return $result;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code
*
* @see encrypt()
* @access public
* @param String $ciphertext
* @return String $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine == CRYPT_ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::decrypt($ciphertext);
$this->key = $temp;
return $result;
}
return parent::encrypt($ciphertext);
}
/** /**
* Encrypts a block * Encrypts a block
* *
@ -506,6 +587,21 @@ class Crypt_RC2 extends Crypt_Base
return pack('vvvv', $r0, $r1, $r2, $r3); return pack('vvvv', $r0, $r1, $r2, $r3);
} }
/**
* Setup the CRYPT_ENGINE_MCRYPT $engine
*
* @see Crypt_Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
if (!isset($this->key)) {
$this->setKey('');
}
parent::_setupMcrypt();
}
/** /**
* Creates the key schedule * Creates the key schedule
* *
@ -514,6 +610,10 @@ class Crypt_RC2 extends Crypt_Base
*/ */
function _setupKey() function _setupKey()
{ {
if (!isset($this->key)) {
$this->setKey('');
}
// Key has already been expanded in Crypt_RC2::setKey(): // Key has already been expanded in Crypt_RC2::setKey():
// Only the first value must be altered. // Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key); $l = unpack('Ca/Cb/v*', $this->key);
@ -536,14 +636,14 @@ class Crypt_RC2 extends Crypt_Base
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers // The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster]. // for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10. // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
$keys = $this->keys; // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
if (count($lambda_functions) >= 10) { $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
$code_hash = md5(str_pad("Crypt_RC2, {$this->mode}, ", 32, "\0") . implode(',', $keys)); // Generation of a uniqe hash for our generated code
$code_hash = "Crypt_RC2, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there? // Is there a re-usable $lambda_functions in there?
// If not, we have to create it. // If not, we have to create it.
@ -551,6 +651,16 @@ class Crypt_RC2 extends Crypt_Base
// Init code for both, encrypt and decrypt. // Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;'; $init_crypt = '$keys = $self->keys;';
switch (true) {
case $gen_hi_opt_code:
$keys = $this->keys;
default:
$keys = array();
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// $in is the current 8 bytes block which has to be en/decrypt // $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = ' $encrypt_block = $decrypt_block = '
$in = unpack("v4", $in); $in = unpack("v4", $in);

View File

@ -55,7 +55,7 @@
* @category Crypt * @category Crypt
* @package Crypt_RC4 * @package Crypt_RC4
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -69,20 +69,6 @@ if (!class_exists('Crypt_Base')) {
include_once 'Base.php'; include_once 'Base.php';
} }
/**#@+
* @access private
* @see Crypt_RC4::Crypt_RC4()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**#@+ /**#@+
* @access private * @access private
* @see Crypt_RC4::_crypt() * @see Crypt_RC4::_crypt()
@ -181,6 +167,38 @@ class Crypt_RC4 extends Crypt_Base
parent::Crypt_Base(CRYPT_MODE_STREAM); parent::Crypt_Base(CRYPT_MODE_STREAM);
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
switch (strlen($this->key)) {
case 5:
$this->cipher_name_openssl = 'rc4-40';
break;
case 8:
$this->cipher_name_openssl = 'rc4-64';
break;
case 16:
$this->cipher_name_openssl = 'rc4';
break;
default:
return false;
}
}
return parent::isValidEngine($engine);
}
/** /**
* Dummy function. * Dummy function.
* *
@ -230,7 +248,7 @@ class Crypt_RC4 extends Crypt_Base
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) { if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::encrypt($plaintext); return parent::encrypt($plaintext);
} }
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT); return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
@ -250,7 +268,7 @@ class Crypt_RC4 extends Crypt_Base
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) { if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::decrypt($ciphertext); return parent::decrypt($ciphertext);
} }
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT); return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);

View File

@ -62,7 +62,7 @@
* @category Crypt * @category Crypt
* @package Crypt_RSA * @package Crypt_RSA
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMIX Jim Wigginton * @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -107,6 +107,13 @@ define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
* compatibility with protocols (like SSH-1) written before OAEP's introduction. * compatibility with protocols (like SSH-1) written before OAEP's introduction.
*/ */
define('CRYPT_RSA_ENCRYPTION_PKCS1', 2); define('CRYPT_RSA_ENCRYPTION_PKCS1', 2);
/**
* Do not use any padding
*
* Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
* stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
*/
define('CRYPT_RSA_ENCRYPTION_NONE', 3);
/**#@-*/ /**#@-*/
/**#@+ /**#@+
@ -492,7 +499,7 @@ class Crypt_RSA
$this->configFile = CRYPT_RSA_OPENSSL_CONFIG; $this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
if ( !defined('CRYPT_RSA_MODE') ) { if (!defined('CRYPT_RSA_MODE')) {
switch (true) { switch (true) {
// Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular, // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
// Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
@ -515,9 +522,16 @@ class Crypt_RSA
$versions = array(); $versions = array();
if (!empty($matches[1])) { if (!empty($matches[1])) {
for ($i = 0; $i < count($matches[1]); $i++) { for ($i = 0; $i < count($matches[1]); $i++) {
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i]))); $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
}
// Remove letter part in OpenSSL version
if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
$versions[$matches[1][$i]] = $fullVersion;
} else {
$versions[$matches[1][$i]] = $m[0];
}
}
} }
// it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+ // it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
@ -578,7 +592,7 @@ class Crypt_RSA
} }
// OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
if ( CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) { if (CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) {
$config = array(); $config = array();
if (isset($this->configFile)) { if (isset($this->configFile)) {
$config['config'] = $this->configFile; $config['config'] = $this->configFile;
@ -592,7 +606,8 @@ class Crypt_RSA
$publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1))); $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1)));
// clear the buffer of error strings stemming from a minimalistic openssl.cnf // clear the buffer of error strings stemming from a minimalistic openssl.cnf
while (openssl_error_string() !== false); while (openssl_error_string() !== false) {
}
return array( return array(
'privatekey' => $privatekey, 'privatekey' => $privatekey,
@ -782,19 +797,39 @@ class Crypt_RSA
$encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none'; $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
$key.= $encryption; $key.= $encryption;
$key.= "\r\nComment: " . $this->comment . "\r\n"; $key.= "\r\nComment: " . $this->comment . "\r\n";
$public = pack('Na*Na*Na*', $public = pack(
strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus'] 'Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($raw['publicExponent']),
$raw['publicExponent'],
strlen($raw['modulus']),
$raw['modulus']
); );
$source = pack('Na*Na*Na*Na*', $source = pack(
strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption, 'Na*Na*Na*Na*',
strlen($this->comment), $this->comment, strlen($public), $public strlen('ssh-rsa'),
'ssh-rsa',
strlen($encryption),
$encryption,
strlen($this->comment),
$this->comment,
strlen($public),
$public
); );
$public = base64_encode($public); $public = base64_encode($public);
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
$key.= chunk_split($public, 64); $key.= chunk_split($public, 64);
$private = pack('Na*Na*Na*Na*', $private = pack(
strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'], 'Na*Na*Na*Na*',
strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient'] strlen($raw['privateExponent']),
$raw['privateExponent'],
strlen($raw['prime1']),
$raw['prime1'],
strlen($raw['prime2']),
$raw['prime2'],
strlen($raw['coefficient']),
$raw['coefficient']
); );
if (empty($this->password) && !is_string($this->password)) { if (empty($this->password) && !is_string($this->password)) {
$source.= pack('Na*', strlen($private), $private); $source.= pack('Na*', strlen($private), $private);
@ -861,8 +896,14 @@ class Crypt_RSA
if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) { if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPrivateKey = pack('Ca*a*Ca*a*', $RSAPrivateKey = pack(
CRYPT_RSA_ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey 'Ca*a*Ca*a*',
CRYPT_RSA_ASN1_INTEGER,
"\01\00",
$rsaOID,
4,
$this->_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
); );
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if (!empty($this->password) || is_string($this->password)) { if (!empty($this->password) || is_string($this->password)) {
@ -876,20 +917,35 @@ class Crypt_RSA
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
$RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
$parameters = pack('Ca*a*Ca*N', $parameters = pack(
CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($salt)), $salt, 'Ca*a*Ca*N',
CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(4), $iterationCount CRYPT_RSA_ASN1_OCTETSTRING,
$this->_encodeLength(strlen($salt)),
$salt,
CRYPT_RSA_ASN1_INTEGER,
$this->_encodeLength(4),
$iterationCount
); );
$pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
$encryptionAlgorithm = pack('Ca*a*Ca*a*', $encryptionAlgorithm = pack(
CRYPT_RSA_ASN1_OBJECT, $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), $pbeWithMD5AndDES_CBC, 'Ca*a*Ca*a*',
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($parameters)), $parameters CRYPT_RSA_ASN1_OBJECT,
$this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
$pbeWithMD5AndDES_CBC,
CRYPT_RSA_ASN1_SEQUENCE,
$this->_encodeLength(strlen($parameters)),
$parameters
); );
$RSAPrivateKey = pack('Ca*a*Ca*a*', $RSAPrivateKey = pack(
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($encryptionAlgorithm)), $encryptionAlgorithm, 'Ca*a*Ca*a*',
CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey CRYPT_RSA_ASN1_SEQUENCE,
$this->_encodeLength(strlen($encryptionAlgorithm)),
$encryptionAlgorithm,
CRYPT_RSA_ASN1_OCTETSTRING,
$this->_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
); );
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
@ -976,9 +1032,12 @@ class Crypt_RSA
'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent) 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent)
); );
$RSAPublicKey = pack('Ca*a*a*', $RSAPublicKey = pack(
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), 'Ca*a*a*',
$components['modulus'], $components['publicExponent'] CRYPT_RSA_ASN1_SEQUENCE,
$this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
); );
if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) { if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
@ -991,8 +1050,11 @@ class Crypt_RSA
$RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(0) . $RSAPublicKey;
$RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
$RSAPublicKey = pack('Ca*a*', $RSAPublicKey = pack(
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey 'Ca*a*',
CRYPT_RSA_ASN1_SEQUENCE,
$this->_encodeLength(strlen($rsaOID . $RSAPublicKey)),
$rsaOID . $RSAPublicKey
); );
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@ -1765,6 +1827,41 @@ class Crypt_RSA
return $temp; return $temp;
} }
/**
* Returns the public key's fingerprint
*
* The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
* no public key currently loaded, false is returned.
* Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
*
* @access public
* @param String $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
* for invalid values.
*/
public function getPublicKeyFingerprint($algorithm = 'md5')
{
if (empty($this->modulus) || empty($this->publicExponent)) {
return false;
}
$modulus = $this->modulus->toBytes(true);
$publicExponent = $this->publicExponent->toBytes(true);
$RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
switch ($algorithm) {
case 'sha256':
$hash = new Crypt_Hash('sha256');
$base = base64_encode($hash->hash($RSAPublicKey));
return substr($base, 0, strlen($base) - 1);
case 'md5':
return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1);
default:
return false;
}
}
/** /**
* Returns the private key * Returns the private key
* *
@ -1878,7 +1975,7 @@ class Crypt_RSA
function _decodeLength(&$string) function _decodeLength(&$string)
{ {
$length = ord($this->_string_shift($string)); $length = ord($this->_string_shift($string));
if ( $length & 0x80 ) { // definite length, long form if ($length & 0x80) { // definite length, long form
$length&= 0x7F; $length&= 0x7F;
$temp = $this->_string_shift($string, $length); $temp = $this->_string_shift($string, $length);
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
@ -2401,6 +2498,22 @@ class Crypt_RSA
return substr($m, 1); return substr($m, 1);
} }
/**
* Raw Encryption / Decryption
*
* Doesn't use padding and is not recommended.
*
* @access private
* @param String $m
* @return String
*/
function _raw_encrypt($m)
{
$temp = $this->_os2ip($m);
$temp = $this->_rsaep($temp);
return $this->_i2osp($temp, $this->k);
}
/** /**
* RSAES-PKCS1-V1_5-ENCRYPT * RSAES-PKCS1-V1_5-ENCRYPT
* *
@ -2524,7 +2637,7 @@ class Crypt_RSA
// be output. // be output.
$emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8)
$sLen = $this->sLen == false ? $this->hLen : $this->sLen; $sLen = $this->sLen === false ? $this->hLen : $this->sLen;
$mHash = $this->hash->hash($m); $mHash = $this->hash->hash($m);
if ($emLen < $this->hLen + $sLen + 2) { if ($emLen < $this->hLen + $sLen + 2) {
@ -2562,7 +2675,7 @@ class Crypt_RSA
// be output. // be output.
$emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8);
$sLen = $this->sLen == false ? $this->hLen : $this->sLen; $sLen = $this->sLen === false ? $this->hLen : $this->sLen;
$mHash = $this->hash->hash($m); $mHash = $this->hash->hash($m);
if ($emLen < $this->hLen + $sLen + 2) { if ($emLen < $this->hLen + $sLen + 2) {
@ -2847,6 +2960,13 @@ class Crypt_RSA
function encrypt($plaintext) function encrypt($plaintext)
{ {
switch ($this->encryptionMode) { switch ($this->encryptionMode) {
case CRYPT_RSA_ENCRYPTION_NONE:
$plaintext = str_split($plaintext, $this->k);
$ciphertext = '';
foreach ($plaintext as $m) {
$ciphertext.= $this->_raw_encrypt($m);
}
return $ciphertext;
case CRYPT_RSA_ENCRYPTION_PKCS1: case CRYPT_RSA_ENCRYPTION_PKCS1:
$length = $this->k - 11; $length = $this->k - 11;
if ($length <= 0) { if ($length <= 0) {
@ -2895,6 +3015,9 @@ class Crypt_RSA
$plaintext = ''; $plaintext = '';
switch ($this->encryptionMode) { switch ($this->encryptionMode) {
case CRYPT_RSA_ENCRYPTION_NONE:
$decrypt = '_raw_encrypt';
break;
case CRYPT_RSA_ENCRYPTION_PKCS1: case CRYPT_RSA_ENCRYPTION_PKCS1:
$decrypt = '_rsaes_pkcs1_v1_5_decrypt'; $decrypt = '_rsaes_pkcs1_v1_5_decrypt';
break; break;

View File

@ -38,7 +38,7 @@
* @category Crypt * @category Crypt
* @package Crypt_Random * @package Crypt_Random
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -171,9 +171,9 @@ if (!function_exists('crypt_random_string')) {
ini_set('session.use_cookies', $old_use_cookies); ini_set('session.use_cookies', $old_use_cookies);
session_cache_limiter($old_session_cache_limiter); session_cache_limiter($old_session_cache_limiter);
} else { } else {
if ($_OLD_SESSION !== false) { if ($_OLD_SESSION !== false) {
$_SESSION = $_OLD_SESSION; $_SESSION = $_OLD_SESSION;
unset($_OLD_SESSION); unset($_OLD_SESSION);
} else { } else {
unset($_SESSION); unset($_SESSION);
} }

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@
* @category Crypt * @category Crypt
* @package Crypt_TripleDES * @package Crypt_TripleDES
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -59,19 +59,31 @@ if (!class_exists('Crypt_DES')) {
include_once 'DES.php'; include_once 'DES.php';
} }
/**#@+
* @access public
* @see Crypt_TripleDES::Crypt_TripleDES()
*/
/** /**
* Encrypt / decrypt using inner chaining * Encrypt / decrypt using inner chaining
* *
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3). * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
*/ */
define('CRYPT_MODE_3CBC', -2);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_3CBC', -2); define('CRYPT_DES_MODE_3CBC', -2);
/** /**
* Encrypt / decrypt using outer chaining * Encrypt / decrypt using outer chaining
* *
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC. * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
*/ */
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC); define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
/**#@-*/
/** /**
* Pure-PHP implementation of Triple DES. * Pure-PHP implementation of Triple DES.
@ -186,20 +198,20 @@ class Crypt_TripleDES extends Crypt_DES
* @param optional Integer $mode * @param optional Integer $mode
* @access public * @access public
*/ */
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC) function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
{ {
switch ($mode) { switch ($mode) {
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC // In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC // and additional flag us internally as 3CBC
case CRYPT_DES_MODE_3CBC: case CRYPT_DES_MODE_3CBC:
parent::Crypt_Base(CRYPT_DES_MODE_CBC); parent::Crypt_Base(CRYPT_MODE_CBC);
$this->mode_3cbc = true; $this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits) // This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array( $this->des = array(
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
); );
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
@ -213,6 +225,27 @@ class Crypt_TripleDES extends Crypt_DES
} }
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/** /**
* Sets the initialization vector. (optional) * Sets the initialization vector. (optional)
* *
@ -255,7 +288,7 @@ class Crypt_TripleDES extends Crypt_DES
$key = str_pad(substr($key, 0, 24), 24, chr(0)); $key = str_pad(substr($key, 0, 24), 24, chr(0));
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this: // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
// http://php.net/function.mcrypt-encrypt#47973 // http://php.net/function.mcrypt-encrypt#47973
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24); $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else { } else {
$key = str_pad($key, 8, chr(0)); $key = str_pad($key, 8, chr(0));
} }
@ -283,7 +316,7 @@ class Crypt_TripleDES extends Crypt_DES
function encrypt($plaintext) function encrypt($plaintext)
{ {
// parent::en/decrypt() is able to do all the work for all modes and keylengths, // parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: CRYPT_DES_MODE_3CBC (inner chaining CBC) with a key > 64bits // except for: CRYPT_MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do // if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) { if ($this->mode_3cbc && strlen($this->key) > 8) {
@ -425,4 +458,24 @@ class Crypt_TripleDES extends Crypt_DES
// setup our key // setup our key
parent::_setupKey(); parent::_setupKey();
} }
/**
* Sets the internal crypt engine
*
* @see Crypt_Base::Crypt_Base()
* @see Crypt_Base::setPreferredEngine()
* @param Integer $engine
* @access public
* @return Integer
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
} }

View File

@ -48,7 +48,7 @@
* @package Crypt_Twofish * @package Crypt_Twofish
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com> * @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -101,20 +101,6 @@ define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_TWOFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of Twofish. * Pure-PHP implementation of Twofish.
* *
@ -618,7 +604,9 @@ class Crypt_Twofish extends Crypt_Base
$u^= 0x7fffffff & ($t >> 1); $u^= 0x7fffffff & ($t >> 1);
// Add the modular polynomial on underflow. // Add the modular polynomial on underflow.
if ($t & 0x01) $u^= 0xa6 ; if ($t & 0x01) {
$u^= 0xa6 ;
}
// Remove t * (a + 1/a) * (x^3 + x). // Remove t * (a + 1/a) * (x^3 + x).
$B^= ($u << 24) | ($u << 8); $B^= ($u << 24) | ($u << 8);
@ -754,21 +742,19 @@ class Crypt_Twofish extends Crypt_Base
$lambda_functions =& Crypt_Twofish::_getLambdaFunctions(); $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one. // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) { // Generation of a uniqe hash for our generated code
case $gen_hi_opt_code: $code_hash = "Crypt_Twofish, {$this->mode}";
$code_hash = md5(str_pad("Crypt_Twofish, {$this->mode}, ", 32, "\0") . $this->key); if ($gen_hi_opt_code) {
break; $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
default:
$code_hash = "Crypt_Twofish, {$this->mode}";
} }
if (!isset($lambda_functions[$code_hash])) { if (!isset($lambda_functions[$code_hash])) {
switch (true) { switch (true) {
case $gen_hi_opt_code: case $gen_hi_opt_code:
$K = $this->K; $K = $this->K;
$init_crypt = ' $init_crypt = '
static $S0, $S1, $S2, $S3; static $S0, $S1, $S2, $S3;
if (!$S0) { if (!$S0) {
@ -786,7 +772,6 @@ class Crypt_Twofish extends Crypt_Base
for ($i = 0; $i < 40; ++$i) { for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i; $K[] = '$K_' . $i;
} }
$init_crypt = ' $init_crypt = '
$S0 = $self->S0; $S0 = $self->S0;
$S1 = $self->S1; $S1 = $self->S1;

View File

@ -31,7 +31,7 @@
* @category File * @category File
* @package File_ANSI * @package File_ANSI
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -117,6 +117,22 @@ class File_ANSI
*/ */
var $old_y; var $old_y;
/**
* An empty attribute cell
*
* @var Object
* @access private
*/
var $base_attr_cell;
/**
* The current attribute cell
*
* @var Object
* @access private
*/
var $attr_cell;
/** /**
* An empty attribute row * An empty attribute row
* *
@ -141,62 +157,6 @@ class File_ANSI
*/ */
var $attrs; var $attrs;
/**
* The current foreground color
*
* @var String
* @access private
*/
var $foreground;
/**
* The current background color
*
* @var String
* @access private
*/
var $background;
/**
* Bold flag
*
* @var Boolean
* @access private
*/
var $bold;
/**
* Underline flag
*
* @var Boolean
* @access private
*/
var $underline;
/**
* Blink flag
*
* @var Boolean
* @access private
*/
var $blink;
/**
* Reverse flag
*
* @var Boolean
* @access private
*/
var $reverse;
/**
* Color flag
*
* @var Boolean
* @access private
*/
var $color;
/** /**
* Current ANSI code * Current ANSI code
* *
@ -205,6 +165,14 @@ class File_ANSI
*/ */
var $ansi; var $ansi;
/**
* Tokenization
*
* @var Array
* @access private
*/
var $tokenization;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -213,6 +181,16 @@ class File_ANSI
*/ */
function File_ANSI() function File_ANSI()
{ {
$attr_cell = new stdClass();
$attr_cell->bold = false;
$attr_cell->underline = false;
$attr_cell->blink = false;
$attr_cell->background = 'black';
$attr_cell->foreground = 'white';
$attr_cell->reverse = false;
$this->base_attr_cell = clone($attr_cell);
$this->attr_cell = clone($attr_cell);
$this->setHistory(200); $this->setHistory(200);
$this->setDimensions(80, 24); $this->setDimensions(80, 24);
} }
@ -232,17 +210,9 @@ class File_ANSI
$this->max_y = $y - 1; $this->max_y = $y - 1;
$this->x = $this->y = 0; $this->x = $this->y = 0;
$this->history = $this->history_attrs = array(); $this->history = $this->history_attrs = array();
$this->attr_row = array_fill(0, $this->max_x + 1, ''); $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
$this->screen = array_fill(0, $this->max_y + 1, ''); $this->screen = array_fill(0, $this->max_y + 1, '');
$this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row); $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
$this->foreground = 'white';
$this->background = 'black';
$this->bold = false;
$this->underline = false;
$this->blink = false;
$this->reverse = false;
$this->color = false;
$this->ansi = ''; $this->ansi = '';
} }
@ -278,6 +248,7 @@ class File_ANSI
*/ */
function appendString($source) function appendString($source)
{ {
$this->tokenization = array('');
for ($i = 0; $i < strlen($source); $i++) { for ($i = 0; $i < strlen($source); $i++) {
if (strlen($this->ansi)) { if (strlen($this->ansi)) {
$this->ansi.= $source[$i]; $this->ansi.= $source[$i];
@ -294,6 +265,8 @@ class File_ANSI
default: default:
continue 2; continue 2;
} }
$this->tokenization[] = $this->ansi;
$this->tokenization[] = '';
// http://ascii-table.com/ansi-escape-sequences-vt-100.php // http://ascii-table.com/ansi-escape-sequences-vt-100.php
switch ($this->ansi) { switch ($this->ansi) {
case "\x1B[H": // Move cursor to upper left corner case "\x1B[H": // Move cursor to upper left corner
@ -315,7 +288,7 @@ class File_ANSI
case "\x1B[K": // Clear screen from cursor right case "\x1B[K": // Clear screen from cursor right
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
array_splice($this->attrs[$this->y], $this->x + 1); array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
break; break;
case "\x1B[2K": // Clear entire line case "\x1B[2K": // Clear entire line
$this->screen[$this->y] = str_repeat(' ', $this->x); $this->screen[$this->y] = str_repeat(' ', $this->x);
@ -323,6 +296,7 @@ class File_ANSI
break; break;
case "\x1B[?1h": // set cursor key to application case "\x1B[?1h": // set cursor key to application
case "\x1B[?25h": // show the cursor case "\x1B[?25h": // show the cursor
case "\x1B(B": // set united states g0 character set
break; break;
case "\x1BE": // Move to next line case "\x1BE": // Move to next line
$this->_newLine(); $this->_newLine();
@ -330,6 +304,10 @@ class File_ANSI
break; break;
default: default:
switch (true) { switch (true) {
case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
$this->old_y = $this->y;
$this->y+= $match[1];
break;
case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
$this->old_x = $this->x; $this->old_x = $this->x;
$this->old_y = $this->y; $this->old_y = $this->y;
@ -338,65 +316,44 @@ class File_ANSI
break; break;
case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
$this->old_x = $this->x; $this->old_x = $this->x;
$x = $match[1] - 1; $this->x+= $match[1];
break;
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
$this->old_x = $this->x;
$this->x-= $match[1];
break; break;
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
break; break;
case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
$attr_cell = &$this->attr_cell;
$mods = explode(';', $match[1]); $mods = explode(';', $match[1]);
foreach ($mods as $mod) { foreach ($mods as $mod) {
switch ($mod) { switch ($mod) {
case 0: // Turn off character attributes case 0: // Turn off character attributes
$this->attrs[$this->y][$this->x] = ''; $attr_cell = clone($this->base_attr_cell);
if ($this->bold) $this->attrs[$this->y][$this->x].= '</b>';
if ($this->underline) $this->attrs[$this->y][$this->x].= '</u>';
if ($this->blink) $this->attrs[$this->y][$this->x].= '</blink>';
if ($this->color) $this->attrs[$this->y][$this->x].= '</span>';
if ($this->reverse) {
$temp = $this->background;
$this->background = $this->foreground;
$this->foreground = $temp;
}
$this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false;
break; break;
case 1: // Turn bold mode on case 1: // Turn bold mode on
if (!$this->bold) { $attr_cell->bold = true;
$this->attrs[$this->y][$this->x] = '<b>';
$this->bold = true;
}
break; break;
case 4: // Turn underline mode on case 4: // Turn underline mode on
if (!$this->underline) { $attr_cell->underline = true;
$this->attrs[$this->y][$this->x] = '<u>';
$this->underline = true;
}
break; break;
case 5: // Turn blinking mode on case 5: // Turn blinking mode on
if (!$this->blink) { $attr_cell->blink = true;
$this->attrs[$this->y][$this->x] = '<blink>';
$this->blink = true;
}
break; break;
case 7: // Turn reverse video on case 7: // Turn reverse video on
$this->reverse = !$this->reverse; $attr_cell->reverse = !$attr_cell->reverse;
$temp = $this->background; $temp = $attr_cell->background;
$this->background = $this->foreground; $attr_cell->background = $attr_cell->foreground;
$this->foreground = $temp; $attr_cell->foreground = $temp;
$this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
if ($this->color) {
$this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
}
$this->color = true;
break; break;
default: // set colors default: // set colors
//$front = $this->reverse ? &$this->background : &$this->foreground; //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
$front = &$this->{ $this->reverse ? 'background' : 'foreground' }; $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
//$back = $this->reverse ? &$this->foreground : &$this->background; //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
$back = &$this->{ $this->reverse ? 'foreground' : 'background' }; $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
switch ($mod) { switch ($mod) {
// @codingStandardsIgnoreStart
case 30: $front = 'black'; break; case 30: $front = 'black'; break;
case 31: $front = 'red'; break; case 31: $front = 'red'; break;
case 32: $front = 'green'; break; case 32: $front = 'green'; break;
@ -414,30 +371,25 @@ class File_ANSI
case 45: $back = 'magenta'; break; case 45: $back = 'magenta'; break;
case 46: $back = 'cyan'; break; case 46: $back = 'cyan'; break;
case 47: $back = 'white'; break; case 47: $back = 'white'; break;
// @codingStandardsIgnoreEnd
default: default:
user_error('Unsupported attribute: ' . $mod); //user_error('Unsupported attribute: ' . $mod);
$this->ansi = ''; $this->ansi = '';
break 2; break 2;
} }
unset($temp);
$this->attrs[$this->y][$this->x] = '<span style="color: ' . $this->foreground . '; background: ' . $this->background . '">';
if ($this->color) {
$this->attrs[$this->y][$this->x] = '</span>' . $this->attrs[$this->y][$this->x];
}
$this->color = true;
} }
} }
break; break;
default: default:
user_error("{$this->ansi} unsupported\r\n"); //user_error("{$this->ansi} is unsupported\r\n");
} }
} }
$this->ansi = ''; $this->ansi = '';
continue; continue;
} }
$this->tokenization[count($this->tokenization) - 1].= $source[$i];
switch ($source[$i]) { switch ($source[$i]) {
case "\r": case "\r":
$this->x = 0; $this->x = 0;
@ -445,12 +397,32 @@ class File_ANSI
case "\n": case "\n":
$this->_newLine(); $this->_newLine();
break; break;
case "\x08": // backspace
if ($this->x) {
$this->x--;
$this->attrs[$this->y][$this->x] = clone($this->base_attr_cell);
$this->screen[$this->y] = substr_replace(
$this->screen[$this->y],
$source[$i],
$this->x,
1
);
}
break;
case "\x0F": // shift case "\x0F": // shift
break; break;
case "\x1B": // start ANSI escape code case "\x1B": // start ANSI escape code
$this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
//if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
// array_pop($this->tokenization);
//}
$this->ansi.= "\x1B"; $this->ansi.= "\x1B";
break; break;
default: default:
$this->attrs[$this->y][$this->x] = clone($this->attr_cell);
if ($this->x > strlen($this->screen[$this->y])) {
$this->screen[$this->y] = str_repeat(' ', $this->x);
}
$this->screen[$this->y] = substr_replace( $this->screen[$this->y] = substr_replace(
$this->screen[$this->y], $this->screen[$this->y],
$source[$i], $source[$i],
@ -498,6 +470,63 @@ class File_ANSI
$this->y++; $this->y++;
} }
/**
* Returns the current coordinate without preformating
*
* @access private
* @return String
*/
function _processCoordinate($last_attr, $cur_attr, $char)
{
$output = '';
if ($last_attr != $cur_attr) {
$close = $open = '';
if ($last_attr->foreground != $cur_attr->foreground) {
if ($cur_attr->foreground != 'white') {
$open.= '<span style="color: ' . $cur_attr->foreground . '">';
}
if ($last_attr->foreground != 'white') {
$close = '</span>' . $close;
}
}
if ($last_attr->background != $cur_attr->background) {
if ($cur_attr->background != 'black') {
$open.= '<span style="background: ' . $cur_attr->background . '">';
}
if ($last_attr->background != 'black') {
$close = '</span>' . $close;
}
}
if ($last_attr->bold != $cur_attr->bold) {
if ($cur_attr->bold) {
$open.= '<b>';
} else {
$close = '</b>' . $close;
}
}
if ($last_attr->underline != $cur_attr->underline) {
if ($cur_attr->underline) {
$open.= '<u>';
} else {
$close = '</u>' . $close;
}
}
if ($last_attr->blink != $cur_attr->blink) {
if ($cur_attr->blink) {
$open.= '<blink>';
} else {
$close = '</blink>' . $close;
}
}
$output.= $close . $open;
}
$output.= htmlspecialchars($char);
return $output;
}
/** /**
* Returns the current screen without preformating * Returns the current screen without preformating
* *
@ -507,17 +536,18 @@ class File_ANSI
function _getScreen() function _getScreen()
{ {
$output = ''; $output = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i <= $this->max_y; $i++) { for ($i = 0; $i <= $this->max_y; $i++) {
for ($j = 0; $j <= $this->max_x + 1; $j++) { for ($j = 0; $j <= $this->max_x; $j++) {
if (isset($this->attrs[$i][$j])) { $cur_attr = $this->attrs[$i][$j];
$output.= $this->attrs[$i][$j]; $output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
} $last_attr = $this->attrs[$i][$j];
if (isset($this->screen[$i][$j])) {
$output.= htmlspecialchars($this->screen[$i][$j]);
}
} }
$output.= "\r\n"; $output.= "\r\n";
} }
$output = substr($output, 0, -2);
// close any remaining open tags
$output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
return rtrim($output); return rtrim($output);
} }
@ -529,7 +559,7 @@ class File_ANSI
*/ */
function getScreen() function getScreen()
{ {
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $this->_getScreen() . '</pre>'; return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
} }
/** /**
@ -541,19 +571,20 @@ class File_ANSI
function getHistory() function getHistory()
{ {
$scrollback = ''; $scrollback = '';
$last_attr = $this->base_attr_cell;
for ($i = 0; $i < count($this->history); $i++) { for ($i = 0; $i < count($this->history); $i++) {
for ($j = 0; $j <= $this->max_x + 1; $j++) { for ($j = 0; $j <= $this->max_x + 1; $j++) {
if (isset($this->history_attrs[$i][$j])) { $cur_attr = $this->history_attrs[$i][$j];
$scrollback.= $this->history_attrs[$i][$j]; $scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
} $last_attr = $this->history_attrs[$i][$j];
if (isset($this->history[$i][$j])) {
$scrollback.= htmlspecialchars($this->history[$i][$j]);
}
} }
$scrollback.= "\r\n"; $scrollback.= "\r\n";
} }
$base_attr_cell = $this->base_attr_cell;
$this->base_attr_cell = $last_attr;
$scrollback.= $this->_getScreen(); $scrollback.= $this->_getScreen();
$this->base_attr_cell = $base_attr_cell;
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>'; return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
} }
} }

View File

@ -34,7 +34,7 @@
* @category File * @category File
* @package File_ASN1 * @package File_ASN1
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -306,17 +306,17 @@ class File_ASN1
$tag <<= 7; $tag <<= 7;
$tag |= ord($this->_string_shift($encoded)) & 0x7F; $tag |= ord($this->_string_shift($encoded)) & 0x7F;
$start++; $start++;
} while ( $loop ); } while ($loop);
} }
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13 // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
$length = ord($this->_string_shift($encoded)); $length = ord($this->_string_shift($encoded));
$start++; $start++;
if ( $length == 0x80 ) { // indefinite length if ($length == 0x80) { // indefinite length
// "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
// immediately available." -- paragraph 8.1.3.2.c // immediately available." -- paragraph 8.1.3.2.c
$length = strlen($encoded); $length = strlen($encoded);
} elseif ( $length & 0x80 ) { // definite length, long form } elseif ($length & 0x80) { // definite length, long form
// technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
// support it up to four. // support it up to four.
$length&= 0x7F; $length&= 0x7F;
@ -329,6 +329,10 @@ class File_ASN1
$current+= array('headerlength' => 2); $current+= array('headerlength' => 2);
} }
if ($length > strlen($encoded)) {
return false;
}
$content = $this->_string_shift($encoded, $length); $content = $this->_string_shift($encoded, $length);
// at this point $length can be overwritten. it's only accurate for definite length things as is // at this point $length can be overwritten. it's only accurate for definite length things as is
@ -347,19 +351,38 @@ class File_ASN1
case FILE_ASN1_CLASS_APPLICATION: case FILE_ASN1_CLASS_APPLICATION:
case FILE_ASN1_CLASS_PRIVATE: case FILE_ASN1_CLASS_PRIVATE:
case FILE_ASN1_CLASS_CONTEXT_SPECIFIC: case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
$newcontent = $this->_decode_ber($content, $start); if (!$constructed) {
$length = $newcontent['length']; return array(
if (substr($content, $length, 2) == "\0\0") { 'type' => $class,
$length+= 2; 'constant' => $tag,
'content' => $content,
'length' => $length + $start - $current['start']
);
} }
$start+= $length; $newcontent = array();
$remainingLength = $length;
while ($remainingLength > 0) {
$temp = $this->_decode_ber($content, $start);
$length = $temp['length'];
// end-of-content octets - see paragraph 8.1.5
if (substr($content, $length, 2) == "\0\0") {
$length+= 2;
$start+= $length;
$newcontent[] = $temp;
break;
}
$start+= $length;
$remainingLength-= $length;
$newcontent[] = $temp;
$this->_string_shift($content, $length);
}
return array( return array(
'type' => $class, 'type' => $class,
'constant' => $tag, 'constant' => $tag,
// the array encapsulation is for BC with the old format // the array encapsulation is for BC with the old format
'content' => array($newcontent), 'content' => $newcontent,
// the only time when $content['headerlength'] isn't defined is when the length is indefinite. // the only time when $content['headerlength'] isn't defined is when the length is indefinite.
// the absence of $content['headerlength'] is how we know if something is indefinite or not. // the absence of $content['headerlength'] is how we know if something is indefinite or not.
// technically, it could be defined to be 2 and then another indicator could be used but whatever. // technically, it could be defined to be 2 and then another indicator could be used but whatever.
@ -874,7 +897,7 @@ class File_ASN1
} }
foreach ($mapping['children'] as $key => $child) { foreach ($mapping['children'] as $key => $child) {
if (!isset($source[$key])) { if (!array_key_exists($key, $source)) {
if (!isset($child['optional'])) { if (!isset($child['optional'])) {
return false; return false;
} }
@ -1065,7 +1088,7 @@ class File_ASN1
if ($outtype !== false) { if ($outtype !== false) {
return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special); return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
} }
} }
$filters = $this->filters; $filters = $this->filters;
foreach ($loc as $part) { foreach ($loc as $part) {

View File

@ -37,7 +37,7 @@
* @category File * @category File
* @package File_X509 * @package File_X509
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright 2012 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -1505,6 +1505,16 @@ class File_X509
case 'rsaEncryption': case 'rsaEncryption':
$cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']))); = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
/* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier."
-- https://tools.ietf.org/html/rfc3279#section-2.3.1
given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank,
it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever.
*/
$cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null;
// https://tools.ietf.org/html/rfc3279#section-2.2.1
$cert['signatureAlgorithm']['parameters'] = null;
$cert['tbsCertificate']['signature']['parameters'] = null;
} }
} }
@ -1589,7 +1599,7 @@ class File_X509
} }
} }
} }
} elseif ($map) { } else {
$value = base64_encode($value); $value = base64_encode($value);
} }
} }
@ -1612,6 +1622,10 @@ class File_X509
if (is_array($extensions)) { if (is_array($extensions)) {
$size = count($extensions); $size = count($extensions);
for ($i = 0; $i < $size; $i++) { for ($i = 0; $i < $size; $i++) {
if (is_object($extensions[$i]) && strtolower(get_class($extensions[$i])) == 'file_asn1_element') {
continue;
}
$id = $extensions[$i]['extnId']; $id = $extensions[$i]['extnId'];
$value = &$extensions[$i]['extnValue']; $value = &$extensions[$i]['extnValue'];
@ -2509,7 +2523,7 @@ class File_X509
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$result = ''; $result = '';
foreach ($dn['rdnSequence'] as $rdn) { foreach ($dn['rdnSequence'] as $rdn) {
foreach ($rdn as $i=>$attr) { foreach ($rdn as $i => $attr) {
$attr = &$rdn[$i]; $attr = &$rdn[$i];
if (is_array($attr['value'])) { if (is_array($attr['value'])) {
foreach ($attr['value'] as $type => $v) { foreach ($attr['value'] as $type => $v) {
@ -2576,7 +2590,7 @@ class File_X509
break; break;
default: default:
$delim = '/'; $delim = '/';
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '='; $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '=';
} }
if (!$start) { if (!$start) {
@ -2733,7 +2747,7 @@ class File_X509
break; break;
} }
} }
foreach ($chain as $key=>$value) { foreach ($chain as $key => $value) {
$chain[$key] = new File_X509(); $chain[$key] = new File_X509();
$chain[$key]->loadX509($value); $chain[$key]->loadX509($value);
} }
@ -2917,7 +2931,7 @@ class File_X509
switch (true) { switch (true) {
case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')): case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']); case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
break; break;
default: default:
switch ($algorithm) { switch ($algorithm) {
@ -3044,7 +3058,7 @@ class File_X509
$algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm'); $algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
switch (true) { switch (true) {
case !$algorithm: case !$algorithm:
case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']); case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
break; break;
default: default:
switch ($algorithm) { switch ($algorithm) {
@ -3198,9 +3212,9 @@ class File_X509
{ {
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this $year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
if ($year < 2050) { if ($year < 2050) {
return array('utcTime' => $date); return array('utcTime' => $date);
} else { } else {
return array('generalTime' => $date); return array('generalTime' => $date);
} }
} }
@ -3254,7 +3268,7 @@ class File_X509
if (isset($subject->domains)) { if (isset($subject->domains)) {
$this->removeExtension('id-ce-subjectAltName'); $this->removeExtension('id-ce-subjectAltName');
} }
} else if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) { } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
return false; return false;
} else { } else {
if (!isset($subject->publicKey)) { if (!isset($subject->publicKey)) {
@ -3263,7 +3277,21 @@ class File_X509
$startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O'); $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
$endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year')); $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M Y H:i:s O', strtotime('+1 year'));
$serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger(); if (!empty($this->serialNumber)) {
$serialNumber = $this->serialNumber;
} else {
if (!function_exists('crypt_random_string')) {
include_once 'Crypt/Random.php';
}
/* "The serial number MUST be a positive integer"
"Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
-- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
for the integer to be positive the leading bit needs to be 0 hence the
application of a bitmap
*/
$serialNumber = new Math_BigInteger(crypt_random_string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256);
}
$this->currentCert = array( $this->currentCert = array(
'tbsCertificate' => 'tbsCertificate' =>
@ -3279,8 +3307,8 @@ class File_X509
'subject' => $subject->dn, 'subject' => $subject->dn,
'subjectPublicKeyInfo' => $subjectPublicKey 'subjectPublicKeyInfo' => $subjectPublicKey
), ),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later 'signature' => false // this is going to be overwritten later
); );
// Copy extensions from CSR. // Copy extensions from CSR.
@ -3301,8 +3329,7 @@ class File_X509
// ) // )
//), //),
'keyIdentifier' => $issuer->currentKeyIdentifier 'keyIdentifier' => $issuer->currentKeyIdentifier
) ));
);
//$extensions = &$this->currentCert['tbsCertificate']['extensions']; //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
//if (isset($issuer->serialNumber)) { //if (isset($issuer->serialNumber)) {
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
@ -3345,7 +3372,8 @@ class File_X509
$keyUsage = array(); $keyUsage = array();
} }
$this->setExtension('id-ce-keyUsage', $this->setExtension(
'id-ce-keyUsage',
array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign')))) array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))
); );
@ -3354,8 +3382,11 @@ class File_X509
$basicConstraints = array(); $basicConstraints = array();
} }
$this->setExtension('id-ce-basicConstraints', $this->setExtension(
array_unique(array_merge(array('cA' => true), $basicConstraints)), true); 'id-ce-basicConstraints',
array_unique(array_merge(array('cA' => true), $basicConstraints)),
true
);
if (!isset($subject->currentKeyIdentifier)) { if (!isset($subject->currentKeyIdentifier)) {
$this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false); $this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
@ -3415,8 +3446,8 @@ class File_X509
'subject' => $this->dn, 'subject' => $this->dn,
'subjectPKInfo' => $publicKey 'subjectPKInfo' => $publicKey
), ),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later 'signature' => false // this is going to be overwritten later
); );
} }
@ -3480,8 +3511,8 @@ class File_X509
// crypt_random_string(8) & str_repeat("\x7F", 8) // crypt_random_string(8) & str_repeat("\x7F", 8)
'challenge' => !empty($this->challenge) ? $this->challenge : '' 'challenge' => !empty($this->challenge) ? $this->challenge : ''
), ),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later 'signature' => false // this is going to be overwritten later
); );
} }
@ -3533,8 +3564,8 @@ class File_X509
'issuer' => false, // this is going to be overwritten later 'issuer' => false, // this is going to be overwritten later
'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate() 'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
), ),
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm), 'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
'signature' => false // this is going to be overwritten later 'signature' => false // this is going to be overwritten later
); );
} }
@ -3552,6 +3583,11 @@ class File_X509
$crlNumber = $this->serialNumber; $crlNumber = $this->serialNumber;
} else { } else {
$crlNumber = $this->getExtension('id-ce-cRLNumber'); $crlNumber = $this->getExtension('id-ce-cRLNumber');
// "The CRL number is a non-critical CRL extension that conveys a
// monotonically increasing sequence number for a given CRL scope and
// CRL issuer. This extension allows users to easily determine when a
// particular CRL supersedes another CRL."
// -- https://tools.ietf.org/html/rfc5280#section-5.2.3
$crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null; $crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null;
} }
@ -3590,8 +3626,7 @@ class File_X509
// ) // )
//), //),
'keyIdentifier' => $issuer->currentKeyIdentifier 'keyIdentifier' => $issuer->currentKeyIdentifier
) ));
);
//$extensions = &$tbsCertList['crlExtensions']; //$extensions = &$tbsCertList['crlExtensions'];
//if (isset($issuer->serialNumber)) { //if (isset($issuer->serialNumber)) {
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber; // $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
@ -4124,7 +4159,7 @@ class File_X509
case $disposition == FILE_X509_ATTR_APPEND: case $disposition == FILE_X509_ATTR_APPEND:
$last = $key; $last = $key;
break; break;
case $disposition >= $n; case $disposition >= $n:
$disposition -= $n; $disposition -= $n;
break; break;
default: default:
@ -4382,7 +4417,6 @@ class File_X509
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) { if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
if (!empty($date)) { if (!empty($date)) {
$rclist[$i]['revocationDate'] = $this->_timeField($date); $rclist[$i]['revocationDate'] = $this->_timeField($date);
} }
@ -4500,7 +4534,7 @@ class File_X509
if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) { if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) { if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
return $this->_getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions"); return $this->_getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
} }
} }

View File

@ -63,7 +63,7 @@
* @category Math * @category Math
* @package Math_BigInteger * @package Math_BigInteger
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVI Jim Wigginton * @copyright 2006 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://pear.php.net/package/Math_BigInteger * @link http://pear.php.net/package/Math_BigInteger
*/ */
@ -253,7 +253,7 @@ class Math_BigInteger
*/ */
function Math_BigInteger($x = 0, $base = 10) function Math_BigInteger($x = 0, $base = 10)
{ {
if ( !defined('MATH_BIGINTEGER_MODE') ) { if (!defined('MATH_BIGINTEGER_MODE')) {
switch (true) { switch (true) {
case extension_loaded('gmp'): case extension_loaded('gmp'):
define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP); define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
@ -278,7 +278,14 @@ class Math_BigInteger
$versions = array(); $versions = array();
if (!empty($matches[1])) { if (!empty($matches[1])) {
for ($i = 0; $i < count($matches[1]); $i++) { for ($i = 0; $i < count($matches[1]); $i++) {
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i]))); $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
// Remove letter part in OpenSSL version
if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) {
$versions[$matches[1][$i]] = $fullVersion;
} else {
$versions[$matches[1][$i]] = $m[0];
}
} }
} }
@ -327,11 +334,14 @@ class Math_BigInteger
} }
} }
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
if (is_resource($x) && get_resource_type($x) == 'GMP integer') { switch (true) {
$this->value = $x; case is_resource($x) && get_resource_type($x) == 'GMP integer':
return; // PHP 5.6 switched GMP from using resources to objects
case is_object($x) && get_class($x) == 'GMP':
$this->value = $x;
return;
} }
$this->value = gmp_init(0); $this->value = gmp_init(0);
break; break;
@ -354,8 +364,8 @@ class Math_BigInteger
$x = ~$x; $x = ~$x;
$this->is_negative = true; $this->is_negative = true;
} }
case 256: case 256:
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$sign = $this->is_negative ? '-' : ''; $sign = $this->is_negative ? '-' : '';
$this->value = gmp_init($sign . '0x' . bin2hex($x)); $this->value = gmp_init($sign . '0x' . bin2hex($x));
@ -391,7 +401,7 @@ class Math_BigInteger
$this->value = $temp->value; $this->value = $temp->value;
} }
break; break;
case 16: case 16:
case -16: case -16:
if ($base > 0 && $x[0] == '-') { if ($base > 0 && $x[0] == '-') {
$this->is_negative = true; $this->is_negative = true;
@ -406,7 +416,7 @@ class Math_BigInteger
$x = bin2hex(~pack('H*', $x)); $x = bin2hex(~pack('H*', $x));
} }
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = $this->is_negative ? '-0x' . $x : '0x' . $x; $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
$this->value = gmp_init($temp); $this->value = gmp_init($temp);
@ -429,14 +439,14 @@ class Math_BigInteger
$this->value = $temp->value; $this->value = $temp->value;
} }
break; break;
case 10: case 10:
case -10: case -10:
// (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
// (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals) // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
// [^-0-9].*: find any non-numeric characters and then any characters that follow that // [^-0-9].*: find any non-numeric characters and then any characters that follow that
$x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x); $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$this->value = gmp_init($x); $this->value = gmp_init($x);
break; break;
@ -466,7 +476,7 @@ class Math_BigInteger
$this->value = $temp->value; $this->value = $temp->value;
} }
break; break;
case 2: // base-2 support originally implemented by Lluis Pamies - thanks! case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
case -2: case -2:
if ($base > 0 && $x[0] == '-') { if ($base > 0 && $x[0] == '-') {
$this->is_negative = true; $this->is_negative = true;
@ -541,7 +551,7 @@ class Math_BigInteger
return $comparison < 0 ? ~$bytes : $bytes; return $comparison < 0 ? ~$bytes : $bytes;
} }
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
if (gmp_cmp($this->value, gmp_init(0)) == 0) { if (gmp_cmp($this->value, gmp_init(0)) == 0) {
return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
@ -682,7 +692,7 @@ class Math_BigInteger
*/ */
function toString() function toString()
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
return gmp_strval($this->value); return gmp_strval($this->value);
case MATH_BIGINTEGER_MODE_BCMATH: case MATH_BIGINTEGER_MODE_BCMATH:
@ -839,7 +849,7 @@ class Math_BigInteger
*/ */
function add($y) function add($y)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_add($this->value, $y->value); $temp->value = gmp_add($this->value, $y->value);
@ -881,7 +891,7 @@ class Math_BigInteger
MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_VALUE => $y_value,
MATH_BIGINTEGER_SIGN => $y_negative MATH_BIGINTEGER_SIGN => $y_negative
); );
} else if ($y_size == 0) { } elseif ($y_size == 0) {
return array( return array(
MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_VALUE => $x_value,
MATH_BIGINTEGER_SIGN => $x_negative MATH_BIGINTEGER_SIGN => $x_negative
@ -889,8 +899,8 @@ class Math_BigInteger
} }
// subtract, if appropriate // subtract, if appropriate
if ( $x_negative != $y_negative ) { if ($x_negative != $y_negative) {
if ( $x_value == $y_value ) { if ($x_value == $y_value) {
return array( return array(
MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false MATH_BIGINTEGER_SIGN => false
@ -912,7 +922,7 @@ class Math_BigInteger
$value = $x_value; $value = $x_value;
} }
$value[] = 0; // just in case the carry adds an extra digit $value[count($value)] = 0; // just in case the carry adds an extra digit
$carry = 0; $carry = 0;
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
@ -970,7 +980,7 @@ class Math_BigInteger
*/ */
function subtract($y) function subtract($y)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_sub($this->value, $y->value); $temp->value = gmp_sub($this->value, $y->value);
@ -1012,7 +1022,7 @@ class Math_BigInteger
MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_VALUE => $y_value,
MATH_BIGINTEGER_SIGN => !$y_negative MATH_BIGINTEGER_SIGN => !$y_negative
); );
} else if ($y_size == 0) { } elseif ($y_size == 0) {
return array( return array(
MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_VALUE => $x_value,
MATH_BIGINTEGER_SIGN => $x_negative MATH_BIGINTEGER_SIGN => $x_negative
@ -1020,7 +1030,7 @@ class Math_BigInteger
} }
// add, if appropriate (ie. -$x - +$y or +$x - -$y) // add, if appropriate (ie. -$x - +$y or +$x - -$y)
if ( $x_negative != $y_negative ) { if ($x_negative != $y_negative) {
$temp = $this->_add($x_value, false, $y_value, false); $temp = $this->_add($x_value, false, $y_value, false);
$temp[MATH_BIGINTEGER_SIGN] = $x_negative; $temp[MATH_BIGINTEGER_SIGN] = $x_negative;
@ -1029,7 +1039,7 @@ class Math_BigInteger
$diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative);
if ( !$diff ) { if (!$diff) {
return array( return array(
MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false MATH_BIGINTEGER_SIGN => false
@ -1037,7 +1047,7 @@ class Math_BigInteger
} }
// switch $x and $y around, if appropriate. // switch $x and $y around, if appropriate.
if ( (!$x_negative && $diff < 0) || ($x_negative && $diff > 0) ) { if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) {
$temp = $x_value; $temp = $x_value;
$x_value = $y_value; $x_value = $y_value;
$y_value = $temp; $y_value = $temp;
@ -1105,7 +1115,7 @@ class Math_BigInteger
*/ */
function multiply($x) function multiply($x)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_mul($this->value, $x->value); $temp->value = gmp_mul($this->value, $x->value);
@ -1149,7 +1159,7 @@ class Math_BigInteger
$x_length = count($x_value); $x_length = count($x_value);
$y_length = count($y_value); $y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied if (!$x_length || !$y_length) { // a 0 is being multiplied
return array( return array(
MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false MATH_BIGINTEGER_SIGN => false
@ -1179,11 +1189,11 @@ class Math_BigInteger
$x_length = count($x_value); $x_length = count($x_value);
$y_length = count($y_value); $y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied if (!$x_length || !$y_length) { // a 0 is being multiplied
return array(); return array();
} }
if ( $x_length < $y_length ) { if ($x_length < $y_length) {
$temp = $x_value; $temp = $x_value;
$x_value = $y_value; $x_value = $y_value;
$y_value = $temp; $y_value = $temp;
@ -1296,7 +1306,7 @@ class Math_BigInteger
*/ */
function _baseSquare($value) function _baseSquare($value)
{ {
if ( empty($value) ) { if (empty($value)) {
return array(); return array();
} }
$square_value = $this->_array_repeat(0, 2 * count($value)); $square_value = $this->_array_repeat(0, 2 * count($value));
@ -1392,7 +1402,7 @@ class Math_BigInteger
*/ */
function divide($y) function divide($y)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$quotient = new Math_BigInteger(); $quotient = new Math_BigInteger();
$remainder = new Math_BigInteger(); $remainder = new Math_BigInteger();
@ -1429,7 +1439,7 @@ class Math_BigInteger
} }
static $zero; static $zero;
if ( !isset($zero) ) { if (!isset($zero)) {
$zero = new Math_BigInteger(); $zero = new Math_BigInteger();
} }
@ -1443,16 +1453,16 @@ class Math_BigInteger
$diff = $x->compare($y); $diff = $x->compare($y);
if ( !$diff ) { if (!$diff) {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = array(1); $temp->value = array(1);
$temp->is_negative = $x_sign != $y_sign; $temp->is_negative = $x_sign != $y_sign;
return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger())); return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger()));
} }
if ( $diff < 0 ) { if ($diff < 0) {
// if $x is negative, "add" $y. // if $x is negative, "add" $y.
if ( $x_sign ) { if ($x_sign) {
$x = $y->subtract($x); $x = $y->subtract($x);
} }
return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x)); return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x));
@ -1486,7 +1496,7 @@ class Math_BigInteger
// $temp = $y << ($x_max - $y_max-1) in base 2**26 // $temp = $y << ($x_max - $y_max-1) in base 2**26
$temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value);
while ( $x->compare($temp) >= 0 ) { while ($x->compare($temp) >= 0) {
// calculate the "common residue" // calculate the "common residue"
++$quotient_value[$x_max - $y_max]; ++$quotient_value[$x_max - $y_max];
$x = $x->subtract($temp); $x = $x->subtract($temp);
@ -1522,7 +1532,7 @@ class Math_BigInteger
$rhs_value = array($x_window[2], $x_window[1], $x_window[0]); $rhs_value = array($x_window[2], $x_window[1], $x_window[0]);
while ( $lhs->compare($rhs) > 0 ) { while ($lhs->compare($rhs) > 0) {
--$quotient_value[$q_index]; --$quotient_value[$q_index];
$lhs->value = array($quotient_value[$q_index]); $lhs->value = array($quotient_value[$q_index]);
@ -1553,7 +1563,7 @@ class Math_BigInteger
$quotient->is_negative = $x_sign != $y_sign; $quotient->is_negative = $x_sign != $y_sign;
// calculate the "common residue", if appropriate // calculate the "common residue", if appropriate
if ( $x_sign ) { if ($x_sign) {
$y->_rshift($shift); $y->_rshift($shift);
$x = $y->subtract($x); $x = $y->subtract($x);
} }
@ -1642,7 +1652,7 @@ class Math_BigInteger
return $this->_normalize($temp->modPow($e, $n)); return $this->_normalize($temp->modPow($e, $n));
} }
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP ) { if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_powm($this->value, $e->value, $n->value); $temp->value = gmp_powm($this->value, $e->value, $n->value);
@ -1665,17 +1675,23 @@ class Math_BigInteger
'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent'])
); );
$RSAPublicKey = pack('Ca*a*a*', $RSAPublicKey = pack(
48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), 'Ca*a*a*',
$components['modulus'], $components['publicExponent'] 48,
$this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
); );
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(0) . $RSAPublicKey;
$RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey;
$encapsulated = pack('Ca*a*', $encapsulated = pack(
48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey 'Ca*a*',
48,
$this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)),
$rsaOID . $RSAPublicKey
); );
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
@ -1689,25 +1705,25 @@ class Math_BigInteger
} }
} }
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) { if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = bcpowmod($this->value, $e->value, $n->value, 0); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0);
return $this->_normalize($temp); return $this->_normalize($temp);
} }
if ( empty($e->value) ) { if (empty($e->value)) {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = array(1); $temp->value = array(1);
return $this->_normalize($temp); return $this->_normalize($temp);
} }
if ( $e->value == array(1) ) { if ($e->value == array(1)) {
list(, $temp) = $this->divide($n); list(, $temp) = $this->divide($n);
return $this->_normalize($temp); return $this->_normalize($temp);
} }
if ( $e->value == array(2) ) { if ($e->value == array(2)) {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = $this->_square($this->value); $temp->value = $this->_square($this->value);
list(, $temp) = $temp->divide($n); list(, $temp) = $temp->divide($n);
@ -1722,14 +1738,14 @@ class Math_BigInteger
// made uncallable // made uncallable
// is the modulo odd? // is the modulo odd?
if ( $n->value[0] & 1 ) { if ($n->value[0] & 1) {
return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY)); return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
} }
// if it's not, it's even // if it's not, it's even
// find the lowest set bit (eg. the max pow of 2 that divides $n) // find the lowest set bit (eg. the max pow of 2 that divides $n)
for ($i = 0; $i < count($n->value); ++$i) { for ($i = 0; $i < count($n->value); ++$i) {
if ( $n->value[$i] ) { if ($n->value[$i]) {
$temp = decbin($n->value[$i]); $temp = decbin($n->value[$i]);
$j = strlen($temp) - strrpos($temp, '1') - 1; $j = strlen($temp) - strrpos($temp, '1') - 1;
$j+= 26 * $i; $j+= 26 * $i;
@ -1807,7 +1823,8 @@ class Math_BigInteger
// calculate the appropriate window size. // calculate the appropriate window size.
// $window_size == 3 if $window_ranges is between 25 and 81, for example. // $window_size == 3 if $window_ranges is between 25 and 81, for example.
for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i); for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i) {
}
$n_value = $n->value; $n_value = $n->value;
@ -1827,13 +1844,13 @@ class Math_BigInteger
$result = array(1); $result = array(1);
$result = $this->_prepareReduce($result, $n_value, $mode); $result = $this->_prepareReduce($result, $n_value, $mode);
for ($i = 0; $i < $e_length; ) { for ($i = 0; $i < $e_length;) {
if ( !$e_bits[$i] ) { if (!$e_bits[$i]) {
$result = $this->_squareReduce($result, $n_value, $mode); $result = $this->_squareReduce($result, $n_value, $mode);
++$i; ++$i;
} else { } else {
for ($j = $window_size - 1; $j > 0; --$j) { for ($j = $window_size - 1; $j > 0; --$j) {
if ( !empty($e_bits[$i + $j]) ) { if (!empty($e_bits[$i + $j])) {
break; break;
} }
} }
@ -2017,7 +2034,7 @@ class Math_BigInteger
// n = 2 * m.length // n = 2 * m.length
if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]); $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $m; $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
@ -2106,7 +2123,7 @@ class Math_BigInteger
return $temp->value; return $temp->value;
} }
if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]); $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $n; $cache[MATH_BIGINTEGER_VARIABLE][] = $n;
$lhs = new Math_BigInteger(); $lhs = new Math_BigInteger();
@ -2134,7 +2151,7 @@ class Math_BigInteger
if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) { if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
$corrector_value = $this->_array_repeat(0, $n_length + 1); $corrector_value = $this->_array_repeat(0, $n_length + 1);
$corrector_value[] = 1; $corrector_value[count($corrector_value)] = 1;
$result = $this->_add($result, false, $corrector_value, false); $result = $this->_add($result, false, $corrector_value, false);
$result = $result[MATH_BIGINTEGER_VALUE]; $result = $result[MATH_BIGINTEGER_VALUE];
} }
@ -2167,14 +2184,14 @@ class Math_BigInteger
$x_length = count($x_value); $x_length = count($x_value);
$y_length = count($y_value); $y_length = count($y_value);
if ( !$x_length || !$y_length ) { // a 0 is being multiplied if (!$x_length || !$y_length) { // a 0 is being multiplied
return array( return array(
MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_VALUE => array(),
MATH_BIGINTEGER_SIGN => false MATH_BIGINTEGER_SIGN => false
); );
} }
if ( $x_length < $y_length ) { if ($x_length < $y_length) {
$temp = $x_value; $temp = $x_value;
$x_value = $y_value; $x_value = $y_value;
$y_value = $temp; $y_value = $temp;
@ -2248,7 +2265,7 @@ class Math_BigInteger
MATH_BIGINTEGER_DATA => array() MATH_BIGINTEGER_DATA => array()
); );
if ( ($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]); $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $x; $cache[MATH_BIGINTEGER_VARIABLE][] = $x;
$cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n); $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n);
@ -2304,7 +2321,7 @@ class Math_BigInteger
MATH_BIGINTEGER_DATA => array() MATH_BIGINTEGER_DATA => array()
); );
if ( ($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false ) { if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) {
$key = count($cache[MATH_BIGINTEGER_VARIABLE]); $key = count($cache[MATH_BIGINTEGER_VARIABLE]);
$cache[MATH_BIGINTEGER_VARIABLE][] = $m; $cache[MATH_BIGINTEGER_VARIABLE][] = $m;
$cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m); $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m);
@ -2419,7 +2436,7 @@ class Math_BigInteger
*/ */
function modInverse($n) function modInverse($n)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_invert($this->value, $n->value); $temp->value = gmp_invert($this->value, $n->value);
@ -2485,7 +2502,7 @@ class Math_BigInteger
*/ */
function extendedGCD($n) function extendedGCD($n)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
extract(gmp_gcdext($this->value, $n->value)); extract(gmp_gcdext($this->value, $n->value));
@ -2535,7 +2552,7 @@ class Math_BigInteger
$g = new Math_BigInteger(); $g = new Math_BigInteger();
$g->value = array(1); $g->value = array(1);
while ( !(($x->value[0] & 1)|| ($y->value[0] & 1)) ) { while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) {
$x->_rshift(1); $x->_rshift(1);
$y->_rshift(1); $y->_rshift(1);
$g->_lshift(1); $g->_lshift(1);
@ -2552,10 +2569,10 @@ class Math_BigInteger
$a->value = $d->value = $g->value = array(1); $a->value = $d->value = $g->value = array(1);
$b->value = $c->value = array(); $b->value = $c->value = array();
while ( !empty($u->value) ) { while (!empty($u->value)) {
while ( !($u->value[0] & 1) ) { while (!($u->value[0] & 1)) {
$u->_rshift(1); $u->_rshift(1);
if ( (!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1)) ) { if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) {
$a = $a->add($y); $a = $a->add($y);
$b = $b->subtract($x); $b = $b->subtract($x);
} }
@ -2563,9 +2580,9 @@ class Math_BigInteger
$b->_rshift(1); $b->_rshift(1);
} }
while ( !($v->value[0] & 1) ) { while (!($v->value[0] & 1)) {
$v->_rshift(1); $v->_rshift(1);
if ( (!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1)) ) { if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) {
$c = $c->add($y); $c = $c->add($y);
$d = $d->subtract($x); $d = $d->subtract($x);
} }
@ -2630,7 +2647,7 @@ class Math_BigInteger
{ {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp->value = gmp_abs($this->value); $temp->value = gmp_abs($this->value);
break; break;
@ -2664,7 +2681,7 @@ class Math_BigInteger
*/ */
function compare($y) function compare($y)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
return gmp_cmp($this->value, $y->value); return gmp_cmp($this->value, $y->value);
case MATH_BIGINTEGER_MODE_BCMATH: case MATH_BIGINTEGER_MODE_BCMATH:
@ -2687,13 +2704,13 @@ class Math_BigInteger
*/ */
function _compare($x_value, $x_negative, $y_value, $y_negative) function _compare($x_value, $x_negative, $y_value, $y_negative)
{ {
if ( $x_negative != $y_negative ) { if ($x_negative != $y_negative) {
return ( !$x_negative && $y_negative ) ? 1 : -1; return ( !$x_negative && $y_negative ) ? 1 : -1;
} }
$result = $x_negative ? -1 : 1; $result = $x_negative ? -1 : 1;
if ( count($x_value) != count($y_value) ) { if (count($x_value) != count($y_value)) {
return ( count($x_value) > count($y_value) ) ? $result : -$result; return ( count($x_value) > count($y_value) ) ? $result : -$result;
} }
$size = max(count($x_value), count($y_value)); $size = max(count($x_value), count($y_value));
@ -2722,7 +2739,7 @@ class Math_BigInteger
*/ */
function equals($x) function equals($x)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
return gmp_cmp($this->value, $x->value) == 0; return gmp_cmp($this->value, $x->value) == 0;
default: default:
@ -2742,7 +2759,7 @@ class Math_BigInteger
function setPrecision($bits) function setPrecision($bits)
{ {
$this->precision = $bits; $this->precision = $bits;
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ) { if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH) {
$this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256);
} else { } else {
$this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0)); $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0));
@ -2762,7 +2779,7 @@ class Math_BigInteger
*/ */
function bitwise_and($x) function bitwise_and($x)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_and($this->value, $x->value); $temp->value = gmp_and($this->value, $x->value);
@ -2803,7 +2820,7 @@ class Math_BigInteger
*/ */
function bitwise_or($x) function bitwise_or($x)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_or($this->value, $x->value); $temp->value = gmp_or($this->value, $x->value);
@ -2843,7 +2860,7 @@ class Math_BigInteger
*/ */
function bitwise_xor($x) function bitwise_xor($x)
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
$temp->value = gmp_xor($this->value, $x->value); $temp->value = gmp_xor($this->value, $x->value);
@ -2923,7 +2940,7 @@ class Math_BigInteger
{ {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
static $two; static $two;
@ -2961,7 +2978,7 @@ class Math_BigInteger
{ {
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
static $two; static $two;
@ -3000,7 +3017,7 @@ class Math_BigInteger
if ($this->precision > 0) { if ($this->precision > 0) {
$precision = $this->precision; $precision = $this->precision;
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) { if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
$mask = $this->bitmask->subtract(new Math_BigInteger(1)); $mask = $this->bitmask->subtract(new Math_BigInteger(1));
$mask = $mask->toBytes(); $mask = $mask->toBytes();
} else { } else {
@ -3008,7 +3025,8 @@ class Math_BigInteger
} }
} else { } else {
$temp = ord($bits[0]); $temp = ord($bits[0]);
for ($i = 0; $temp >> $i; ++$i); for ($i = 0; $temp >> $i; ++$i) {
}
$precision = 8 * strlen($bits) - 8 + $i; $precision = 8 * strlen($bits) - 8 + $i;
$mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3);
} }
@ -3119,7 +3137,7 @@ class Math_BigInteger
if (!$compare) { if (!$compare) {
return $this->_normalize($min); return $this->_normalize($min);
} else if ($compare < 0) { } elseif ($compare < 0) {
// if $min is bigger then $max, swap $min and $max // if $min is bigger then $max, swap $min and $max
$temp = $max; $temp = $max;
$max = $min; $max = $min;
@ -3200,7 +3218,7 @@ class Math_BigInteger
if (!$compare) { if (!$compare) {
return $min->isPrime() ? $min : false; return $min->isPrime() ? $min : false;
} else if ($compare < 0) { } elseif ($compare < 0) {
// if $min is bigger then $max, swap $min and $max // if $min is bigger then $max, swap $min and $max
$temp = $max; $temp = $max;
$max = $min; $max = $min;
@ -3218,7 +3236,7 @@ class Math_BigInteger
$x = $this->random($min, $max); $x = $this->random($min, $max);
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>. // gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) { if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime')) {
$p = new Math_BigInteger(); $p = new Math_BigInteger();
$p->value = gmp_nextprime($x->value); $p->value = gmp_nextprime($x->value);
@ -3284,7 +3302,7 @@ class Math_BigInteger
*/ */
function _make_odd() function _make_odd()
{ {
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
gmp_setbit($this->value, 0); gmp_setbit($this->value, 0);
break; break;
@ -3336,7 +3354,7 @@ class Math_BigInteger
// ie. gmp_testbit($this, 0) // ie. gmp_testbit($this, 0)
// ie. isEven() or !isOdd() // ie. isEven() or !isOdd()
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
return gmp_prob_prime($this->value, $t) != 0; return gmp_prob_prime($this->value, $t) != 0;
case MATH_BIGINTEGER_MODE_BCMATH: case MATH_BIGINTEGER_MODE_BCMATH:
@ -3373,7 +3391,7 @@ class Math_BigInteger
953, 967, 971, 977, 983, 991, 997 953, 967, 971, 977, 983, 991, 997
); );
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) { if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
for ($i = 0; $i < count($primes); ++$i) { for ($i = 0; $i < count($primes); ++$i) {
$primes[$i] = new Math_BigInteger($primes[$i]); $primes[$i] = new Math_BigInteger($primes[$i]);
} }
@ -3389,7 +3407,7 @@ class Math_BigInteger
} }
// see HAC 4.4.1 "Random search for probable primes" // see HAC 4.4.1 "Random search for probable primes"
if ( MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL ) { if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) {
foreach ($primes as $prime) { foreach ($primes as $prime) {
list(, $r) = $this->divide($prime); list(, $r) = $this->divide($prime);
if ($r->equals($zero)) { if ($r->equals($zero)) {
@ -3413,7 +3431,7 @@ class Math_BigInteger
$r = $n_1->copy(); $r = $n_1->copy();
$r_value = $r->value; $r_value = $r->value;
// ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH ) { if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) {
$s = 0; $s = 0;
// if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals($one) check earlier
while ($r->value[strlen($r->value) - 1] % 2 == 0) { while ($r->value[strlen($r->value) - 1] % 2 == 0) {
@ -3423,7 +3441,8 @@ class Math_BigInteger
} else { } else {
for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
$temp = ~$r_value[$i] & 0xFFFFFF; $temp = ~$r_value[$i] & 0xFFFFFF;
for ($j = 1; ($temp >> $j) & 1; ++$j); for ($j = 1; ($temp >> $j) & 1; ++$j) {
}
if ($j != 25) { if ($j != 25) {
break; break;
} }
@ -3462,7 +3481,7 @@ class Math_BigInteger
*/ */
function _lshift($shift) function _lshift($shift)
{ {
if ( $shift == 0 ) { if ($shift == 0) {
return; return;
} }
@ -3478,8 +3497,8 @@ class Math_BigInteger
$this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL); $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
} }
if ( $carry ) { if ($carry) {
$this->value[] = $carry; $this->value[count($this->value)] = $carry;
} }
while ($num_digits--) { while ($num_digits--) {
@ -3506,7 +3525,7 @@ class Math_BigInteger
$carry_shift = MATH_BIGINTEGER_BASE - $shift; $carry_shift = MATH_BIGINTEGER_BASE - $shift;
$carry_mask = (1 << $shift) - 1; $carry_mask = (1 << $shift) - 1;
if ( $num_digits ) { if ($num_digits) {
$this->value = array_slice($this->value, $num_digits); $this->value = array_slice($this->value, $num_digits);
} }
@ -3536,7 +3555,7 @@ class Math_BigInteger
$result->precision = $this->precision; $result->precision = $this->precision;
$result->bitmask = $this->bitmask; $result->bitmask = $this->bitmask;
switch ( MATH_BIGINTEGER_MODE ) { switch (MATH_BIGINTEGER_MODE) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
if (!empty($result->bitmask->value)) { if (!empty($result->bitmask->value)) {
$result->value = gmp_and($result->value, $result->bitmask->value); $result->value = gmp_and($result->value, $result->bitmask->value);
@ -3553,7 +3572,7 @@ class Math_BigInteger
$value = &$result->value; $value = &$result->value;
if ( !count($value) ) { if (!count($value)) {
return $result; return $result;
} }
@ -3583,7 +3602,7 @@ class Math_BigInteger
function _trim($value) function _trim($value)
{ {
for ($i = count($value) - 1; $i >= 0; --$i) { for ($i = count($value) - 1; $i >= 0; --$i) {
if ( $value[$i] ) { if ($value[$i]) {
break; break;
} }
unset($value[$i]); unset($value[$i]);

View File

@ -17,7 +17,7 @@
* if (!$ssh->login('username', 'password')) { * if (!$ssh->login('username', 'password')) {
* exit('bad login'); * exit('bad login');
* } * }
*
* $scp = new Net_SCP($ssh); * $scp = new Net_SCP($ssh);
* $scp->put('abcd', str_repeat('x', 1024*1024)); * $scp->put('abcd', str_repeat('x', 1024*1024));
* ?> * ?>
@ -44,7 +44,7 @@
* @category Net * @category Net
* @package Net_SCP * @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMX Jim Wigginton * @copyright 2010 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -129,7 +129,7 @@ class Net_SCP
} }
switch (strtolower(get_class($ssh))) { switch (strtolower(get_class($ssh))) {
case'net_ssh2': case 'net_ssh2':
$this->mode = NET_SCP_SSH2; $this->mode = NET_SCP_SSH2;
break; break;
case 'net_ssh1': case 'net_ssh1':
@ -170,7 +170,7 @@ class Net_SCP
return false; return false;
} }
if (!$this->ssh->exec('scp -t "' . $remote_file . '"', false)) { // -t = to if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
return false; return false;
} }
@ -195,7 +195,6 @@ class Net_SCP
$fp = @fopen($data, 'rb'); $fp = @fopen($data, 'rb');
if (!$fp) { if (!$fp) {
fclose($fp);
return false; return false;
} }
$size = filesize($data); $size = filesize($data);
@ -245,7 +244,7 @@ class Net_SCP
return false; return false;
} }
if (!$this->ssh->exec('scp -f "' . $remote_file . '"', false)) { // -f = from if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
return false; return false;
} }
@ -304,7 +303,7 @@ class Net_SCP
case NET_SCP_SSH1: case NET_SCP_SSH1:
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data); $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
$this->ssh->_send_binary_packet($data); $this->ssh->_send_binary_packet($data);
} }
} }
/** /**
@ -340,7 +339,7 @@ class Net_SCP
return false; return false;
} }
} }
} }
} }
/** /**
@ -356,6 +355,6 @@ class Net_SCP
break; break;
case NET_SCP_SSH1: case NET_SCP_SSH1:
$this->ssh->disconnect(); $this->ssh->disconnect();
} }
} }
} }

View File

@ -48,7 +48,7 @@
* @category Net * @category Net
* @package Net_SFTP * @package Net_SFTP
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMIX Jim Wigginton * @copyright 2009 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -102,6 +102,11 @@ define('NET_SFTP_LOCAL_FILE', 1);
*/ */
// this value isn't really used anymore but i'm keeping it reserved for historical reasons // this value isn't really used anymore but i'm keeping it reserved for historical reasons
define('NET_SFTP_STRING', 2); define('NET_SFTP_STRING', 2);
/**
* Reads data from callback:
* function callback($length) returns string to proceed, null for EOF
*/
define('NET_SFTP_CALLBACK', 16);
/** /**
* Resumes an upload * Resumes an upload
*/ */
@ -429,8 +434,15 @@ class Net_SFTP extends Net_SSH2
$this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size; $this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size;
$packet = pack('CNa*N3', $packet = pack(
NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SFTP_CHANNEL, $this->window_size, 0x4000); 'CNa*N3',
NET_SSH2_MSG_CHANNEL_OPEN,
strlen('session'),
'session',
NET_SFTP_CHANNEL,
$this->window_size,
0x4000
);
if (!$this->_send_binary_packet($packet)) { if (!$this->_send_binary_packet($packet)) {
return false; return false;
@ -443,8 +455,16 @@ class Net_SFTP extends Net_SSH2
return false; return false;
} }
$packet = pack('CNNa*CNa*', $packet = pack(
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp'); 'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[NET_SFTP_CHANNEL],
strlen('subsystem'),
'subsystem',
1,
strlen('sftp'),
'sftp'
);
if (!$this->_send_binary_packet($packet)) { if (!$this->_send_binary_packet($packet)) {
return false; return false;
} }
@ -459,8 +479,16 @@ class Net_SFTP extends Net_SSH2
"exec sftp-server"; "exec sftp-server";
// 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 // 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
// is redundant // is redundant
$packet = pack('CNNa*CNa*', $packet = pack(
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command); 'CNNa*CNa*',
NET_SSH2_MSG_CHANNEL_REQUEST,
$this->server_channels[NET_SFTP_CHANNEL],
strlen('exec'),
'exec',
1,
strlen($command),
$command
);
if (!$this->_send_binary_packet($packet)) { if (!$this->_send_binary_packet($packet)) {
return false; return false;
} }
@ -801,7 +829,7 @@ class Net_SFTP extends Net_SSH2
static $depth = 0; static $depth = 0;
foreach ($files as $key=>$value) { foreach ($files as $key => $value) {
if ($depth != 0 && $key == '..') { if ($depth != 0 && $key == '..') {
unset($files[$key]); unset($files[$key]);
continue; continue;
@ -896,7 +924,7 @@ class Net_SFTP extends Net_SSH2
} else { } else {
$temp = $dir . '/' . $shortname; $temp = $dir . '/' . $shortname;
} }
$this->_update_stat_cache($temp, (object) $attributes); $this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
} }
// SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
// final SSH_FXP_STATUS packet should tell us that, already. // final SSH_FXP_STATUS packet should tell us that, already.
@ -1057,16 +1085,34 @@ class Net_SFTP extends Net_SSH2
*/ */
function _update_stat_cache($path, $value) function _update_stat_cache($path, $value)
{ {
if ($this->use_stat_cache === false) {
return;
}
// preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/')) // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path)); $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
$temp = &$this->stat_cache; $temp = &$this->stat_cache;
$max = count($dirs) - 1; $max = count($dirs) - 1;
foreach ($dirs as $i=>$dir) { foreach ($dirs as $i => $dir) {
// if $temp is an object that means one of two things.
// 1. a file was deleted and changed to a directory behind phpseclib's back
// 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
if (is_object($temp)) {
$temp = array();
}
if (!isset($temp[$dir])) { if (!isset($temp[$dir])) {
$temp[$dir] = array(); $temp[$dir] = array();
} }
if ($i === $max) { if ($i === $max) {
if (is_object($temp[$dir])) {
if (!isset($value->stat) && isset($temp[$dir]->stat)) {
$value->stat = $temp[$dir]->stat;
}
if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
$value->lstat = $temp[$dir]->lstat;
}
}
$temp[$dir] = $value; $temp[$dir] = $value;
break; break;
} }
@ -1087,7 +1133,7 @@ class Net_SFTP extends Net_SSH2
$temp = &$this->stat_cache; $temp = &$this->stat_cache;
$max = count($dirs) - 1; $max = count($dirs) - 1;
foreach ($dirs as $i=>$dir) { foreach ($dirs as $i => $dir) {
if ($i === $max) { if ($i === $max) {
unset($temp[$dir]); unset($temp[$dir]);
return true; return true;
@ -1144,11 +1190,11 @@ class Net_SFTP extends Net_SSH2
if ($this->use_stat_cache) { if ($this->use_stat_cache) {
$result = $this->_query_stat_cache($filename); $result = $this->_query_stat_cache($filename);
if (is_array($result) && isset($result['.'])) { if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
return (array) $result['.']; return $result['.']->stat;
} }
if (is_object($result)) { if (is_object($result) && isset($result->stat)) {
return (array) $result; return $result->stat;
} }
} }
@ -1161,7 +1207,7 @@ class Net_SFTP extends Net_SSH2
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.'; $filename.= '/.';
} }
$this->_update_stat_cache($filename, (object) $stat); $this->_update_stat_cache($filename, (object) array('stat' => $stat));
return $stat; return $stat;
} }
@ -1174,7 +1220,7 @@ class Net_SFTP extends Net_SSH2
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) { if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.'; $filename.= '/.';
} }
$this->_update_stat_cache($filename, (object) $stat); $this->_update_stat_cache($filename, (object) array('stat' => $stat));
return $stat; return $stat;
} }
@ -1201,11 +1247,11 @@ class Net_SFTP extends Net_SSH2
if ($this->use_stat_cache) { if ($this->use_stat_cache) {
$result = $this->_query_stat_cache($filename); $result = $this->_query_stat_cache($filename);
if (is_array($result) && isset($result['.'])) { if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
return (array) $result['.']; return $result['.']->lstat;
} }
if (is_object($result)) { if (is_object($result) && isset($result->lstat)) {
return (array) $result; return $result->lstat;
} }
} }
@ -1218,7 +1264,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.'; $filename.= '/.';
} }
$this->_update_stat_cache($filename, (object) $lstat); $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $lstat; return $lstat;
} }
@ -1226,7 +1272,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat != $stat) { if ($lstat != $stat) {
$lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK)); $lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
$this->_update_stat_cache($filename, (object) $lstat); $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $stat; return $stat;
} }
@ -1239,7 +1285,7 @@ class Net_SFTP extends Net_SSH2
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) { if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
$filename.= '/.'; $filename.= '/.';
} }
$this->_update_stat_cache($filename, (object) $lstat); $this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
return $lstat; return $lstat;
} }
@ -1517,7 +1563,7 @@ class Net_SFTP extends Net_SSH2
} }
unset($entries['.'], $entries['..']); unset($entries['.'], $entries['..']);
foreach ($entries as $filename=>$props) { foreach ($entries as $filename => $props) {
if (!isset($props['type'])) { if (!isset($props['type'])) {
return false; return false;
} }
@ -1759,6 +1805,10 @@ class Net_SFTP extends Net_SSH2
* *
* If $data is a resource then it'll be used as a resource instead. * If $data is a resource then it'll be used as a resource instead.
* *
*
* Setting $mode to NET_SFTP_CALLBACK will use $data as callback function, which gets only one parameter -- number
* of bytes to return, and returns a string if there is some data or null if there is no more data
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself. * care of that, yourself.
* *
@ -1784,11 +1834,12 @@ class Net_SFTP extends Net_SSH2
* @param optional Integer $mode * @param optional Integer $mode
* @param optional Integer $start * @param optional Integer $start
* @param optional Integer $local_start * @param optional Integer $local_start
* @param optional callable|null $progressCallback
* @return Boolean * @return Boolean
* @access public * @access public
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode(). * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode().
*/ */
function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1, $local_start = -1) function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1, $local_start = -1, $progressCallback = null)
{ {
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
return false; return false;
@ -1836,7 +1887,15 @@ class Net_SFTP extends Net_SSH2
} }
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
$dataCallback = false;
switch (true) { switch (true) {
case $mode & NET_SFTP_CALLBACK:
if (!is_callable($data)) {
user_error("\$data should be is_callable if you set NET_SFTP_CALLBACK flag");
}
$dataCallback = $data;
// do nothing
break;
case is_resource($data): case is_resource($data):
$mode = $mode & ~NET_SFTP_LOCAL_FILE; $mode = $mode & ~NET_SFTP_LOCAL_FILE;
$fp = $data; $fp = $data;
@ -1863,6 +1922,8 @@ class Net_SFTP extends Net_SSH2
} else { } else {
fseek($fp, $offset); fseek($fp, $offset);
} }
} elseif ($dataCallback) {
$size = 0;
} else { } else {
$size = strlen($data); $size = strlen($data);
} }
@ -1874,8 +1935,15 @@ class Net_SFTP extends Net_SSH2
// make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header" // make the SFTP packet be exactly 4096 bytes by including the bytes in the NET_SFTP_WRITE packets "header"
$sftp_packet_size-= strlen($handle) + 25; $sftp_packet_size-= strlen($handle) + 25;
$i = 0; $i = 0;
while ($sent < $size) { while ($dataCallback || ($sent < $size)) {
$temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size); if ($dataCallback) {
$temp = call_user_func($dataCallback, $sftp_packet_size);
if (is_null($temp)) {
break;
}
} else {
$temp = isset($fp) ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size);
}
$subtemp = $offset + $sent; $subtemp = $offset + $sent;
$packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp); $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) { if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) {
@ -1885,6 +1953,9 @@ class Net_SFTP extends Net_SSH2
return false; return false;
} }
$sent+= strlen($temp); $sent+= strlen($temp);
if (is_callable($progressCallback)) {
call_user_func($progressCallback, $sent);
}
$i++; $i++;
@ -2166,7 +2237,7 @@ class Net_SFTP extends Net_SSH2
} }
unset($entries['.'], $entries['..']); unset($entries['.'], $entries['..']);
foreach ($entries as $filename=>$props) { foreach ($entries as $filename => $props) {
if (!isset($props['type'])) { if (!isset($props['type'])) {
return false; return false;
} }
@ -2180,6 +2251,7 @@ class Net_SFTP extends Net_SSH2
if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) { if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($temp), $temp))) {
return false; return false;
} }
$this->_remove_from_stat_cache($temp);
$i++; $i++;
@ -2190,12 +2262,12 @@ class Net_SFTP extends Net_SSH2
$i = 0; $i = 0;
} }
} }
$this->_remove_from_stat_cache($path);
} }
if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) { if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($path), $path))) {
return false; return false;
} }
$this->_remove_from_stat_cache($path);
$i++; $i++;
@ -2273,7 +2345,7 @@ class Net_SFTP extends Net_SSH2
*/ */
function is_link($path) function is_link($path)
{ {
$result = $this->_get_stat_cache_prop($path, 'type'); $result = $this->_get_lstat_cache_prop($path, 'type');
if ($result === false) { if ($result === false) {
return false; return false;
} }
@ -2367,13 +2439,20 @@ class Net_SFTP extends Net_SSH2
} }
switch ($type) { switch ($type) {
case NET_SFTP_BLOCK_DEVICE: return 'block'; case NET_SFTP_TYPE_BLOCK_DEVICE:
case NET_SFTP_TYPE_CHAR_DEVICE: return 'char'; return 'block';
case NET_SFTP_TYPE_DIRECTORY: return 'dir'; case NET_SFTP_TYPE_CHAR_DEVICE:
case NET_SFTP_TYPE_FIFO: return 'fifo'; return 'char';
case NET_SFTP_TYPE_REGULAR: return 'file'; case NET_SFTP_TYPE_DIRECTORY:
case NET_SFTP_TYPE_SYMLINK: return 'link'; return 'dir';
default: return false; case NET_SFTP_TYPE_FIFO:
return 'fifo';
case NET_SFTP_TYPE_REGULAR:
return 'file';
case NET_SFTP_TYPE_SYMLINK:
return 'link';
default:
return false;
} }
} }
@ -2388,18 +2467,48 @@ class Net_SFTP extends Net_SSH2
* @access private * @access private
*/ */
function _get_stat_cache_prop($path, $prop) function _get_stat_cache_prop($path, $prop)
{
return $this->_get_xstat_cache_prop($path, $prop, 'stat');
}
/**
* Return an lstat properity
*
* Uses cache if appropriate.
*
* @param String $path
* @param String $prop
* @return Mixed
* @access private
*/
function _get_lstat_cache_prop($path, $prop)
{
return $this->_get_xstat_cache_prop($path, $prop, 'lstat');
}
/**
* Return a stat or lstat properity
*
* Uses cache if appropriate.
*
* @param String $path
* @param String $prop
* @return Mixed
* @access private
*/
function _get_xstat_cache_prop($path, $prop, $type)
{ {
if ($this->use_stat_cache) { if ($this->use_stat_cache) {
$path = $this->_realpath($path); $path = $this->_realpath($path);
$result = $this->_query_stat_cache($path); $result = $this->_query_stat_cache($path);
if (is_object($result) && isset($result->$prop)) { if (is_object($result) && isset($result->$type)) {
return $result->$prop; return $result->{$type}[$prop];
} }
} }
$result = $this->stat($path); $result = $this->$type($path);
if ($result === false || !isset($result[$prop])) { if ($result === false || !isset($result[$prop])) {
return false; return false;
@ -2473,14 +2582,13 @@ class Net_SFTP extends Net_SSH2
foreach ($this->attributes as $key => $value) { foreach ($this->attributes as $key => $value) {
switch ($flags & $key) { switch ($flags & $key) {
case NET_SFTP_ATTR_SIZE: // 0x00000001 case NET_SFTP_ATTR_SIZE: // 0x00000001
// size is represented by a 64-bit integer, so we perhaps ought to be doing the following: // The size attribute is defined as an unsigned 64-bit integer.
// $attr['size'] = new Math_BigInteger($this->_string_shift($response, 8), 256); // The following will use floats on 32-bit platforms, if necessary.
// of course, you shouldn't be using Net_SFTP to transfer files that are in excess of 4GB // As can be seen in the BigInteger class, floats are generally
// (0xFFFFFFFF bytes), anyway. as such, we'll just represent all file sizes that are bigger than // IEEE 754 binary64 "double precision" on such platforms and
// 4GB as being 4GB. // as such can represent integers of at least 2^50 without loss
extract(unpack('Nupper/Nsize', $this->_string_shift($response, 8))); // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
$attr['size'] = $upper ? 4294967296 * $upper : 0; $attr['size'] = hexdec(bin2hex($this->_string_shift($response, 8)));
$attr['size']+= $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size;
break; break;
case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only) case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
$attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8)); $attr+= unpack('Nuid/Ngid', $this->_string_shift($response, 8));
@ -2540,7 +2648,7 @@ class Net_SFTP extends Net_SSH2
case 0020000: // character special case 0020000: // character special
return NET_SFTP_TYPE_CHAR_DEVICE; return NET_SFTP_TYPE_CHAR_DEVICE;
case 0060000: // block special case 0060000: // block special
return NET_SFTP_BLOCK_DEVICE; return NET_SFTP_TYPE_BLOCK_DEVICE;
case 0140000: // socket case 0140000: // socket
return NET_SFTP_TYPE_SOCKET; return NET_SFTP_TYPE_SOCKET;
case 0160000: // whiteout case 0160000: // whiteout
@ -2603,7 +2711,7 @@ class Net_SFTP extends Net_SSH2
{ {
$packet = $this->request_id !== false ? $packet = $this->request_id !== false ?
pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) : pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
pack('NCa*', strlen($data) + 1, $type, $data); pack('NCa*', strlen($data) + 1, $type, $data);
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
$result = $this->_send_channel_packet(NET_SFTP_CHANNEL, $packet); $result = $this->_send_channel_packet(NET_SFTP_CHANNEL, $packet);

View File

@ -28,7 +28,7 @@
* @category Net * @category Net
* @package Net_SFTP_Stream * @package Net_SFTP_Stream
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXIII Jim Wigginton * @copyright 2013 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -48,7 +48,6 @@ class Net_SFTP_Stream
* Rather than re-create the connection we re-use instances if possible * Rather than re-create the connection we re-use instances if possible
* *
* @var Array * @var Array
* @access static
*/ */
static $instances; static $instances;
@ -281,14 +280,17 @@ class Net_SFTP_Stream
if ($this->size === false) { if ($this->size === false) {
if ($this->mode[0] == 'r') { if ($this->mode[0] == 'r') {
return false; return false;
} else {
$this->sftp->touch($path);
$this->size = 0;
} }
} else { } else {
switch ($this->mode[0]) { switch ($this->mode[0]) {
case 'x': case 'x':
return false; return false;
case 'w': case 'w':
case 'c':
$this->sftp->truncate($path, 0); $this->sftp->truncate($path, 0);
$this->size = 0;
} }
} }
@ -512,7 +514,7 @@ class Net_SFTP_Stream
$path_from = $this->_parse_path($path_from); $path_from = $this->_parse_path($path_from);
$path_to = parse_url($path_to); $path_to = parse_url($path_to);
if ($path_from == false) { if ($path_from === false) {
return false; return false;
} }

View File

@ -59,7 +59,7 @@
* @category Net * @category Net
* @package Net_SSH1 * @package Net_SSH1
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright 2007 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -621,7 +621,7 @@ class Net_SSH1
// get a list of the supported ciphers // get a list of the supported ciphers
extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4))); extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
foreach ($this->supported_ciphers as $mask=>$name) { foreach ($this->supported_ciphers as $mask => $name) {
if (($supported_ciphers_mask & (1 << $mask)) == 0) { if (($supported_ciphers_mask & (1 << $mask)) == 0) {
unset($this->supported_ciphers[$mask]); unset($this->supported_ciphers[$mask]);
} }
@ -629,7 +629,7 @@ class Net_SSH1
// get a list of the supported authentications // get a list of the supported authentications
extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4))); extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
foreach ($this->supported_authentications as $mask=>$name) { foreach ($this->supported_authentications as $mask => $name) {
if (($supported_authentications_mask & (1 << $mask)) == 0) { if (($supported_authentications_mask & (1 << $mask)) == 0) {
unset($this->supported_authentications[$mask]); unset($this->supported_authentications[$mask]);
} }
@ -691,7 +691,7 @@ class Net_SSH1
$this->crypto = new Crypt_DES(); $this->crypto = new Crypt_DES();
$this->crypto->disablePadding(); $this->crypto->disablePadding();
$this->crypto->enableContinuousBuffer(); $this->crypto->enableContinuousBuffer();
$this->crypto->setKey(substr($session_key, 0, 8)); $this->crypto->setKey(substr($session_key, 0, 8));
break; break;
case NET_SSH1_CIPHER_3DES: case NET_SSH1_CIPHER_3DES:
if (!class_exists('Crypt_TripleDES')) { if (!class_exists('Crypt_TripleDES')) {
@ -760,7 +760,7 @@ class Net_SSH1
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN; $this->bitmap |= NET_SSH1_MASK_LOGIN;
return true; return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { } elseif ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
return false; return false;
} }
@ -786,7 +786,7 @@ class Net_SSH1
if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) { if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_SUCCESS) {
$this->bitmap |= NET_SSH1_MASK_LOGIN; $this->bitmap |= NET_SSH1_MASK_LOGIN;
return true; return true;
} else if ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { } elseif ($response[NET_SSH1_RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
return false; return false;
} else { } else {
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
@ -1128,6 +1128,7 @@ class Net_SSH1
$padding_length = 8 - ($temp['length'] & 7); $padding_length = 8 - ($temp['length'] & 7);
$length = $temp['length'] + $padding_length; $length = $temp['length'] + $padding_length;
$raw = '';
while ($length > 0) { while ($length > 0) {
$temp = fread($this->fsock, $length); $temp = fread($this->fsock, $length);
@ -1298,7 +1299,7 @@ class Net_SSH1
$crc = 0x00000000; $crc = 0x00000000;
$length = strlen($data); $length = strlen($data);
for ($i=0;$i<$length;$i++) { for ($i=0; $i<$length; $i++) {
// We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all // We AND $crc >> 8 with 0x00FFFFFF because we want the eight newly added bits to all
// be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example, // be zero. PHP, unfortunately, doesn't always do this. 0x80000000 >> 8, as an example,
// yields 0xFF800000 - not 0x00800000. The following link elaborates: // yields 0xFF800000 - not 0x00800000. The following link elaborates:
@ -1397,7 +1398,7 @@ class Net_SSH1
{ {
$args = func_get_args(); $args = func_get_args();
foreach ($args as $arg) { foreach ($args as $arg) {
foreach ($arg as $key=>$value) { foreach ($arg as $key => $value) {
if (!defined($value)) { if (!defined($value)) {
define($value, $key); define($value, $key);
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Pure-PHP ssh-agent client. * Pure-PHP ssh-agent client.
* *
@ -43,7 +44,7 @@
* @category System * @category System
* @package System_SSH_Agent * @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXIV Jim Wigginton * @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent * @internal See http://api.libssh.org/rfc/PROTOCOL.agent
@ -63,6 +64,20 @@ define('SYSTEM_SSH_AGENT_FAILURE', 5);
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13); define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4) // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14); define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
/**@+
* Agent forwarding status
*
* @access private
*/
// no forwarding requested and not active
define('SYSTEM_SSH_AGENT_FORWARD_NONE', 0);
// request agent forwarding when opportune
define('SYSTEM_SSH_AGENT_FORWARD_REQUEST', 1);
// forwarding has been request and is active
define('SYSTEM_SSH_AGENT_FORWARD_ACTIVE', 2);
/**#@-*/ /**#@-*/
/** /**
@ -225,6 +240,29 @@ class System_SSH_Agent
*/ */
var $fsock; var $fsock;
/**
* Agent forwarding status
*
* @access private
*/
var $forward_status = SYSTEM_SSH_AGENT_FORWARD_NONE;
/**
* Buffer for accumulating forwarded authentication
* agent data arriving on SSH data channel destined
* for agent unix socket
*
* @access private
*/
var $socket_buffer = '';
/**
* Tracking the number of bytes we are expecting
* to arrive for the agent socket on the SSH data
* channel
*/
var $expected_bytes = 0;
/** /**
* Default Constructor * Default Constructor
* *
@ -310,4 +348,113 @@ class System_SSH_Agent
return $identities; return $identities;
} }
/**
* Signal that agent forwarding should
* be requested when a channel is opened
*
* @param Net_SSH2 $ssh
* @return Boolean
* @access public
*/
function startSSHForwarding($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_NONE) {
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_REQUEST;
}
}
/**
* Request agent forwarding of remote server
*
* @param Net_SSH2 $ssh
* @return Boolean
* @access private
*/
function _request_forwarding($ssh)
{
$request_channel = $ssh->_get_open_channel();
if ($request_channel === false) {
return false;
}
$packet = pack(
'CNNa*C',
NET_SSH2_MSG_CHANNEL_REQUEST,
$ssh->server_channels[$request_channel],
strlen('auth-agent-req@openssh.com'),
'auth-agent-req@openssh.com',
1
);
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
if (!$ssh->_send_binary_packet($packet)) {
return false;
}
$response = $ssh->_get_channel_packet($request_channel);
if ($response === false) {
return false;
}
$ssh->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
$this->forward_status = SYSTEM_SSH_AGENT_FORWARD_ACTIVE;
return true;
}
/**
* On successful channel open
*
* This method is called upon successful channel
* open to give the SSH Agent an opportunity
* to take further action. i.e. request agent forwarding
*
* @param Net_SSH2 $ssh
* @access private
*/
function _on_channel_open($ssh)
{
if ($this->forward_status == SYSTEM_SSH_AGENT_FORWARD_REQUEST) {
$this->_request_forwarding($ssh);
}
}
/**
* Forward data to SSH Agent and return data reply
*
* @param String $data
* @return data from SSH Agent
* @access private
*/
function _forward_data($data)
{
if ($this->expected_bytes > 0) {
$this->socket_buffer.= $data;
$this->expected_bytes -= strlen($data);
} else {
$agent_data_bytes = current(unpack('N', $data));
$current_data_bytes = strlen($data);
$this->socket_buffer = $data;
if ($current_data_bytes != $agent_data_bytes + 4) {
$this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
return false;
}
}
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
user_error('Connection closed attempting to forward data to SSH agent');
}
$this->socket_buffer = '';
$this->expected_bytes = 0;
$agent_reply_bytes = current(unpack('N', fread($this->fsock, 4)));
$agent_reply_data = fread($this->fsock, $agent_reply_bytes);
$agent_reply_data = current(unpack('a*', $agent_reply_data));
return pack('Na*', $agent_reply_bytes, $agent_reply_data);
}
} }

View File

@ -30,7 +30,7 @@
* @category System * @category System
* @package System_SSH_Agent * @package System_SSH_Agent
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXIV Jim Wigginton * @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent * @internal See http://api.libssh.org/rfc/PROTOCOL.agent