phpSeclib update
This commit is contained in:
parent
bc0b29a090
commit
0fd01851b9
|
@ -19,7 +19,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/AES.php');
|
||||
* include 'Crypt/AES.php';
|
||||
*
|
||||
* $aes = new Crypt_AES();
|
||||
*
|
||||
|
@ -56,7 +56,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_AES
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -109,7 +109,7 @@ define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
|
|||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_AES::Crypt_AES()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
|
@ -126,7 +126,6 @@ define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
*
|
||||
* @package Crypt_AES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_AES extends Crypt_Rijndael
|
||||
|
@ -140,35 +139,6 @@ class Crypt_AES extends Crypt_Rijndael
|
|||
*/
|
||||
var $const_namespace = 'AES';
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_AES_MODE_ECB
|
||||
*
|
||||
* - CRYPT_AES_MODE_CBC
|
||||
*
|
||||
* - CRYPT_AES_MODE_CTR
|
||||
*
|
||||
* - CRYPT_AES_MODE_CFB
|
||||
*
|
||||
* - CRYPT_AES_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_AES_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Rijndael::Crypt_Rijndael()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Rijndael($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function
|
||||
*
|
||||
|
@ -182,4 +152,56 @@ class Crypt_AES extends Crypt_Rijndael
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key length
|
||||
*
|
||||
* Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to
|
||||
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
|
||||
*
|
||||
* @see Crypt_Rijndael:setKeyLength()
|
||||
* @access public
|
||||
* @param Integer $length
|
||||
*/
|
||||
function setKeyLength($length)
|
||||
{
|
||||
switch ($length) {
|
||||
case 160:
|
||||
$length = 192;
|
||||
break;
|
||||
case 224:
|
||||
$length = 256;
|
||||
}
|
||||
parent::setKeyLength($length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
* Rijndael supports five different key lengths, AES only supports three.
|
||||
*
|
||||
* @see Crypt_Rijndael:setKey()
|
||||
* @see setKeyLength()
|
||||
* @access public
|
||||
* @param String $key
|
||||
*/
|
||||
function setKey($key)
|
||||
{
|
||||
parent::setKey($key);
|
||||
|
||||
if (!$this->explicit_key_length) {
|
||||
$length = strlen($key);
|
||||
switch (true) {
|
||||
case $length <= 16:
|
||||
$this->key_size = 16;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_size = 24;
|
||||
break;
|
||||
default:
|
||||
$this->key_size = 32;
|
||||
}
|
||||
$this->_setupEngine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,8 @@
|
|||
* @package Crypt_Base
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @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
|
||||
* @version 1.0.1
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
|
@ -117,7 +116,6 @@ define('CRYPT_MODE_MCRYPT', 2);
|
|||
* @package Crypt_Base
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @version 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_Base
|
||||
|
@ -279,7 +277,7 @@ class Crypt_Base
|
|||
* $buffer bytes > $cfb_init_len than
|
||||
* using the $ecb resource furthermore.
|
||||
*
|
||||
* This value depends of the choosen cipher
|
||||
* This value depends of the chosen cipher
|
||||
* and the time it would be needed for it's
|
||||
* initialization [by mcrypt_generic_init()]
|
||||
* which, typically, depends on the complexity
|
||||
|
@ -438,9 +436,9 @@ class Crypt_Base
|
|||
*
|
||||
* - CRYPT_MODE_OFB
|
||||
*
|
||||
* (or the alias constants of the choosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
|
||||
* (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...)
|
||||
*
|
||||
* If not explictly set, CRYPT_MODE_CBC will be used.
|
||||
* If not explicitly set, CRYPT_MODE_CBC will be used.
|
||||
*
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
|
@ -500,7 +498,7 @@ class Crypt_Base
|
|||
/**
|
||||
* Sets the initialization vector. (optional)
|
||||
*
|
||||
* SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explictly set, it'll be assumed
|
||||
* SetIV is not required when CRYPT_MODE_ECB (or ie for AES: CRYPT_AES_MODE_ECB) is being used. If not explicitly set, it'll be assumed
|
||||
* to be all zero's.
|
||||
*
|
||||
* Note: Could, but not must, extend by the child Crypt_* class
|
||||
|
@ -543,7 +541,7 @@ class Crypt_Base
|
|||
* Sets the password.
|
||||
*
|
||||
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
|
||||
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
|
||||
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
|
||||
* $hash, $salt, $count, $dkLen
|
||||
*
|
||||
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
|
||||
|
@ -553,6 +551,7 @@ class Crypt_Base
|
|||
* @see Crypt/Hash.php
|
||||
* @param String $password
|
||||
* @param optional String $method
|
||||
* @return Boolean
|
||||
* @access public
|
||||
*/
|
||||
function setPassword($password, $method = 'pbkdf2')
|
||||
|
@ -560,7 +559,7 @@ class Crypt_Base
|
|||
$key = '';
|
||||
|
||||
switch ($method) {
|
||||
default: // 'pbkdf2'
|
||||
default: // 'pbkdf2' or 'pbkdf1'
|
||||
$func_args = func_get_args();
|
||||
|
||||
// Hash function
|
||||
|
@ -574,10 +573,34 @@ class Crypt_Base
|
|||
$count = isset($func_args[4]) ? $func_args[4] : 1000;
|
||||
|
||||
// Keylength
|
||||
$dkLen = isset($func_args[5]) ? $func_args[5] : $this->password_key_size;
|
||||
if (isset($func_args[5])) {
|
||||
$dkLen = $func_args[5];
|
||||
} else {
|
||||
$dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size;
|
||||
}
|
||||
|
||||
// Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
|
||||
switch (true) {
|
||||
case $method == 'pbkdf1':
|
||||
if (!class_exists('Crypt_Hash')) {
|
||||
include_once 'Crypt/Hash.php';
|
||||
}
|
||||
$hashObj = new Crypt_Hash();
|
||||
$hashObj->setHash($hash);
|
||||
if ($dkLen > $hashObj->getLength()) {
|
||||
user_error('Derived key too long');
|
||||
return false;
|
||||
}
|
||||
$t = $password . $salt;
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$t = $hashObj->hash($t);
|
||||
}
|
||||
$key = substr($t, 0, $dkLen);
|
||||
|
||||
$this->setKey(substr($key, 0, $dkLen >> 1));
|
||||
$this->setIV(substr($key, $dkLen >> 1));
|
||||
|
||||
return true;
|
||||
// Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
|
||||
case !function_exists('hash_pbkdf2'):
|
||||
case !function_exists('hash_algos'):
|
||||
case !in_array($hash, hash_algos()):
|
||||
|
@ -604,6 +627,8 @@ class Crypt_Base
|
|||
}
|
||||
|
||||
$this->setKey($key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1446,7 +1471,7 @@ class Crypt_Base
|
|||
* - each time on _setup(), after(!) _setupKey()
|
||||
*
|
||||
*
|
||||
* This ensures that _setupInlineCrypt() has allways a
|
||||
* This ensures that _setupInlineCrypt() has always a
|
||||
* full ready2go initializated internal cipher $engine state
|
||||
* where, for example, the keys allready expanded,
|
||||
* keys/block_size calculated and such.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/Blowfish.php');
|
||||
* include 'Crypt/Blowfish.php';
|
||||
*
|
||||
* $blowfish = new Crypt_Blowfish();
|
||||
*
|
||||
|
@ -48,9 +48,8 @@
|
|||
* @package Crypt_Blowfish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @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
|
||||
* @version 1.0
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
|
@ -104,7 +103,7 @@ define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
|
|||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_Blowfish::Crypt_Blowfish()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
|
@ -122,7 +121,6 @@ define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
* @package Crypt_Blowfish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @version 1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_Blowfish extends Crypt_Base
|
||||
|
@ -369,34 +367,6 @@ class Crypt_Blowfish extends Crypt_Base
|
|||
*/
|
||||
var $kl;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_BLOWFISH_MODE_ECB
|
||||
*
|
||||
* - CRYPT_BLOWFISH_MODE_CBC
|
||||
*
|
||||
* - CRYPT_BLOWFISH_MODE_CTR
|
||||
*
|
||||
* - CRYPT_BLOWFISH_MODE_CFB
|
||||
*
|
||||
* - CRYPT_BLOWFISH_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_BLOWFISH_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_Blowfish($mode = CRYPT_BLOWFISH_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Base($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/DES.php');
|
||||
* include 'Crypt/DES.php';
|
||||
*
|
||||
* $des = new Crypt_DES();
|
||||
*
|
||||
|
@ -53,7 +53,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_DES
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -123,7 +123,7 @@ define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB);
|
|||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_DES::Crypt_DES()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
|
@ -140,7 +140,6 @@ define('CRYPT_DES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
*
|
||||
* @package Crypt_DES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_DES extends Crypt_Base
|
||||
|
@ -662,34 +661,6 @@ class Crypt_DES extends Crypt_Base
|
|||
0x00000820, 0x00020020, 0x08000000, 0x08020800
|
||||
);
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_DES_MODE_ECB
|
||||
*
|
||||
* - CRYPT_DES_MODE_CBC
|
||||
*
|
||||
* - CRYPT_DES_MODE_CTR
|
||||
*
|
||||
* - CRYPT_DES_MODE_CFB
|
||||
*
|
||||
* - CRYPT_DES_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_DES_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_DES($mode = CRYPT_DES_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Base($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||
*
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
||||
*
|
||||
* If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
|
||||
* the hash. If no valid algorithm is provided, sha1 will be used.
|
||||
|
@ -18,7 +18,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/Hash.php');
|
||||
* include 'Crypt/Hash.php';
|
||||
*
|
||||
* $hash = new Crypt_Hash('sha1');
|
||||
*
|
||||
|
@ -49,7 +49,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Hash
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -77,7 +77,6 @@ define('CRYPT_HASH_MODE_HASH', 3);
|
|||
*
|
||||
* @package Crypt_Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_Hash
|
||||
|
@ -208,6 +207,9 @@ class Crypt_Hash
|
|||
switch ($hash) {
|
||||
case 'md5-96':
|
||||
case 'sha1-96':
|
||||
case 'sha256-96':
|
||||
case 'sha512-96':
|
||||
$hash = substr($hash, 0, -3);
|
||||
$this->l = 12; // 96 / 8 = 12
|
||||
break;
|
||||
case 'md2':
|
||||
|
@ -244,14 +246,12 @@ class Crypt_Hash
|
|||
case CRYPT_HASH_MODE_MHASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->hash = MHASH_MD5;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->hash = MHASH_SHA256;
|
||||
break;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->hash = MHASH_SHA1;
|
||||
}
|
||||
|
@ -259,7 +259,6 @@ class Crypt_Hash
|
|||
case CRYPT_HASH_MODE_HASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->hash = 'md5';
|
||||
return;
|
||||
case 'md2':
|
||||
|
@ -269,7 +268,6 @@ class Crypt_Hash
|
|||
$this->hash = $hash;
|
||||
return;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->hash = 'sha1';
|
||||
}
|
||||
|
@ -282,7 +280,6 @@ class Crypt_Hash
|
|||
$this->hash = array($this, '_md2');
|
||||
break;
|
||||
case 'md5':
|
||||
case 'md5-96':
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_md5');
|
||||
break;
|
||||
|
@ -296,7 +293,6 @@ class Crypt_Hash
|
|||
$this->hash = array($this, '_sha512');
|
||||
break;
|
||||
case 'sha1':
|
||||
case 'sha1-96':
|
||||
default:
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_sha1');
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/RC2.php');
|
||||
* include 'Crypt/RC2.php';
|
||||
*
|
||||
* $rc2 = new Crypt_RC2();
|
||||
*
|
||||
|
@ -117,7 +117,6 @@ define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
* Pure-PHP implementation of RC2.
|
||||
*
|
||||
* @package Crypt_RC2
|
||||
* @version 0.1.1
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_RC2 extends Crypt_Base
|
||||
|
@ -178,7 +177,7 @@ class Crypt_RC2 extends Crypt_Base
|
|||
*/
|
||||
var $cfb_init_len = 500;
|
||||
|
||||
/**
|
||||
/**
|
||||
* The key length in bits.
|
||||
*
|
||||
* @see Crypt_RC2::setKeyLength()
|
||||
|
@ -333,7 +332,7 @@ class Crypt_RC2 extends Crypt_Base
|
|||
*
|
||||
* - CRYPT_RC2_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_RC2_MODE_CBC will be used.
|
||||
* If not explicitly set, CRYPT_RC2_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
|
@ -386,7 +385,7 @@ class Crypt_RC2 extends Crypt_Base
|
|||
$t1 = 1024;
|
||||
}
|
||||
// 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);
|
||||
|
||||
// The mcrypt RC2 implementation only supports effective key length
|
||||
|
@ -445,8 +444,8 @@ class Crypt_RC2 extends Crypt_Base
|
|||
$r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
|
||||
$r3 |= $r3 >> 16;
|
||||
|
||||
if ($j == $limit) {
|
||||
if ($limit == 64) {
|
||||
if ($j === $limit) {
|
||||
if ($limit === 64) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -490,8 +489,8 @@ class Crypt_RC2 extends Crypt_Base
|
|||
$r0 = ($r0 | ($r0 << 16)) >> 1;
|
||||
$r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
|
||||
|
||||
if ($j == $limit) {
|
||||
if (!$limit) {
|
||||
if ($j === $limit) {
|
||||
if ($limit === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -582,8 +581,8 @@ class Crypt_RC2 extends Crypt_Base
|
|||
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
|
||||
$r3 |= $r3 >> 16;';
|
||||
|
||||
if ($j == $limit) {
|
||||
if ($limit == 64) {
|
||||
if ($j === $limit) {
|
||||
if ($limit === 64) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -620,8 +619,8 @@ class Crypt_RC2 extends Crypt_Base
|
|||
$r0 = ($r0 - ' . $keys[--$j] . ' -
|
||||
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
|
||||
|
||||
if ($j == $limit) {
|
||||
if (!$limit) {
|
||||
if ($j === $limit) {
|
||||
if ($limit === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/RC4.php');
|
||||
* include 'Crypt/RC4.php';
|
||||
*
|
||||
* $rc4 = new Crypt_RC4();
|
||||
*
|
||||
|
@ -55,7 +55,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_RC4
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -96,7 +96,6 @@ define('CRYPT_RC4_DECRYPT', 1);
|
|||
*
|
||||
* @package Crypt_RC4
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_RC4 extends Crypt_Base
|
||||
|
@ -241,7 +240,7 @@ class Crypt_RC4 extends Crypt_Base
|
|||
* Decrypts a message.
|
||||
*
|
||||
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||
* Atleast if the continuous buffer is disabled.
|
||||
* At least if the continuous buffer is disabled.
|
||||
*
|
||||
* @see Crypt_Base::encrypt()
|
||||
* @see Crypt_RC4::_crypt()
|
||||
|
@ -268,10 +267,7 @@ class Crypt_RC4 extends Crypt_Base
|
|||
{
|
||||
$key = $this->key;
|
||||
$keyLength = strlen($key);
|
||||
$keyStream = array();
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$keyStream[$i] = $i;
|
||||
}
|
||||
$keyStream = range(0, 255);
|
||||
$j = 0;
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
|
||||
|
@ -325,7 +321,7 @@ class Crypt_RC4 extends Crypt_Base
|
|||
|
||||
$keyStream[$i] = $ksj;
|
||||
$keyStream[$j] = $ksi;
|
||||
$text[$k] = chr(ord($text[$k]) ^ $keyStream[($ksj + $ksi) & 255]);
|
||||
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
|
||||
}
|
||||
|
||||
return $text;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Here's an example of how to encrypt and decrypt text with this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/RSA.php');
|
||||
* include 'Crypt/RSA.php';
|
||||
*
|
||||
* $rsa = new Crypt_RSA();
|
||||
* extract($rsa->createKey());
|
||||
|
@ -26,7 +26,7 @@
|
|||
* Here's an example of how to create signatures and verify signatures with this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/RSA.php');
|
||||
* include 'Crypt/RSA.php';
|
||||
*
|
||||
* $rsa = new Crypt_RSA();
|
||||
* extract($rsa->createKey());
|
||||
|
@ -62,7 +62,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_RSA
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -104,7 +104,7 @@ define('CRYPT_RSA_ENCRYPTION_OAEP', 1);
|
|||
* Use PKCS#1 padding.
|
||||
*
|
||||
* Although CRYPT_RSA_ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards
|
||||
* compatability 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);
|
||||
/**#@-*/
|
||||
|
@ -128,7 +128,7 @@ define('CRYPT_RSA_SIGNATURE_PSS', 1);
|
|||
* Use the PKCS#1 scheme by default.
|
||||
*
|
||||
* Although CRYPT_RSA_SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards
|
||||
* compatability with protocols (like SSH-2) written before PSS's introduction.
|
||||
* compatibility with protocols (like SSH-2) written before PSS's introduction.
|
||||
*/
|
||||
define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
|
||||
/**#@-*/
|
||||
|
@ -140,15 +140,23 @@ define('CRYPT_RSA_SIGNATURE_PKCS1', 2);
|
|||
/**
|
||||
* ASN1 Integer
|
||||
*/
|
||||
define('CRYPT_RSA_ASN1_INTEGER', 2);
|
||||
define('CRYPT_RSA_ASN1_INTEGER', 2);
|
||||
/**
|
||||
* ASN1 Bit String
|
||||
*/
|
||||
define('CRYPT_RSA_ASN1_BITSTRING', 3);
|
||||
define('CRYPT_RSA_ASN1_BITSTRING', 3);
|
||||
/**
|
||||
* ASN1 Octet String
|
||||
*/
|
||||
define('CRYPT_RSA_ASN1_OCTETSTRING', 4);
|
||||
/**
|
||||
* ASN1 Object Identifier
|
||||
*/
|
||||
define('CRYPT_RSA_ASN1_OBJECT', 6);
|
||||
/**
|
||||
* ASN1 Sequence (with the constucted bit set)
|
||||
*/
|
||||
define('CRYPT_RSA_ASN1_SEQUENCE', 48);
|
||||
define('CRYPT_RSA_ASN1_SEQUENCE', 48);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
|
@ -191,6 +199,10 @@ define('CRYPT_RSA_PRIVATE_FORMAT_PUTTY', 1);
|
|||
* XML formatted private key
|
||||
*/
|
||||
define('CRYPT_RSA_PRIVATE_FORMAT_XML', 2);
|
||||
/**
|
||||
* PKCS#8 formatted private key
|
||||
*/
|
||||
define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 3);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
|
@ -216,7 +228,14 @@ define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 3);
|
|||
* PKCS#1 formatted public key (raw)
|
||||
*
|
||||
* Used by File/X509.php
|
||||
*
|
||||
* Has the following header:
|
||||
*
|
||||
* -----BEGIN RSA PUBLIC KEY-----
|
||||
*
|
||||
* Analogous to ssh-keygen's pem format (as specified by -m)
|
||||
*/
|
||||
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 4);
|
||||
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4);
|
||||
/**
|
||||
* XML formatted public key
|
||||
|
@ -232,8 +251,16 @@ define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 6);
|
|||
* PKCS#1 formatted public key (encapsulated)
|
||||
*
|
||||
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
|
||||
*
|
||||
* Has the following header:
|
||||
*
|
||||
* -----BEGIN PUBLIC KEY-----
|
||||
*
|
||||
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
|
||||
* is specific to private keys it's basically creating a DER-encoded wrapper
|
||||
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
|
||||
*/
|
||||
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 7);
|
||||
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS8', 7);
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
|
@ -241,7 +268,6 @@ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 7);
|
|||
*
|
||||
* @package Crypt_RSA
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_RSA
|
||||
|
@ -276,7 +302,7 @@ class Crypt_RSA
|
|||
* @var Integer
|
||||
* @access public
|
||||
*/
|
||||
var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS1;
|
||||
var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8;
|
||||
|
||||
/**
|
||||
* Modulus (ie. n)
|
||||
|
@ -467,18 +493,21 @@ class Crypt_RSA
|
|||
$this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
|
||||
|
||||
if ( !defined('CRYPT_RSA_MODE') ) {
|
||||
// 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
|
||||
// can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
|
||||
if ( defined('MATH_BIGINTEGER_OPENSSL_DISABLE') ) {
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
|
||||
switch ( !defined('CRYPT_RSA_MODE') ) { // ie. only run this if the above didn't set CRYPT_RSA_MODE already
|
||||
switch (true) {
|
||||
// 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
|
||||
// can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
|
||||
case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'):
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
break;
|
||||
// openssl_pkey_get_details - which is used in the only place Crypt/RSA.php uses OpenSSL - was introduced in PHP 5.2.0
|
||||
case !function_exists('openssl_pkey_get_details'):
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
break;
|
||||
case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile):
|
||||
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
||||
ob_start();
|
||||
phpinfo();
|
||||
@phpinfo();
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
|
@ -486,9 +515,16 @@ class Crypt_RSA
|
|||
|
||||
$versions = array();
|
||||
if (!empty($matches[1])) {
|
||||
for ($i = 0; $i < count($matches[1]); $i++) {
|
||||
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
|
||||
}
|
||||
for ($i = 0; $i < count($matches[1]); $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+
|
||||
|
@ -503,7 +539,7 @@ class Crypt_RSA
|
|||
define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
|
||||
}
|
||||
break;
|
||||
case true:
|
||||
default:
|
||||
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
@ -713,17 +749,18 @@ class Crypt_RSA
|
|||
*/
|
||||
function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients)
|
||||
{
|
||||
$signed = $this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_XML;
|
||||
$num_primes = count($primes);
|
||||
$raw = array(
|
||||
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
|
||||
'modulus' => $n->toBytes(true),
|
||||
'publicExponent' => $e->toBytes(true),
|
||||
'privateExponent' => $d->toBytes(true),
|
||||
'prime1' => $primes[1]->toBytes(true),
|
||||
'prime2' => $primes[2]->toBytes(true),
|
||||
'exponent1' => $exponents[1]->toBytes(true),
|
||||
'exponent2' => $exponents[2]->toBytes(true),
|
||||
'coefficient' => $coefficients[2]->toBytes(true)
|
||||
'modulus' => $n->toBytes($signed),
|
||||
'publicExponent' => $e->toBytes($signed),
|
||||
'privateExponent' => $d->toBytes($signed),
|
||||
'prime1' => $primes[1]->toBytes($signed),
|
||||
'prime2' => $primes[2]->toBytes($signed),
|
||||
'exponent1' => $exponents[1]->toBytes($signed),
|
||||
'exponent2' => $exponents[2]->toBytes($signed),
|
||||
'coefficient' => $coefficients[2]->toBytes($signed)
|
||||
);
|
||||
|
||||
// if the format in question does not support multi-prime rsa and multi-prime rsa was used,
|
||||
|
@ -756,8 +793,8 @@ class Crypt_RSA
|
|||
strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']
|
||||
);
|
||||
$source = pack('Na*Na*Na*Na*',
|
||||
strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption,
|
||||
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);
|
||||
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
|
||||
|
@ -829,6 +866,52 @@ class Crypt_RSA
|
|||
|
||||
$RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
|
||||
|
||||
if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) {
|
||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||
$RSAPrivateKey = pack('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);
|
||||
if (!empty($this->password) || is_string($this->password)) {
|
||||
$salt = crypt_random_string(8);
|
||||
$iterationCount = 2048;
|
||||
|
||||
if (!class_exists('Crypt_DES')) {
|
||||
include_once 'Crypt/DES.php';
|
||||
}
|
||||
$crypto = new Crypt_DES();
|
||||
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
|
||||
$RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
|
||||
|
||||
$parameters = pack('Ca*a*Ca*N',
|
||||
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";
|
||||
|
||||
$encryptionAlgorithm = pack('Ca*a*Ca*a*',
|
||||
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*',
|
||||
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 = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
|
||||
chunk_split(base64_encode($RSAPrivateKey), 64) .
|
||||
'-----END ENCRYPTED PRIVATE KEY-----';
|
||||
} else {
|
||||
$RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
|
||||
chunk_split(base64_encode($RSAPrivateKey), 64) .
|
||||
'-----END PRIVATE KEY-----';
|
||||
}
|
||||
return $RSAPrivateKey;
|
||||
}
|
||||
|
||||
if (!empty($this->password) || is_string($this->password)) {
|
||||
$iv = crypt_random_string(8);
|
||||
$symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
|
||||
|
@ -866,8 +949,10 @@ class Crypt_RSA
|
|||
*/
|
||||
function _convertPublicKey($n, $e)
|
||||
{
|
||||
$modulus = $n->toBytes(true);
|
||||
$publicExponent = $e->toBytes(true);
|
||||
$signed = $this->publicKeyFormat != CRYPT_RSA_PUBLIC_FORMAT_XML;
|
||||
|
||||
$modulus = $n->toBytes($signed);
|
||||
$publicExponent = $e->toBytes($signed);
|
||||
|
||||
switch ($this->publicKeyFormat) {
|
||||
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
|
||||
|
@ -903,7 +988,11 @@ class Crypt_RSA
|
|||
$components['modulus'], $components['publicExponent']
|
||||
);
|
||||
|
||||
if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1) {
|
||||
if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
|
||||
$RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
|
||||
chunk_split(base64_encode($RSAPublicKey), 64) .
|
||||
'-----END RSA PUBLIC KEY-----';
|
||||
} else {
|
||||
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
|
||||
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
|
||||
$RSAPublicKey = chr(0) . $RSAPublicKey;
|
||||
|
@ -912,11 +1001,11 @@ class Crypt_RSA
|
|||
$RSAPublicKey = pack('Ca*a*',
|
||||
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
|
||||
);
|
||||
}
|
||||
|
||||
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
chunk_split(base64_encode($RSAPublicKey), 64) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
chunk_split(base64_encode($RSAPublicKey), 64) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
}
|
||||
|
||||
return $RSAPublicKey;
|
||||
}
|
||||
|
@ -972,6 +1061,7 @@ class Crypt_RSA
|
|||
}
|
||||
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
|
||||
case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
|
||||
case CRYPT_RSA_PRIVATE_FORMAT_PKCS8:
|
||||
case CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
|
||||
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
|
||||
"outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
|
||||
|
@ -1062,7 +1152,9 @@ class Crypt_RSA
|
|||
7:d=1 hl=2 l= 13 cons: SEQUENCE
|
||||
9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
|
||||
20:d=2 hl=2 l= 0 prim: NULL
|
||||
22:d=1 hl=4 l= 609 prim: OCTET STRING */
|
||||
22:d=1 hl=4 l= 609 prim: OCTET STRING
|
||||
|
||||
ie. PKCS8 keys*/
|
||||
|
||||
if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
|
||||
$this->_string_shift($key, 3);
|
||||
|
@ -1070,6 +1162,52 @@ class Crypt_RSA
|
|||
}
|
||||
|
||||
if ($tag == CRYPT_RSA_ASN1_SEQUENCE) {
|
||||
$temp = $this->_string_shift($key, $this->_decodeLength($key));
|
||||
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_OBJECT) {
|
||||
return false;
|
||||
}
|
||||
$length = $this->_decodeLength($temp);
|
||||
switch ($this->_string_shift($temp, $length)) {
|
||||
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
|
||||
break;
|
||||
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
|
||||
/*
|
||||
PBEParameter ::= SEQUENCE {
|
||||
salt OCTET STRING (SIZE(8)),
|
||||
iterationCount INTEGER }
|
||||
*/
|
||||
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_SEQUENCE) {
|
||||
return false;
|
||||
}
|
||||
if ($this->_decodeLength($temp) != strlen($temp)) {
|
||||
return false;
|
||||
}
|
||||
$this->_string_shift($temp); // assume it's an octet string
|
||||
$salt = $this->_string_shift($temp, $this->_decodeLength($temp));
|
||||
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_INTEGER) {
|
||||
return false;
|
||||
}
|
||||
$this->_decodeLength($temp);
|
||||
list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
|
||||
$this->_string_shift($key); // assume it's an octet string
|
||||
$length = $this->_decodeLength($key);
|
||||
if (strlen($key) != $length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!class_exists('Crypt_DES')) {
|
||||
include_once 'Crypt/DES.php';
|
||||
}
|
||||
$crypto = new Crypt_DES();
|
||||
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount);
|
||||
$key = $crypto->decrypt($key);
|
||||
if ($key === false) {
|
||||
return false;
|
||||
}
|
||||
return $this->_parseKey($key, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
/* intended for keys for which OpenSSL's asn1parse returns the following:
|
||||
|
||||
0:d=0 hl=4 l= 290 cons: SEQUENCE
|
||||
|
@ -1077,7 +1215,6 @@ class Crypt_RSA
|
|||
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
|
||||
17:d=2 hl=2 l= 0 prim: NULL
|
||||
19:d=1 hl=4 l= 271 prim: BIT STRING */
|
||||
$this->_string_shift($key, $this->_decodeLength($key));
|
||||
$tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
|
||||
$this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
|
||||
// "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
|
||||
|
@ -1479,6 +1616,19 @@ class Crypt_RSA
|
|||
$this->publicExponent = false;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
|
||||
case CRYPT_RSA_PUBLIC_FORMAT_RAW:
|
||||
$this->setPublicKey();
|
||||
break;
|
||||
case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
|
||||
switch (true) {
|
||||
case strpos($key, '-BEGIN PUBLIC KEY-') !== false:
|
||||
case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false:
|
||||
$this->setPublicKey();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1505,7 +1655,9 @@ class Crypt_RSA
|
|||
* used in certain contexts. For example, in SSH-2, RSA authentication works by sending the public key along with a
|
||||
* message signed by the private key to the server. The SSH-2 server looks the public key up in an index of public keys
|
||||
* and if it's present then proceeds to verify the signature. Problem is, if your private key doesn't include the public
|
||||
* exponent this won't work unless you manually add the public exponent.
|
||||
* exponent this won't work unless you manually add the public exponent. phpseclib tries to guess if the key being used
|
||||
* is the public key but in the event that it guesses incorrectly you might still want to explicitly set the key as being
|
||||
* public.
|
||||
*
|
||||
* Do note that when a new key is loaded the index will be cleared.
|
||||
*
|
||||
|
@ -1561,6 +1713,40 @@ class Crypt_RSA
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the private key
|
||||
*
|
||||
* If phpseclib guessed a private key was a public key and loaded it as such it might be desirable to force
|
||||
* phpseclib to treat the key as a private key. This function will do that.
|
||||
*
|
||||
* Do note that when a new key is loaded the index will be cleared.
|
||||
*
|
||||
* Returns true on success, false on failure
|
||||
*
|
||||
* @see getPublicKey()
|
||||
* @access public
|
||||
* @param String $key optional
|
||||
* @param Integer $type optional
|
||||
* @return Boolean
|
||||
*/
|
||||
function setPrivateKey($key = false, $type = false)
|
||||
{
|
||||
if ($key === false && !empty($this->publicExponent)) {
|
||||
unset($this->publicExponent);
|
||||
return true;
|
||||
}
|
||||
|
||||
$rsa = new Crypt_RSA();
|
||||
if (!$rsa->loadKey($key, $type)) {
|
||||
return false;
|
||||
}
|
||||
unset($rsa->publicExponent);
|
||||
|
||||
// don't overwrite the old key if the new key is invalid
|
||||
$this->loadKey($rsa);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public key
|
||||
*
|
||||
|
@ -1573,7 +1759,7 @@ class Crypt_RSA
|
|||
* @param String $key
|
||||
* @param Integer $type optional
|
||||
*/
|
||||
function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
||||
function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
|
||||
{
|
||||
if (empty($this->modulus) || empty($this->publicExponent)) {
|
||||
return false;
|
||||
|
@ -1620,7 +1806,7 @@ class Crypt_RSA
|
|||
* @param String $key
|
||||
* @param Integer $type optional
|
||||
*/
|
||||
function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
||||
function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8)
|
||||
{
|
||||
if (empty($this->modulus) || empty($this->exponent)) {
|
||||
return false;
|
||||
|
@ -2275,11 +2461,11 @@ class Crypt_RSA
|
|||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
|
||||
*
|
||||
* For compatability purposes, this function departs slightly from the description given in RFC3447.
|
||||
* For compatibility purposes, this function departs slightly from the description given in RFC3447.
|
||||
* The reason being that RFC2313#section-8.1 (PKCS#1 v1.5) states that ciphertext's encrypted by the
|
||||
* private key should have the second byte set to either 0 or 1 and that ciphertext's encrypted by the
|
||||
* public key should have the second byte set to 2. In RFC3447 (PKCS#1 v2.1), the second byte is supposed
|
||||
* to be 2 regardless of which key is used. For compatability purposes, we'll just check to make sure the
|
||||
* to be 2 regardless of which key is used. For compatibility purposes, we'll just check to make sure the
|
||||
* second byte is 2 or less. If it is, we'll accept the decrypted string as valid.
|
||||
*
|
||||
* As a consequence of this, a private key encrypted ciphertext produced with Crypt_RSA may not decrypt
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
/**
|
||||
* Random Number Generator
|
||||
*
|
||||
* The idea behind this function is that it can be easily replaced with your own crypt_random_string()
|
||||
* function. eg. maybe you have a better source of entropy for creating the initial states or whatever.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/Random.php');
|
||||
* include 'Crypt/Random.php';
|
||||
*
|
||||
* echo bin2hex(crypt_random_string(8));
|
||||
* ?>
|
||||
|
@ -35,181 +38,210 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Random
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
/**
|
||||
* "Is Windows" test
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
||||
// laravel is a PHP framework that utilizes phpseclib. laravel workbenches may, independently,
|
||||
// have phpseclib as a requirement as well. if you're developing such a program you may encounter
|
||||
// a "Cannot redeclare crypt_random_string()" error.
|
||||
if (!function_exists('crypt_random_string')) {
|
||||
/**
|
||||
* "Is Windows" test
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
||||
|
||||
/**
|
||||
* Generate a random string.
|
||||
*
|
||||
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
|
||||
* microoptimizations because this function has the potential of being called a huge number of times.
|
||||
* eg. for RSA key generation.
|
||||
*
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function crypt_random_string($length)
|
||||
{
|
||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||
return mcrypt_create_iv($length);
|
||||
}
|
||||
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
||||
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||
// call php_win32_get_random_bytes():
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||
//
|
||||
// php_win32_get_random_bytes() is defined thusly:
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
||||
//
|
||||
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
||||
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
} else {
|
||||
// method 1. the fastest
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
// method 2
|
||||
static $fp = true;
|
||||
if ($fp === true) {
|
||||
// warning's will be output unles the error suppression operator is used. errors such as
|
||||
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
}
|
||||
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||
return fread($fp, $length);
|
||||
}
|
||||
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
||||
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
||||
// restrictions or some such
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||
}
|
||||
}
|
||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||
|
||||
// cascade entropy across multiple PHP instances by fixing the session and collecting all
|
||||
// environmental variables, including the previous session data and the current session
|
||||
// data.
|
||||
//
|
||||
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
|
||||
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
||||
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
||||
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
||||
// however. a ton of people visiting the website. obviously you don't want to base your seeding
|
||||
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
||||
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
||||
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
||||
// another user visits the page and the serialization of their data is utilized along with the
|
||||
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
|
||||
// a hash of the session data before that). certainly an attacker should be assumed to have
|
||||
// full control over his own http requests. he, however, is not going to have control over
|
||||
// everyone's http requests.
|
||||
static $crypto = false, $v;
|
||||
if ($crypto === false) {
|
||||
// save old session data
|
||||
$old_session_id = session_id();
|
||||
$old_use_cookies = ini_get('session.use_cookies');
|
||||
$old_session_cache_limiter = session_cache_limiter();
|
||||
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
|
||||
if ($old_session_id != '') {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
session_id(1);
|
||||
ini_set('session.use_cookies', 0);
|
||||
session_cache_limiter('');
|
||||
session_start();
|
||||
|
||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||
serialize($_SERVER) .
|
||||
serialize($_POST) .
|
||||
serialize($_GET) .
|
||||
serialize($_COOKIE) .
|
||||
serialize($GLOBALS) .
|
||||
serialize($_SESSION) .
|
||||
serialize($_OLD_SESSION)
|
||||
));
|
||||
if (!isset($_SESSION['count'])) {
|
||||
$_SESSION['count'] = 0;
|
||||
}
|
||||
$_SESSION['count']++;
|
||||
|
||||
session_write_close();
|
||||
|
||||
// restore old session data
|
||||
if ($old_session_id != '') {
|
||||
session_id($old_session_id);
|
||||
session_start();
|
||||
ini_set('session.use_cookies', $old_use_cookies);
|
||||
session_cache_limiter($old_session_cache_limiter);
|
||||
/**
|
||||
* Generate a random string.
|
||||
*
|
||||
* Although microoptimizations are generally discouraged as they impair readability this function is ripe with
|
||||
* microoptimizations because this function has the potential of being called a huge number of times.
|
||||
* eg. for RSA key generation.
|
||||
*
|
||||
* @param Integer $length
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function crypt_random_string($length)
|
||||
{
|
||||
if (CRYPT_RANDOM_IS_WINDOWS) {
|
||||
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
|
||||
// ie. class_alias is a function that was introduced in PHP 5.3
|
||||
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
|
||||
return mcrypt_create_iv($length);
|
||||
}
|
||||
// method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
|
||||
// to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
|
||||
// openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
|
||||
// call php_win32_get_random_bytes():
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
|
||||
//
|
||||
// php_win32_get_random_bytes() is defined thusly:
|
||||
//
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
|
||||
//
|
||||
// we're calling it, all the same, in the off chance that the mcrypt extension is not available
|
||||
if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
} else {
|
||||
if ($_OLD_SESSION !== false) {
|
||||
$_SESSION = $_OLD_SESSION;
|
||||
unset($_OLD_SESSION);
|
||||
} else {
|
||||
unset($_SESSION);
|
||||
// method 1. the fastest
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return openssl_random_pseudo_bytes($length);
|
||||
}
|
||||
// method 2
|
||||
static $fp = true;
|
||||
if ($fp === true) {
|
||||
// warning's will be output unles the error suppression operator is used. errors such as
|
||||
// "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
|
||||
$fp = @fopen('/dev/urandom', 'rb');
|
||||
}
|
||||
if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
|
||||
return fread($fp, $length);
|
||||
}
|
||||
// method 3. pretty much does the same thing as method 2 per the following url:
|
||||
// https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
|
||||
// surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
|
||||
// not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
|
||||
// restrictions or some such
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
|
||||
}
|
||||
}
|
||||
// at this point we have no choice but to use a pure-PHP CSPRNG
|
||||
|
||||
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
|
||||
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
|
||||
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
|
||||
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
|
||||
// cascade entropy across multiple PHP instances by fixing the session and collecting all
|
||||
// environmental variables, including the previous session data and the current session
|
||||
// data.
|
||||
//
|
||||
// http://tools.ietf.org/html/rfc4253#section-7.2
|
||||
//
|
||||
// see the is_string($crypto) part for an example of how to expand the keys
|
||||
$key = pack('H*', sha1($seed . 'A'));
|
||||
$iv = pack('H*', sha1($seed . 'C'));
|
||||
// mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
|
||||
// easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
|
||||
// PHP isn't low level to be able to use those as sources and on a web server there's not likely
|
||||
// going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
|
||||
// however, a ton of people visiting the website. obviously you don't want to base your seeding
|
||||
// soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
|
||||
// by the user and (2) this isn't just looking at the data sent by the current user - it's based
|
||||
// on the data sent by all users. one user requests the page and a hash of their info is saved.
|
||||
// another user visits the page and the serialization of their data is utilized along with the
|
||||
// server envirnment stuff and a hash of the previous http request data (which itself utilizes
|
||||
// a hash of the session data before that). certainly an attacker should be assumed to have
|
||||
// full control over his own http requests. he, however, is not going to have control over
|
||||
// everyone's http requests.
|
||||
static $crypto = false, $v;
|
||||
if ($crypto === false) {
|
||||
// save old session data
|
||||
$old_session_id = session_id();
|
||||
$old_use_cookies = ini_get('session.use_cookies');
|
||||
$old_session_cache_limiter = session_cache_limiter();
|
||||
$_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
|
||||
if ($old_session_id != '') {
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
// ciphers are used as per the nist.gov link below. also, see this link:
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
||||
switch (true) {
|
||||
case class_exists('Crypt_AES'):
|
||||
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_TripleDES'):
|
||||
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_DES'):
|
||||
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||
break;
|
||||
case class_exists('Crypt_RC4'):
|
||||
$crypto = new Crypt_RC4();
|
||||
break;
|
||||
default:
|
||||
$crypto = $seed;
|
||||
return crypt_random_string($length);
|
||||
session_id(1);
|
||||
ini_set('session.use_cookies', 0);
|
||||
session_cache_limiter('');
|
||||
session_start();
|
||||
|
||||
$v = $seed = $_SESSION['seed'] = pack('H*', sha1(
|
||||
serialize($_SERVER) .
|
||||
serialize($_POST) .
|
||||
serialize($_GET) .
|
||||
serialize($_COOKIE) .
|
||||
serialize($GLOBALS) .
|
||||
serialize($_SESSION) .
|
||||
serialize($_OLD_SESSION)
|
||||
));
|
||||
if (!isset($_SESSION['count'])) {
|
||||
$_SESSION['count'] = 0;
|
||||
}
|
||||
$_SESSION['count']++;
|
||||
|
||||
session_write_close();
|
||||
|
||||
// restore old session data
|
||||
if ($old_session_id != '') {
|
||||
session_id($old_session_id);
|
||||
session_start();
|
||||
ini_set('session.use_cookies', $old_use_cookies);
|
||||
session_cache_limiter($old_session_cache_limiter);
|
||||
} else {
|
||||
if ($_OLD_SESSION !== false) {
|
||||
$_SESSION = $_OLD_SESSION;
|
||||
unset($_OLD_SESSION);
|
||||
} else {
|
||||
unset($_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
// in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
|
||||
// the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
|
||||
// if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
|
||||
// original hash and the current hash. we'll be emulating that. for more info see the following URL:
|
||||
//
|
||||
// http://tools.ietf.org/html/rfc4253#section-7.2
|
||||
//
|
||||
// see the is_string($crypto) part for an example of how to expand the keys
|
||||
$key = pack('H*', sha1($seed . 'A'));
|
||||
$iv = pack('H*', sha1($seed . 'C'));
|
||||
|
||||
// ciphers are used as per the nist.gov link below. also, see this link:
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
|
||||
switch (true) {
|
||||
case phpseclib_resolve_include_path('Crypt/AES.php'):
|
||||
if (!class_exists('Crypt_AES')) {
|
||||
include_once 'AES.php';
|
||||
}
|
||||
$crypto = new Crypt_AES(CRYPT_AES_MODE_CTR);
|
||||
break;
|
||||
case phpseclib_resolve_include_path('Crypt/Twofish.php'):
|
||||
if (!class_exists('Crypt_Twofish')) {
|
||||
include_once 'Twofish.php';
|
||||
}
|
||||
$crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR);
|
||||
break;
|
||||
case phpseclib_resolve_include_path('Crypt/Blowfish.php'):
|
||||
if (!class_exists('Crypt_Blowfish')) {
|
||||
include_once 'Blowfish.php';
|
||||
}
|
||||
$crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR);
|
||||
break;
|
||||
case phpseclib_resolve_include_path('Crypt/TripleDES.php'):
|
||||
if (!class_exists('Crypt_TripleDES')) {
|
||||
include_once 'TripleDES.php';
|
||||
}
|
||||
$crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR);
|
||||
break;
|
||||
case phpseclib_resolve_include_path('Crypt/DES.php'):
|
||||
if (!class_exists('Crypt_DES')) {
|
||||
include_once 'DES.php';
|
||||
}
|
||||
$crypto = new Crypt_DES(CRYPT_DES_MODE_CTR);
|
||||
break;
|
||||
case phpseclib_resolve_include_path('Crypt/RC4.php'):
|
||||
if (!class_exists('Crypt_RC4')) {
|
||||
include_once 'RC4.php';
|
||||
}
|
||||
$crypto = new Crypt_RC4();
|
||||
break;
|
||||
default:
|
||||
user_error('crypt_random_string requires at least one symmetric cipher be loaded');
|
||||
return false;
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
$crypto->setIV($iv);
|
||||
$crypto->enableContinuousBuffer();
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
$crypto->setIV($iv);
|
||||
$crypto->enableContinuousBuffer();
|
||||
}
|
||||
//return $crypto->encrypt(str_repeat("\0", $length));
|
||||
|
||||
if (is_string($crypto)) {
|
||||
// the following is based off of ANSI X9.31:
|
||||
//
|
||||
// http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
|
||||
|
@ -218,29 +250,51 @@ function crypt_random_string($length)
|
|||
//
|
||||
// http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
|
||||
// (do a search for "ANS X9.31 A.2.4")
|
||||
//
|
||||
// ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see
|
||||
// later on in the code) but if they're not we'll use sha1
|
||||
$result = '';
|
||||
while (strlen($result) < $length) { // each loop adds 20 bytes
|
||||
// microtime() isn't packed as "densely" as it could be but then neither is that the idea.
|
||||
// the idea is simply to ensure that each "block" has a unique element to it.
|
||||
$i = pack('H*', sha1(microtime()));
|
||||
$r = pack('H*', sha1($i ^ $v));
|
||||
$v = pack('H*', sha1($r ^ $i));
|
||||
while (strlen($result) < $length) {
|
||||
$i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
|
||||
$r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
|
||||
$v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
|
||||
//return $crypto->encrypt(str_repeat("\0", $length));
|
||||
|
||||
$result = '';
|
||||
while (strlen($result) < $length) {
|
||||
$i = $crypto->encrypt(microtime());
|
||||
$r = $crypto->encrypt($i ^ $v);
|
||||
$v = $crypto->encrypt($r ^ $i);
|
||||
$result.= $r;
|
||||
}
|
||||
return substr($result, 0, $length);
|
||||
}
|
||||
|
||||
if (!function_exists('phpseclib_resolve_include_path')) {
|
||||
/**
|
||||
* Resolve filename against the include path.
|
||||
*
|
||||
* Wrapper around stream_resolve_include_path() (which was introduced in
|
||||
* PHP 5.3.2) with fallback implementation for earlier PHP versions.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return mixed Filename (string) on success, false otherwise.
|
||||
* @access public
|
||||
*/
|
||||
function phpseclib_resolve_include_path($filename)
|
||||
{
|
||||
if (function_exists('stream_resolve_include_path')) {
|
||||
return stream_resolve_include_path($filename);
|
||||
}
|
||||
|
||||
// handle non-relative paths
|
||||
if (file_exists($filename)) {
|
||||
return realpath($filename);
|
||||
}
|
||||
|
||||
$paths = PATH_SEPARATOR == ':' ?
|
||||
preg_split('#(?<!phar):#', get_include_path()) :
|
||||
explode(PATH_SEPARATOR, get_include_path());
|
||||
foreach ($paths as $prefix) {
|
||||
// path's specified in include_path don't always end in /
|
||||
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
|
||||
$file = $prefix . $ds . $filename;
|
||||
if (file_exists($file)) {
|
||||
return realpath($file);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/Rijndael.php');
|
||||
* include 'Crypt/Rijndael.php';
|
||||
*
|
||||
* $rijndael = new Crypt_Rijndael();
|
||||
*
|
||||
|
@ -65,7 +65,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_Rijndael
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -120,7 +120,7 @@ define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB);
|
|||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_Rijndael::Crypt_Rijndael()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
|
@ -137,7 +137,6 @@ define('CRYPT_RIJNDAEL_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
*
|
||||
* @package Crypt_Rijndael
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_Rijndael extends Crypt_Base
|
||||
|
@ -167,7 +166,7 @@ class Crypt_Rijndael extends Crypt_Base
|
|||
* Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not.
|
||||
* Crypt_Rijndael determines automatically whether mcrypt is useable
|
||||
* or not for the current $block_size/$key_size.
|
||||
* In case of, $cipher_name_mcrypt will be set dynamicaly at run time accordingly.
|
||||
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
|
||||
*
|
||||
* @see Crypt_Base::cipher_name_mcrypt
|
||||
* @see Crypt_Base::engine
|
||||
|
@ -676,34 +675,6 @@ class Crypt_Rijndael extends Crypt_Base
|
|||
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
|
||||
);
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_RIJNDAEL_MODE_ECB
|
||||
*
|
||||
* - CRYPT_RIJNDAEL_MODE_CBC
|
||||
*
|
||||
* - CRYPT_RIJNDAEL_MODE_CTR
|
||||
*
|
||||
* - CRYPT_RIJNDAEL_MODE_CFB
|
||||
*
|
||||
* - CRYPT_RIJNDAEL_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_Rijndael($mode = CRYPT_RIJNDAEL_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Base($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
|
@ -731,9 +702,15 @@ class Crypt_Rijndael extends Crypt_Base
|
|||
case $length <= 16:
|
||||
$this->key_size = 16;
|
||||
break;
|
||||
case $length <= 20:
|
||||
$this->key_size = 20;
|
||||
break;
|
||||
case $length <= 24:
|
||||
$this->key_size = 24;
|
||||
break;
|
||||
case $length <= 28:
|
||||
$this->key_size = 28;
|
||||
break;
|
||||
default:
|
||||
$this->key_size = 32;
|
||||
}
|
||||
|
@ -755,7 +732,7 @@ class Crypt_Rijndael extends Crypt_Base
|
|||
* you should not setKeyLength(160) or setKeyLength(224).
|
||||
*
|
||||
* Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
|
||||
* the mcrypt php extention, even if available.
|
||||
* the mcrypt php extension, even if available.
|
||||
* This results then in slower encryption.
|
||||
*
|
||||
* @access public
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/TripleDES.php');
|
||||
* include 'Crypt/TripleDES.php';
|
||||
*
|
||||
* $des = new Crypt_TripleDES();
|
||||
*
|
||||
|
@ -47,7 +47,7 @@
|
|||
* @category Crypt
|
||||
* @package Crypt_TripleDES
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -78,7 +78,6 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
|
|||
*
|
||||
* @package Crypt_TripleDES
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_TripleDES extends Crypt_DES
|
||||
|
@ -180,7 +179,7 @@ class Crypt_TripleDES extends Crypt_DES
|
|||
*
|
||||
* - CRYPT_DES_MODE_3CBC
|
||||
*
|
||||
* If not explictly set, CRYPT_DES_MODE_CBC will be used.
|
||||
* If not explicitly set, CRYPT_DES_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_DES::Crypt_DES()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
|
@ -193,7 +192,7 @@ class Crypt_TripleDES extends Crypt_DES
|
|||
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
||||
// and additional flag us internally as 3CBC
|
||||
case CRYPT_DES_MODE_3CBC:
|
||||
parent::Crypt_DES(CRYPT_DES_MODE_CBC);
|
||||
parent::Crypt_Base(CRYPT_DES_MODE_CBC);
|
||||
$this->mode_3cbc = true;
|
||||
|
||||
// This three $des'es will do the 3CBC work (if $key > 64bits)
|
||||
|
@ -210,14 +209,14 @@ class Crypt_TripleDES extends Crypt_DES
|
|||
break;
|
||||
// If not 3CBC, we init as usual
|
||||
default:
|
||||
parent::Crypt_DES($mode);
|
||||
parent::Crypt_Base($mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initialization vector. (optional)
|
||||
*
|
||||
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
|
||||
* SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed
|
||||
* to be all zero's.
|
||||
*
|
||||
* @see Crypt_Base::setIV()
|
||||
|
@ -289,8 +288,12 @@ class Crypt_TripleDES extends Crypt_DES
|
|||
// if the key is smaller then 8, do what we'd normally do
|
||||
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
||||
return $this->des[2]->encrypt(
|
||||
$this->des[1]->decrypt(
|
||||
$this->des[0]->encrypt($this->_pad($plaintext))));
|
||||
$this->des[1]->decrypt(
|
||||
$this->des[0]->encrypt(
|
||||
$this->_pad($plaintext)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::encrypt($plaintext);
|
||||
|
@ -307,9 +310,15 @@ class Crypt_TripleDES extends Crypt_DES
|
|||
function decrypt($ciphertext)
|
||||
{
|
||||
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
||||
return $this->_unpad($this->des[0]->decrypt(
|
||||
$this->des[1]->encrypt(
|
||||
$this->des[2]->decrypt(str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")))));
|
||||
return $this->_unpad(
|
||||
$this->des[0]->decrypt(
|
||||
$this->des[1]->encrypt(
|
||||
$this->des[2]->decrypt(
|
||||
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::decrypt($ciphertext);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/Twofish.php');
|
||||
* include 'Crypt/Twofish.php';
|
||||
*
|
||||
* $twofish = new Crypt_Twofish();
|
||||
*
|
||||
|
@ -48,9 +48,8 @@
|
|||
* @package Crypt_Twofish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @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
|
||||
* @version 1.0
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
|
@ -104,7 +103,7 @@ define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
|
|||
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see Crypt_Twofish::Crypt_Twofish()
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
|
@ -122,7 +121,6 @@ define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
|
|||
* @package Crypt_Twofish
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
||||
* @version 1.0
|
||||
* @access public
|
||||
*/
|
||||
class Crypt_Twofish extends Crypt_Base
|
||||
|
@ -448,34 +446,6 @@ class Crypt_Twofish extends Crypt_Base
|
|||
*/
|
||||
var $kl;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* Determines whether or not the mcrypt extension should be used.
|
||||
*
|
||||
* $mode could be:
|
||||
*
|
||||
* - CRYPT_TWOFISH_MODE_ECB
|
||||
*
|
||||
* - CRYPT_TWOFISH_MODE_CBC
|
||||
*
|
||||
* - CRYPT_TWOFISH_MODE_CTR
|
||||
*
|
||||
* - CRYPT_TWOFISH_MODE_CFB
|
||||
*
|
||||
* - CRYPT_TWOFISH_MODE_OFB
|
||||
*
|
||||
* If not explictly set, CRYPT_TWOFISH_MODE_CBC will be used.
|
||||
*
|
||||
* @see Crypt_Base::Crypt_Base()
|
||||
* @param optional Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function Crypt_Twofish($mode = CRYPT_TWOFISH_MODE_CBC)
|
||||
{
|
||||
parent::Crypt_Base($mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key.
|
||||
*
|
||||
|
@ -709,10 +679,12 @@ class Crypt_Twofish extends Crypt_Base
|
|||
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
return pack("V4", $K[4] ^ $R2,
|
||||
$K[5] ^ $R3,
|
||||
$K[6] ^ $R0,
|
||||
$K[7] ^ $R1);
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -763,10 +735,12 @@ class Crypt_Twofish extends Crypt_Base
|
|||
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
return pack("V4", $K[0] ^ $R2,
|
||||
$K[1] ^ $R3,
|
||||
$K[2] ^ $R0,
|
||||
$K[3] ^ $R1);
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* @category File
|
||||
* @package File_ANSI
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -41,7 +41,6 @@
|
|||
*
|
||||
* @package File_ANSI
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.3.0
|
||||
* @access public
|
||||
*/
|
||||
class File_ANSI
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
* @category File
|
||||
* @package File_ASN1
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -112,7 +112,6 @@ define('FILE_ASN1_TYPE_ANY', -2);
|
|||
*
|
||||
* @package File_ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.3.0
|
||||
* @access public
|
||||
*/
|
||||
class File_ASN1_Element
|
||||
|
@ -143,7 +142,6 @@ class File_ASN1_Element
|
|||
*
|
||||
* @package File_ASN1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.3.0
|
||||
* @access public
|
||||
*/
|
||||
class File_ASN1
|
||||
|
@ -164,7 +162,7 @@ class File_ASN1
|
|||
* @access private
|
||||
* @link http://php.net/class.datetime
|
||||
*/
|
||||
var $format = 'D, d M y H:i:s O';
|
||||
var $format = 'D, d M Y H:i:s O';
|
||||
|
||||
/**
|
||||
* Default date format
|
||||
|
@ -274,7 +272,8 @@ class File_ASN1
|
|||
}
|
||||
|
||||
$this->encoded = $encoded;
|
||||
return $this->_decode_ber($encoded);
|
||||
// encapsulate in an array for BC with the old decodeBER
|
||||
return array($this->_decode_ber($encoded));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,215 +288,245 @@ class File_ASN1
|
|||
* @return Array
|
||||
* @access private
|
||||
*/
|
||||
function _decode_ber(&$encoded, $start = 0)
|
||||
function _decode_ber($encoded, $start = 0)
|
||||
{
|
||||
$decoded = array();
|
||||
$current = array('start' => $start);
|
||||
|
||||
while ( strlen($encoded) ) {
|
||||
$current = array('start' => $start);
|
||||
$type = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
|
||||
$type = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
$constructed = ($type >> 5) & 1;
|
||||
|
||||
$constructed = ($type >> 5) & 1;
|
||||
|
||||
$tag = $type & 0x1F;
|
||||
if ($tag == 0x1F) {
|
||||
$tag = 0;
|
||||
// process septets (since the eighth bit is ignored, it's not an octet)
|
||||
do {
|
||||
$loop = ord($encoded[0]) >> 7;
|
||||
$tag <<= 7;
|
||||
$tag |= ord($this->_string_shift($encoded)) & 0x7F;
|
||||
$start++;
|
||||
} while ( $loop );
|
||||
}
|
||||
|
||||
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
||||
$length = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
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
|
||||
// immediately available." -- paragraph 8.1.3.2.c
|
||||
//if ( !$constructed ) {
|
||||
// return false;
|
||||
//}
|
||||
$length = strlen($encoded);
|
||||
} 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
|
||||
// support it up to four.
|
||||
$length&= 0x7F;
|
||||
$temp = $this->_string_shift($encoded, $length);
|
||||
// tags of indefinite length don't really have a header length; this length includes the tag
|
||||
$current+= array('headerlength' => $length + 2);
|
||||
$start+= $length;
|
||||
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
|
||||
} else {
|
||||
$current+= array('headerlength' => 2);
|
||||
}
|
||||
|
||||
// End-of-content, see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
|
||||
if (!$type && !$length) {
|
||||
return $decoded;
|
||||
}
|
||||
$content = $this->_string_shift($encoded, $length);
|
||||
|
||||
/* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
|
||||
built-in types. It defines an application-independent data type that must be distinguishable from all other
|
||||
data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
|
||||
have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
|
||||
a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
|
||||
alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
|
||||
data type; the term CONTEXT-SPECIFIC does not appear.
|
||||
|
||||
-- http://www.obj-sys.com/asn1tutorial/node12.html */
|
||||
$class = ($type >> 6) & 3;
|
||||
switch ($class) {
|
||||
case FILE_ASN1_CLASS_APPLICATION:
|
||||
case FILE_ASN1_CLASS_PRIVATE:
|
||||
case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
|
||||
$decoded[] = array(
|
||||
'type' => $class,
|
||||
'constant' => $tag,
|
||||
'content' => $constructed ? $this->_decode_ber($content, $start) : $content,
|
||||
'length' => $length + $start - $current['start']
|
||||
) + $current;
|
||||
$start+= $length;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
$current+= array('type' => $tag);
|
||||
|
||||
// decode UNIVERSAL tags
|
||||
switch ($tag) {
|
||||
case FILE_ASN1_TYPE_BOOLEAN:
|
||||
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1
|
||||
//if (strlen($content) != 1) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = (bool) ord($content[0]);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_INTEGER:
|
||||
case FILE_ASN1_TYPE_ENUMERATED:
|
||||
$current['content'] = new Math_BigInteger($content, -256);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_REAL: // not currently supported
|
||||
return false;
|
||||
case FILE_ASN1_TYPE_BIT_STRING:
|
||||
// The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
|
||||
// the number of unused bits in the final subsequent octet. The number shall be in the range zero to
|
||||
// seven.
|
||||
if (!$constructed) {
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length-= strlen($content);
|
||||
$last = count($temp) - 1;
|
||||
for ($i = 0; $i < $last; $i++) {
|
||||
// all subtags should be bit strings
|
||||
//if ($temp[$i]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'].= substr($temp[$i]['content'], 1);
|
||||
}
|
||||
// all subtags should be bit strings
|
||||
//if ($temp[$last]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OCTET_STRING:
|
||||
if (!$constructed) {
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length-= strlen($content);
|
||||
for ($i = 0, $size = count($temp); $i < $size; $i++) {
|
||||
// all subtags should be octet strings
|
||||
//if ($temp[$i]['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'].= $temp[$i]['content'];
|
||||
}
|
||||
// $length =
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_NULL:
|
||||
// "The contents octets shall not contain any octets." -- paragraph 8.8.2
|
||||
//if (strlen($content)) {
|
||||
// return false;
|
||||
//}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_SEQUENCE:
|
||||
case FILE_ASN1_TYPE_SET:
|
||||
$current['content'] = $this->_decode_ber($content, $start);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
|
||||
$valuen = 0;
|
||||
// process septets
|
||||
while (strlen($content)) {
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$valuen <<= 7;
|
||||
$valuen |= $temp & 0x7F;
|
||||
if (~$temp & 0x80) {
|
||||
$current['content'].= ".$valuen";
|
||||
$valuen = 0;
|
||||
}
|
||||
}
|
||||
// the eighth bit of the last byte should not be 1
|
||||
//if ($temp >> 7) {
|
||||
// return false;
|
||||
//}
|
||||
break;
|
||||
/* Each character string type shall be encoded as if it had been declared:
|
||||
[UNIVERSAL x] IMPLICIT OCTET STRING
|
||||
|
||||
-- X.690-0207.pdf#page=23 (paragraph 8.21.3)
|
||||
|
||||
Per that, we're not going to do any validation. If there are any illegal characters in the string,
|
||||
we don't really care */
|
||||
case FILE_ASN1_TYPE_NUMERIC_STRING:
|
||||
// 0,1,2,3,4,5,6,7,8,9, and space
|
||||
case FILE_ASN1_TYPE_PRINTABLE_STRING:
|
||||
// Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
|
||||
// hyphen, full stop, solidus, colon, equal sign, question mark
|
||||
case FILE_ASN1_TYPE_TELETEX_STRING:
|
||||
// The Teletex character set in CCITT's T61, space, and delete
|
||||
// see http://en.wikipedia.org/wiki/Teletex#Character_sets
|
||||
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
|
||||
// The Videotex character set in CCITT's T.100 and T.101, space, and delete
|
||||
case FILE_ASN1_TYPE_VISIBLE_STRING:
|
||||
// Printing character sets of international ASCII, and space
|
||||
case FILE_ASN1_TYPE_IA5_STRING:
|
||||
// International Alphabet 5 (International ASCII)
|
||||
case FILE_ASN1_TYPE_GRAPHIC_STRING:
|
||||
// All registered G sets, and space
|
||||
case FILE_ASN1_TYPE_GENERAL_STRING:
|
||||
// All registered C and G sets, space and delete
|
||||
case FILE_ASN1_TYPE_UTF8_STRING:
|
||||
// ????
|
||||
case FILE_ASN1_TYPE_BMP_STRING:
|
||||
$current['content'] = $content;
|
||||
break;
|
||||
case FILE_ASN1_TYPE_UTC_TIME:
|
||||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
$current['content'] = $this->_decodeTime($content, $tag);
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
$start+= $length;
|
||||
$decoded[] = $current + array('length' => $start - $current['start']);
|
||||
$tag = $type & 0x1F;
|
||||
if ($tag == 0x1F) {
|
||||
$tag = 0;
|
||||
// process septets (since the eighth bit is ignored, it's not an octet)
|
||||
do {
|
||||
$loop = ord($encoded[0]) >> 7;
|
||||
$tag <<= 7;
|
||||
$tag |= ord($this->_string_shift($encoded)) & 0x7F;
|
||||
$start++;
|
||||
} while ( $loop );
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
||||
$length = ord($this->_string_shift($encoded));
|
||||
$start++;
|
||||
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
|
||||
// immediately available." -- paragraph 8.1.3.2.c
|
||||
$length = strlen($encoded);
|
||||
} 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
|
||||
// support it up to four.
|
||||
$length&= 0x7F;
|
||||
$temp = $this->_string_shift($encoded, $length);
|
||||
// tags of indefinte length don't really have a header length; this length includes the tag
|
||||
$current+= array('headerlength' => $length + 2);
|
||||
$start+= $length;
|
||||
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
|
||||
} else {
|
||||
$current+= array('headerlength' => 2);
|
||||
}
|
||||
|
||||
$content = $this->_string_shift($encoded, $length);
|
||||
|
||||
// at this point $length can be overwritten. it's only accurate for definite length things as is
|
||||
|
||||
/* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
|
||||
built-in types. It defines an application-independent data type that must be distinguishable from all other
|
||||
data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
|
||||
have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
|
||||
a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
|
||||
alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
|
||||
data type; the term CONTEXT-SPECIFIC does not appear.
|
||||
|
||||
-- http://www.obj-sys.com/asn1tutorial/node12.html */
|
||||
$class = ($type >> 6) & 3;
|
||||
switch ($class) {
|
||||
case FILE_ASN1_CLASS_APPLICATION:
|
||||
case FILE_ASN1_CLASS_PRIVATE:
|
||||
case FILE_ASN1_CLASS_CONTEXT_SPECIFIC:
|
||||
if (!$constructed) {
|
||||
return array(
|
||||
'type' => $class,
|
||||
'constant' => $tag,
|
||||
'content' => $content,
|
||||
'length' => $length + $start - $current['start']
|
||||
);
|
||||
}
|
||||
|
||||
$newcontent = array();
|
||||
if (strlen($content)) {
|
||||
$newcontent = $this->_decode_ber($content, $start);
|
||||
$length = $newcontent['length'];
|
||||
if (substr($content, $length, 2) == "\0\0") {
|
||||
$length+= 2;
|
||||
}
|
||||
$start+= $length;
|
||||
$newcontent = array($newcontent);
|
||||
}
|
||||
|
||||
return array(
|
||||
'type' => $class,
|
||||
'constant' => $tag,
|
||||
// the array encapsulation is for BC with the old format
|
||||
'content' => $newcontent,
|
||||
// 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.
|
||||
// technically, it could be defined to be 2 and then another indicator could be used but whatever.
|
||||
'length' => $start - $current['start']
|
||||
) + $current;
|
||||
}
|
||||
|
||||
$current+= array('type' => $tag);
|
||||
|
||||
// decode UNIVERSAL tags
|
||||
switch ($tag) {
|
||||
case FILE_ASN1_TYPE_BOOLEAN:
|
||||
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1
|
||||
//if (strlen($content) != 1) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = (bool) ord($content[0]);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_INTEGER:
|
||||
case FILE_ASN1_TYPE_ENUMERATED:
|
||||
$current['content'] = new Math_BigInteger($content, -256);
|
||||
break;
|
||||
case FILE_ASN1_TYPE_REAL: // not currently supported
|
||||
return false;
|
||||
case FILE_ASN1_TYPE_BIT_STRING:
|
||||
// The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
|
||||
// the number of unused bits in the final subsequent octet. The number shall be in the range zero to
|
||||
// seven.
|
||||
if (!$constructed) {
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$temp = $this->_decode_ber($content, $start);
|
||||
$length-= strlen($content);
|
||||
$last = count($temp) - 1;
|
||||
for ($i = 0; $i < $last; $i++) {
|
||||
// all subtags should be bit strings
|
||||
//if ($temp[$i]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'].= substr($temp[$i]['content'], 1);
|
||||
}
|
||||
// all subtags should be bit strings
|
||||
//if ($temp[$last]['type'] != FILE_ASN1_TYPE_BIT_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OCTET_STRING:
|
||||
if (!$constructed) {
|
||||
$current['content'] = $content;
|
||||
} else {
|
||||
$current['content'] = '';
|
||||
$length = 0;
|
||||
while (substr($content, 0, 2) != "\0\0") {
|
||||
$temp = $this->_decode_ber($content, $length + $start);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
// all subtags should be octet strings
|
||||
//if ($temp['type'] != FILE_ASN1_TYPE_OCTET_STRING) {
|
||||
// return false;
|
||||
//}
|
||||
$current['content'].= $temp['content'];
|
||||
$length+= $temp['length'];
|
||||
}
|
||||
if (substr($content, 0, 2) == "\0\0") {
|
||||
$length+= 2; // +2 for the EOC
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_NULL:
|
||||
// "The contents octets shall not contain any octets." -- paragraph 8.8.2
|
||||
//if (strlen($content)) {
|
||||
// return false;
|
||||
//}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_SEQUENCE:
|
||||
case FILE_ASN1_TYPE_SET:
|
||||
$offset = 0;
|
||||
$current['content'] = array();
|
||||
while (strlen($content)) {
|
||||
// if indefinite length construction was used and we have an end-of-content string next
|
||||
// see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
|
||||
if (!isset($current['headerlength']) && substr($content, 0, 2) == "\0\0") {
|
||||
$length = $offset + 2; // +2 for the EOC
|
||||
break 2;
|
||||
}
|
||||
$temp = $this->_decode_ber($content, $start + $offset);
|
||||
$this->_string_shift($content, $temp['length']);
|
||||
$current['content'][] = $temp;
|
||||
$offset+= $temp['length'];
|
||||
}
|
||||
break;
|
||||
case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
|
||||
$valuen = 0;
|
||||
// process septets
|
||||
while (strlen($content)) {
|
||||
$temp = ord($this->_string_shift($content));
|
||||
$valuen <<= 7;
|
||||
$valuen |= $temp & 0x7F;
|
||||
if (~$temp & 0x80) {
|
||||
$current['content'].= ".$valuen";
|
||||
$valuen = 0;
|
||||
}
|
||||
}
|
||||
// the eighth bit of the last byte should not be 1
|
||||
//if ($temp >> 7) {
|
||||
// return false;
|
||||
//}
|
||||
break;
|
||||
/* Each character string type shall be encoded as if it had been declared:
|
||||
[UNIVERSAL x] IMPLICIT OCTET STRING
|
||||
|
||||
-- X.690-0207.pdf#page=23 (paragraph 8.21.3)
|
||||
|
||||
Per that, we're not going to do any validation. If there are any illegal characters in the string,
|
||||
we don't really care */
|
||||
case FILE_ASN1_TYPE_NUMERIC_STRING:
|
||||
// 0,1,2,3,4,5,6,7,8,9, and space
|
||||
case FILE_ASN1_TYPE_PRINTABLE_STRING:
|
||||
// Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
|
||||
// hyphen, full stop, solidus, colon, equal sign, question mark
|
||||
case FILE_ASN1_TYPE_TELETEX_STRING:
|
||||
// The Teletex character set in CCITT's T61, space, and delete
|
||||
// see http://en.wikipedia.org/wiki/Teletex#Character_sets
|
||||
case FILE_ASN1_TYPE_VIDEOTEX_STRING:
|
||||
// The Videotex character set in CCITT's T.100 and T.101, space, and delete
|
||||
case FILE_ASN1_TYPE_VISIBLE_STRING:
|
||||
// Printing character sets of international ASCII, and space
|
||||
case FILE_ASN1_TYPE_IA5_STRING:
|
||||
// International Alphabet 5 (International ASCII)
|
||||
case FILE_ASN1_TYPE_GRAPHIC_STRING:
|
||||
// All registered G sets, and space
|
||||
case FILE_ASN1_TYPE_GENERAL_STRING:
|
||||
// All registered C and G sets, space and delete
|
||||
case FILE_ASN1_TYPE_UTF8_STRING:
|
||||
// ????
|
||||
case FILE_ASN1_TYPE_BMP_STRING:
|
||||
$current['content'] = $content;
|
||||
break;
|
||||
case FILE_ASN1_TYPE_UTC_TIME:
|
||||
case FILE_ASN1_TYPE_GENERALIZED_TIME:
|
||||
$current['content'] = $this->_decodeTime($content, $tag);
|
||||
default:
|
||||
}
|
||||
|
||||
$start+= $length;
|
||||
|
||||
// ie. length is the length of the full TLV encoding - it's not just the length of the value
|
||||
return $current + array('length' => $start - $current['start']);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 Decode
|
||||
* ASN.1 Map
|
||||
*
|
||||
* Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
|
||||
*
|
||||
|
@ -511,7 +540,7 @@ class File_ASN1
|
|||
*/
|
||||
function asn1map($decoded, $mapping, $special = array())
|
||||
{
|
||||
if (isset($mapping['explicit'])) {
|
||||
if (isset($mapping['explicit']) && is_array($decoded['content'])) {
|
||||
$decoded = $decoded['content'][0];
|
||||
}
|
||||
|
||||
|
@ -552,7 +581,15 @@ class File_ASN1
|
|||
case $decoded['type'] == $mapping['type']:
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
// if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
|
||||
// let it through
|
||||
switch (true) {
|
||||
case $decoded['type'] < 18: // FILE_ASN1_TYPE_NUMERIC_STRING == 18
|
||||
case $decoded['type'] > 30: // FILE_ASN1_TYPE_BMP_STRING == 30
|
||||
case $mapping['type'] < 18:
|
||||
case $mapping['type'] > 30:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($mapping['implicit'])) {
|
||||
|
@ -799,16 +836,6 @@ class File_ASN1
|
|||
return $this->_encode_der($source, $mapping, null, $special);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 Encode (Helper function)
|
||||
*
|
||||
* @param String $source
|
||||
* @param Array $mapping
|
||||
* @param Integer $idx
|
||||
* @param Array $special
|
||||
* @return String
|
||||
* @access private
|
||||
*/
|
||||
/**
|
||||
* ASN.1 Encode (Helper function)
|
||||
*
|
||||
|
@ -944,6 +971,9 @@ class File_ASN1
|
|||
case FILE_ASN1_TYPE_INTEGER:
|
||||
case FILE_ASN1_TYPE_ENUMERATED:
|
||||
if (!isset($mapping['mapping'])) {
|
||||
if (is_numeric($source)) {
|
||||
$source = new Math_BigInteger($source);
|
||||
}
|
||||
$value = $source->toBytes(true);
|
||||
} else {
|
||||
$value = array_search($source, $mapping['mapping']);
|
||||
|
@ -974,6 +1004,10 @@ class File_ASN1
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
|
||||
$size = $mapping['min'] - 1;
|
||||
}
|
||||
|
||||
$offset = 8 - (($size + 1) & 7);
|
||||
$offset = $offset !== 8 ? $offset : 0;
|
||||
|
||||
|
@ -1087,7 +1121,12 @@ class File_ASN1
|
|||
}
|
||||
|
||||
if (isset($mapping['cast'])) {
|
||||
$tag = ($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast'];
|
||||
if (isset($mapping['explicit']) || $mapping['type'] == FILE_ASN1_TYPE_CHOICE) {
|
||||
$value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
|
||||
$tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast'];
|
||||
} else {
|
||||
$tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast'];
|
||||
}
|
||||
}
|
||||
|
||||
return chr($tag) . $this->_encodeLength(strlen($value)) . $value;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* @category File
|
||||
* @package File_X509
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -125,7 +125,6 @@ define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value.
|
|||
*
|
||||
* @package File_X509
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.3.1
|
||||
* @access public
|
||||
*/
|
||||
class File_X509
|
||||
|
@ -298,6 +297,14 @@ class File_X509
|
|||
*/
|
||||
var $caFlag = false;
|
||||
|
||||
/**
|
||||
* SPKAC Challenge
|
||||
*
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $challenge;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
|
@ -2166,12 +2173,12 @@ class File_X509
|
|||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
return
|
||||
"-----BEGIN PUBLIC KEY-----\r\n" .
|
||||
"-----BEGIN RSA PUBLIC KEY-----\r\n" .
|
||||
// subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
|
||||
// in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
|
||||
// uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
|
||||
chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
|
||||
'-----END PUBLIC KEY-----';
|
||||
'-----END RSA PUBLIC KEY-----';
|
||||
default:
|
||||
return $key;
|
||||
}
|
||||
|
@ -2502,7 +2509,8 @@ class File_X509
|
|||
$asn1->loadFilters($filters);
|
||||
$result = '';
|
||||
foreach ($dn['rdnSequence'] as $rdn) {
|
||||
foreach ($rdn as &$attr) {
|
||||
foreach ($rdn as $i=>$attr) {
|
||||
$attr = &$rdn[$i];
|
||||
if (is_array($attr['value'])) {
|
||||
foreach ($attr['value'] as $type => $v) {
|
||||
$type = array_search($type, $asn1->ANYmap, true);
|
||||
|
@ -2531,7 +2539,7 @@ class File_X509
|
|||
return strtolower(bin2hex(pack('N', $hash)));
|
||||
}
|
||||
|
||||
// Defaut is to return a string.
|
||||
// Default is to return a string.
|
||||
$start = true;
|
||||
$output = '';
|
||||
$asn1 = new File_ASN1();
|
||||
|
@ -2760,6 +2768,19 @@ class File_X509
|
|||
$this->privateKey = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set challenge
|
||||
*
|
||||
* Used for SPKAC CSR's
|
||||
*
|
||||
* @param String $challenge
|
||||
* @access public
|
||||
*/
|
||||
function setChallenge($challenge)
|
||||
{
|
||||
$this->challenge = $challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public key
|
||||
*
|
||||
|
@ -2953,7 +2974,8 @@ class File_X509
|
|||
|
||||
$asn1 = new File_ASN1();
|
||||
|
||||
$temp = preg_replace('#(?:^[^=]+=)|[\r\n\\\]#', '', $spkac);
|
||||
// OpenSSL produces SPKAC's that are preceeded by the string SPKAC=
|
||||
$temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac);
|
||||
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
|
||||
if ($temp != false) {
|
||||
$spkac = $temp;
|
||||
|
@ -3005,6 +3027,49 @@ class File_X509
|
|||
return $spkac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a SPKAC CSR request
|
||||
*
|
||||
* @param Array $csr
|
||||
* @param Integer $format optional
|
||||
* @access public
|
||||
* @return String
|
||||
*/
|
||||
function saveSPKAC($spkac, $format = FILE_X509_FORMAT_PEM)
|
||||
{
|
||||
if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
|
||||
switch (true) {
|
||||
case !$algorithm:
|
||||
case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']);
|
||||
break;
|
||||
default:
|
||||
switch ($algorithm) {
|
||||
case 'rsaEncryption':
|
||||
$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']
|
||||
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
|
||||
}
|
||||
}
|
||||
|
||||
$asn1 = new File_ASN1();
|
||||
|
||||
$asn1->loadOIDs($this->oids);
|
||||
$spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge);
|
||||
|
||||
switch ($format) {
|
||||
case FILE_X509_FORMAT_DER:
|
||||
return $spkac;
|
||||
// case FILE_X509_FORMAT_PEM:
|
||||
default:
|
||||
// OpenSSL's implementation of SPKAC requires the SPKAC be preceeded by SPKAC= and since there are pretty much
|
||||
// no other SPKAC decoders phpseclib will use that same format
|
||||
return 'SPKAC=' . base64_encode($spkac);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Certificate Revocation List
|
||||
*
|
||||
|
@ -3117,6 +3182,28 @@ class File_X509
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build a time field according to RFC 3280 section
|
||||
* - 4.1.2.5 Validity
|
||||
* - 5.1.2.4 This Update
|
||||
* - 5.1.2.5 Next Update
|
||||
* - 5.1.2.6 Revoked Certificates
|
||||
* by choosing utcTime iff year of date given is before 2050 and generalTime else.
|
||||
*
|
||||
* @param String $date in format date('D, d M Y H:i:s O')
|
||||
* @access private
|
||||
* @return Array
|
||||
*/
|
||||
function _timeField($date)
|
||||
{
|
||||
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
|
||||
if ($year < 2050) {
|
||||
return array('utcTime' => $date);
|
||||
} else {
|
||||
return array('generalTime' => $date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign an X.509 certificate
|
||||
*
|
||||
|
@ -3149,12 +3236,10 @@ class File_X509
|
|||
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
||||
|
||||
if (!empty($this->startDate)) {
|
||||
$this->currentCert['tbsCertificate']['validity']['notBefore']['generalTime'] = $this->startDate;
|
||||
unset($this->currentCert['tbsCertificate']['validity']['notBefore']['utcTime']);
|
||||
$this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate);
|
||||
}
|
||||
if (!empty($this->endDate)) {
|
||||
$this->currentCert['tbsCertificate']['validity']['notAfter']['generalTime'] = $this->endDate;
|
||||
unset($this->currentCert['tbsCertificate']['validity']['notAfter']['utcTime']);
|
||||
$this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate);
|
||||
}
|
||||
if (!empty($this->serialNumber)) {
|
||||
$this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
|
||||
|
@ -3176,8 +3261,8 @@ class File_X509
|
|||
return false;
|
||||
}
|
||||
|
||||
$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'));
|
||||
$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'));
|
||||
$serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger();
|
||||
|
||||
$this->currentCert = array(
|
||||
|
@ -3188,8 +3273,8 @@ class File_X509
|
|||
'signature' => array('algorithm' => $signatureAlgorithm),
|
||||
'issuer' => false, // this is going to be overwritten later
|
||||
'validity' => array(
|
||||
'notBefore' => array('generalTime' => $startDate), // $this->setStartDate()
|
||||
'notAfter' => array('generalTime' => $endDate) // $this->setEndDate()
|
||||
'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
|
||||
'notAfter' => $this->_timeField($endDate) // $this->setEndDate()
|
||||
),
|
||||
'subject' => $subject->dn,
|
||||
'subjectPublicKeyInfo' => $subjectPublicKey
|
||||
|
@ -3349,6 +3434,71 @@ class File_X509
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a SPKAC
|
||||
*
|
||||
* @access public
|
||||
* @return Mixed
|
||||
*/
|
||||
function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption')
|
||||
{
|
||||
if (!is_object($this->privateKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$origPublicKey = $this->publicKey;
|
||||
$class = get_class($this->privateKey);
|
||||
$this->publicKey = new $class();
|
||||
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
||||
$this->publicKey->setPublicKey();
|
||||
$publicKey = $this->_formatSubjectPublicKey();
|
||||
if (!$publicKey) {
|
||||
return false;
|
||||
}
|
||||
$this->publicKey = $origPublicKey;
|
||||
|
||||
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
||||
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
|
||||
|
||||
// re-signing a SPKAC seems silly but since everything else supports re-signing why not?
|
||||
if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
|
||||
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
||||
$this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
|
||||
if (!empty($this->challenge)) {
|
||||
// the bitwise AND ensures that the output is a valid IA5String
|
||||
$this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge));
|
||||
}
|
||||
} else {
|
||||
$this->currentCert = array(
|
||||
'publicKeyAndChallenge' =>
|
||||
array(
|
||||
'spki' => $publicKey,
|
||||
// quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
|
||||
// "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
|
||||
// both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
|
||||
// we could alternatively do this instead if we ignored the specs:
|
||||
// crypt_random_string(8) & str_repeat("\x7F", 8)
|
||||
'challenge' => !empty($this->challenge) ? $this->challenge : ''
|
||||
),
|
||||
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
||||
'signature' => false // this is going to be overwritten later
|
||||
);
|
||||
}
|
||||
|
||||
// resync $this->signatureSubject
|
||||
// save $publicKeyAndChallenge in case there are any File_ASN1_Element objects in it
|
||||
$publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
|
||||
$this->loadSPKAC($this->saveSPKAC($this->currentCert));
|
||||
|
||||
$result = $this->_sign($this->privateKey, $signatureAlgorithm);
|
||||
$result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
|
||||
|
||||
$this->currentCert = $currentCert;
|
||||
$this->signatureSubject = $signatureSubject;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a CRL
|
||||
*
|
||||
|
@ -3368,7 +3518,7 @@ class File_X509
|
|||
|
||||
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
||||
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O');
|
||||
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
|
||||
|
||||
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
|
||||
$this->currentCert = $crl->currentCert;
|
||||
|
@ -3381,7 +3531,7 @@ class File_X509
|
|||
'version' => 'v2',
|
||||
'signature' => array('algorithm' => $signatureAlgorithm),
|
||||
'issuer' => false, // this is going to be overwritten later
|
||||
'thisUpdate' => array('generalTime' => $thisUpdate) // $this->setStartDate()
|
||||
'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
|
||||
),
|
||||
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
||||
'signature' => false // this is going to be overwritten later
|
||||
|
@ -3390,10 +3540,10 @@ class File_X509
|
|||
|
||||
$tbsCertList = &$this->currentCert['tbsCertList'];
|
||||
$tbsCertList['issuer'] = $issuer->dn;
|
||||
$tbsCertList['thisUpdate'] = array('generalTime' => $thisUpdate);
|
||||
$tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate);
|
||||
|
||||
if (!empty($this->endDate)) {
|
||||
$tbsCertList['nextUpdate'] = array('generalTime' => $this->endDate); // $this->setEndDate()
|
||||
$tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
|
||||
} else {
|
||||
unset($tbsCertList['nextUpdate']);
|
||||
}
|
||||
|
@ -3516,7 +3666,7 @@ class File_X509
|
|||
*/
|
||||
function setStartDate($date)
|
||||
{
|
||||
$this->startDate = @date('D, d M y H:i:s O', @strtotime($date));
|
||||
$this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3540,7 +3690,7 @@ class File_X509
|
|||
$temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
|
||||
$this->endDate = new File_ASN1_Element($temp);
|
||||
} else {
|
||||
$this->endDate = @date('D, d M y H:i:s O', @strtotime($date));
|
||||
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4085,7 +4235,7 @@ class File_X509
|
|||
}
|
||||
return false;
|
||||
default: // Should be a key object (i.e.: Crypt_RSA).
|
||||
$key = $key->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW);
|
||||
$key = $key->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4126,7 +4276,7 @@ class File_X509
|
|||
//return new File_ASN1_Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
|
||||
return array(
|
||||
'algorithm' => array('algorithm' => 'rsaEncryption'),
|
||||
'subjectPublicKey' => $this->publicKey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW)
|
||||
'subjectPublicKey' => $this->publicKey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_PKCS1)
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
|
@ -4214,7 +4364,7 @@ class File_X509
|
|||
|
||||
$i = count($rclist);
|
||||
$rclist[] = array('userCertificate' => $serial,
|
||||
'revocationDate' => array('generalTime' => @date('D, d M y H:i:s O')));
|
||||
'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
|
||||
return $i;
|
||||
}
|
||||
|
||||
|
@ -4234,7 +4384,7 @@ class File_X509
|
|||
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
|
||||
|
||||
if (!empty($date)) {
|
||||
$rclist[$i]['revocationDate'] = array('generalTime' => $date);
|
||||
$rclist[$i]['revocationDate'] = $this->_timeField($date);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
* which only supports integers. Although this fact will slow this library down, the fact that such a high
|
||||
* base is being used should more than compensate.
|
||||
*
|
||||
* When PHP version 6 is officially released, we'll be able to use 64-bit integers. This should, once again,
|
||||
* allow bitwise operators, and will increase the maximum possible base to 2**31 (or 2**62 for addition /
|
||||
* subtraction).
|
||||
*
|
||||
* Numbers are stored in {@link http://en.wikipedia.org/wiki/Endianness little endian} format. ie.
|
||||
* (new Math_BigInteger(pow(2, 26)))->value = array(0, 1)
|
||||
*
|
||||
|
@ -35,7 +31,7 @@
|
|||
* Here's an example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger(2);
|
||||
* $b = new Math_BigInteger(3);
|
||||
|
@ -67,7 +63,7 @@
|
|||
* @category Math
|
||||
* @package Math_BigInteger
|
||||
* @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
|
||||
* @link http://pear.php.net/package/Math_BigInteger
|
||||
*/
|
||||
|
@ -175,7 +171,6 @@ define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25);
|
|||
*
|
||||
* @package Math_BigInteger
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 1.0.0RC4
|
||||
* @access public
|
||||
*/
|
||||
class Math_BigInteger
|
||||
|
@ -242,13 +237,13 @@ class Math_BigInteger
|
|||
*
|
||||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* <?php
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16
|
||||
*
|
||||
* echo $a->toString(); // outputs 50
|
||||
* ?>
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param optional $x base-10 number or base-$base number if $base set.
|
||||
|
@ -274,7 +269,7 @@ class Math_BigInteger
|
|||
if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
|
||||
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
|
||||
ob_start();
|
||||
phpinfo();
|
||||
@phpinfo();
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
|
@ -283,7 +278,14 @@ class Math_BigInteger
|
|||
$versions = array();
|
||||
if (!empty($matches[1])) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,9 +336,12 @@ class Math_BigInteger
|
|||
|
||||
switch ( MATH_BIGINTEGER_MODE ) {
|
||||
case MATH_BIGINTEGER_MODE_GMP:
|
||||
if (is_resource($x) && get_resource_type($x) == 'GMP integer') {
|
||||
$this->value = $x;
|
||||
return;
|
||||
switch (true) {
|
||||
case is_resource($x) && get_resource_type($x) == 'GMP integer':
|
||||
// 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);
|
||||
break;
|
||||
|
@ -511,7 +516,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('65');
|
||||
*
|
||||
|
@ -608,7 +613,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('65');
|
||||
*
|
||||
|
@ -635,7 +640,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('65');
|
||||
*
|
||||
|
@ -673,7 +678,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('50');
|
||||
*
|
||||
|
@ -826,7 +831,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('10');
|
||||
* $b = new Math_BigInteger('20');
|
||||
|
@ -917,7 +922,7 @@ class Math_BigInteger
|
|||
$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;
|
||||
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
|
||||
|
@ -925,7 +930,7 @@ class Math_BigInteger
|
|||
$carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
|
||||
$sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
|
||||
|
||||
$temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
|
||||
$temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
|
||||
|
||||
$value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
|
||||
$value[$j] = $temp;
|
||||
|
@ -957,7 +962,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('10');
|
||||
* $b = new Math_BigInteger('20');
|
||||
|
@ -1061,7 +1066,7 @@ class Math_BigInteger
|
|||
$carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
|
||||
$sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
|
||||
|
||||
$temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
|
||||
$temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31);
|
||||
|
||||
$x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
|
||||
$x_value[$j] = $temp;
|
||||
|
@ -1093,7 +1098,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('10');
|
||||
* $b = new Math_BigInteger('20');
|
||||
|
@ -1209,7 +1214,7 @@ class Math_BigInteger
|
|||
|
||||
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
|
||||
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1227,7 @@ class Math_BigInteger
|
|||
|
||||
for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
|
||||
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
|
@ -1310,13 +1315,13 @@ class Math_BigInteger
|
|||
$i2 = $i << 1;
|
||||
|
||||
$temp = $square_value[$i2] + $value[$i] * $value[$i];
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
|
||||
// note how we start from $i+1 instead of 0 as we do in multiplication.
|
||||
for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
|
||||
$temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
|
@ -1377,7 +1382,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('10');
|
||||
* $b = new Math_BigInteger('20');
|
||||
|
@ -1514,9 +1519,8 @@ class Math_BigInteger
|
|||
if ($x_window[0] == $y_window[0]) {
|
||||
$quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT;
|
||||
} else {
|
||||
$quotient_value[$q_index] = (int) (
|
||||
($x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1])
|
||||
/
|
||||
$quotient_value[$q_index] = $this->_safe_divide(
|
||||
$x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1],
|
||||
$y_window[0]
|
||||
);
|
||||
}
|
||||
|
@ -1584,7 +1588,7 @@ class Math_BigInteger
|
|||
|
||||
for ($i = count($dividend) - 1; $i >= 0; --$i) {
|
||||
$temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i];
|
||||
$result[$i] = (int) ($temp / $divisor);
|
||||
$result[$i] = $this->_safe_divide($temp, $divisor);
|
||||
$carry = (int) ($temp - $divisor * $result[$i]);
|
||||
}
|
||||
|
||||
|
@ -1597,7 +1601,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger('10');
|
||||
* $b = new Math_BigInteger('20');
|
||||
|
@ -1722,6 +1726,11 @@ class Math_BigInteger
|
|||
|
||||
return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT));
|
||||
|
||||
// the following code, although not callable, can be run independently of the above code
|
||||
// although the above code performed better in my benchmarks the following could might
|
||||
// perform better under different circumstances. in lieu of deleting it it's just been
|
||||
// made uncallable
|
||||
|
||||
// is the modulo odd?
|
||||
if ( $n->value[0] & 1 ) {
|
||||
return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY));
|
||||
|
@ -2135,7 +2144,7 @@ class Math_BigInteger
|
|||
|
||||
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[] = 1;
|
||||
$corrector_value[count($corrector_value)] = 1;
|
||||
$result = $this->_add($result, false, $corrector_value, false);
|
||||
$result = $result[MATH_BIGINTEGER_VALUE];
|
||||
}
|
||||
|
@ -2196,7 +2205,7 @@ class Math_BigInteger
|
|||
|
||||
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
|
||||
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
|
@ -2212,7 +2221,7 @@ class Math_BigInteger
|
|||
|
||||
for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
|
||||
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
|
||||
}
|
||||
|
||||
|
@ -2261,7 +2270,7 @@ class Math_BigInteger
|
|||
|
||||
for ($i = 0; $i < $k; ++$i) {
|
||||
$temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
|
||||
$temp = $this->_regularMultiply(array($temp), $n);
|
||||
$temp = array_merge($this->_array_repeat(0, $i), $temp);
|
||||
$result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
|
||||
|
@ -2295,6 +2304,11 @@ class Math_BigInteger
|
|||
$temp = $this->_multiply($x, false, $y, false);
|
||||
return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m);
|
||||
|
||||
// the following code, although not callable, can be run independently of the above code
|
||||
// although the above code performed better in my benchmarks the following could might
|
||||
// perform better under different circumstances. in lieu of deleting it it's just been
|
||||
// made uncallable
|
||||
|
||||
static $cache = array(
|
||||
MATH_BIGINTEGER_VARIABLE => array(),
|
||||
MATH_BIGINTEGER_DATA => array()
|
||||
|
@ -2313,9 +2327,9 @@ class Math_BigInteger
|
|||
$a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
$temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
|
||||
$temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
|
||||
$temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
|
||||
$temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31));
|
||||
$temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
|
||||
$a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
|
||||
$a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
|
||||
|
@ -2392,7 +2406,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger(30);
|
||||
* $b = new Math_BigInteger(17);
|
||||
|
@ -2460,7 +2474,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger(693);
|
||||
* $b = new Math_BigInteger(609);
|
||||
|
@ -2595,7 +2609,7 @@ class Math_BigInteger
|
|||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Math/BigInteger.php');
|
||||
* include 'Math/BigInteger.php';
|
||||
*
|
||||
* $a = new Math_BigInteger(693);
|
||||
* $b = new Math_BigInteger(609);
|
||||
|
@ -2900,7 +2914,7 @@ class Math_BigInteger
|
|||
$leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
|
||||
$this->_base256_lshift($leading_ones, $current_bits);
|
||||
|
||||
$temp = str_pad($temp, ceil($this->bits / 8), chr(0), STR_PAD_LEFT);
|
||||
$temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
|
||||
|
||||
return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256));
|
||||
}
|
||||
|
@ -3062,8 +3076,7 @@ class Math_BigInteger
|
|||
*/
|
||||
function _random_number_helper($size)
|
||||
{
|
||||
$crypt_random = function_exists('crypt_random_string') || (!class_exists('Crypt_Random') && function_exists('crypt_random_string'));
|
||||
if ($crypt_random) {
|
||||
if (function_exists('crypt_random_string')) {
|
||||
$random = crypt_random_string($size);
|
||||
} else {
|
||||
$random = '';
|
||||
|
@ -3085,19 +3098,31 @@ class Math_BigInteger
|
|||
/**
|
||||
* Generate a random number
|
||||
*
|
||||
* @param optional Integer $min
|
||||
* @param optional Integer $max
|
||||
* Returns a random number between $min and $max where $min and $max
|
||||
* can be defined using one of the two methods:
|
||||
*
|
||||
* $min->random($max)
|
||||
* $max->random($min)
|
||||
*
|
||||
* @param Math_BigInteger $arg1
|
||||
* @param optional Math_BigInteger $arg2
|
||||
* @return Math_BigInteger
|
||||
* @access public
|
||||
* @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a Math_BigInteger object.
|
||||
* That method is still supported for BC purposes.
|
||||
*/
|
||||
function random($min = false, $max = false)
|
||||
function random($arg1, $arg2 = false)
|
||||
{
|
||||
if ($min === false) {
|
||||
$min = new Math_BigInteger(0);
|
||||
if ($arg1 === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($max === false) {
|
||||
$max = new Math_BigInteger(0x7FFFFFFF);
|
||||
if ($arg2 === false) {
|
||||
$max = $arg1;
|
||||
$min = $this;
|
||||
} else {
|
||||
$min = $arg1;
|
||||
$max = $arg2;
|
||||
}
|
||||
|
||||
$compare = $max->compare($min);
|
||||
|
@ -3160,21 +3185,25 @@ class Math_BigInteger
|
|||
* If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed,
|
||||
* give up and return false.
|
||||
*
|
||||
* @param optional Integer $min
|
||||
* @param optional Integer $max
|
||||
* @param Math_BigInteger $arg1
|
||||
* @param optional Math_BigInteger $arg2
|
||||
* @param optional Integer $timeout
|
||||
* @return Math_BigInteger
|
||||
* @return Mixed
|
||||
* @access public
|
||||
* @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}.
|
||||
*/
|
||||
function randomPrime($min = false, $max = false, $timeout = false)
|
||||
function randomPrime($arg1, $arg2 = false, $timeout = false)
|
||||
{
|
||||
if ($min === false) {
|
||||
$min = new Math_BigInteger(0);
|
||||
if ($arg1 === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($max === false) {
|
||||
$max = new Math_BigInteger(0x7FFFFFFF);
|
||||
if ($arg2 === false) {
|
||||
$max = $arg1;
|
||||
$min = $this;
|
||||
} else {
|
||||
$min = $arg1;
|
||||
$max = $arg2;
|
||||
}
|
||||
|
||||
$compare = $max->compare($min);
|
||||
|
@ -3283,10 +3312,10 @@ class Math_BigInteger
|
|||
* Checks a numer to see if it's prime
|
||||
*
|
||||
* Assuming the $t parameter is not set, this function has an error rate of 2**-80. The main motivation for the
|
||||
* $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed accross multiple pageloads
|
||||
* $t parameter is distributability. Math_BigInteger::randomPrime() can be distributed across multiple pageloads
|
||||
* on a website instead of just one.
|
||||
*
|
||||
* @param optional Integer $t
|
||||
* @param optional Math_BigInteger $t
|
||||
* @return Boolean
|
||||
* @access public
|
||||
* @internal Uses the
|
||||
|
@ -3455,12 +3484,12 @@ class Math_BigInteger
|
|||
|
||||
for ($i = 0; $i < count($this->value); ++$i) {
|
||||
$temp = $this->value[$i] * $shift + $carry;
|
||||
$carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
|
||||
$carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31);
|
||||
$this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
|
||||
}
|
||||
|
||||
if ( $carry ) {
|
||||
$this->value[] = $carry;
|
||||
$this->value[count($this->value)] = $carry;
|
||||
}
|
||||
|
||||
while ($num_digits--) {
|
||||
|
@ -3703,4 +3732,27 @@ class Math_BigInteger
|
|||
$temp = ltrim(pack('N', $length), chr(0));
|
||||
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Single digit division
|
||||
*
|
||||
* Even if int64 is being used the division operator will return a float64 value
|
||||
* if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
|
||||
* have the precision of int64 this is a problem so, when int64 is being used,
|
||||
* we'll guarantee that the dividend is divisible by first subtracting the remainder.
|
||||
*
|
||||
* @access private
|
||||
* @param Integer $x
|
||||
* @param Integer $y
|
||||
* @return Integer
|
||||
*/
|
||||
function _safe_divide($x, $y)
|
||||
{
|
||||
if (MATH_BIGINTEGER_BASE === 26) {
|
||||
return (int) ($x / $y);
|
||||
}
|
||||
|
||||
// MATH_BIGINTEGER_BASE === 31
|
||||
return ($x - ($x % $y)) / $y;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Net/SCP.php');
|
||||
* include('Net/SSH2.php');
|
||||
* include 'Net/SCP.php';
|
||||
* include 'Net/SSH2.php';
|
||||
*
|
||||
* $ssh = new Net_SSH2('www.domain.tld');
|
||||
* if (!$ssh->login('username', 'password')) {
|
||||
|
@ -44,7 +44,7 @@
|
|||
* @category Net
|
||||
* @package Net_SCP
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -83,7 +83,6 @@ define('NET_SCP_SSH2', 2);
|
|||
*
|
||||
* @package Net_SCP
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Net_SCP
|
||||
|
@ -130,7 +129,7 @@ class Net_SCP
|
|||
}
|
||||
|
||||
switch (strtolower(get_class($ssh))) {
|
||||
case'net_ssh2':
|
||||
case 'net_ssh2':
|
||||
$this->mode = NET_SCP_SSH2;
|
||||
break;
|
||||
case 'net_ssh1':
|
||||
|
@ -171,7 +170,7 @@ class Net_SCP
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -196,7 +195,6 @@ class Net_SCP
|
|||
|
||||
$fp = @fopen($data, 'rb');
|
||||
if (!$fp) {
|
||||
fclose($fp);
|
||||
return false;
|
||||
}
|
||||
$size = filesize($data);
|
||||
|
@ -216,7 +214,7 @@ class Net_SCP
|
|||
$sent+= strlen($temp);
|
||||
|
||||
if (is_callable($callback)) {
|
||||
$callback($sent);
|
||||
call_user_func($callback, $sent);
|
||||
}
|
||||
}
|
||||
$this->_close();
|
||||
|
@ -246,7 +244,7 @@ class Net_SCP
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,7 +28,7 @@
|
|||
* @category Net
|
||||
* @package Net_SFTP_Stream
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -38,7 +38,6 @@
|
|||
*
|
||||
* @package Net_SFTP_Stream
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.3.2
|
||||
* @access public
|
||||
*/
|
||||
class Net_SFTP_Stream
|
||||
|
@ -49,7 +48,6 @@ class Net_SFTP_Stream
|
|||
* Rather than re-create the connection we re-use instances if possible
|
||||
*
|
||||
* @var Array
|
||||
* @access static
|
||||
*/
|
||||
static $instances;
|
||||
|
||||
|
@ -127,6 +125,22 @@ class Net_SFTP_Stream
|
|||
*/
|
||||
var $notification;
|
||||
|
||||
/**
|
||||
* Registers this class as a URL wrapper.
|
||||
*
|
||||
* @param optional String $protocol The wrapper name to be registered.
|
||||
* @return Boolean True on success, false otherwise.
|
||||
* @access public
|
||||
*/
|
||||
static function register($protocol = 'sftp')
|
||||
{
|
||||
if (in_array($protocol, stream_get_wrappers(), true)) {
|
||||
return false;
|
||||
}
|
||||
$class = function_exists('get_called_class') ? get_called_class() : __CLASS__;
|
||||
return stream_wrapper_register($protocol, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Constructor
|
||||
*
|
||||
|
@ -181,24 +195,24 @@ class Net_SFTP_Stream
|
|||
if (isset($this->context)) {
|
||||
$context = stream_context_get_options($this->context);
|
||||
}
|
||||
if (isset($context['sftp']['session'])) {
|
||||
$sftp = $context['sftp']['session'];
|
||||
if (isset($context[$scheme]['session'])) {
|
||||
$sftp = $context[$scheme]['session'];
|
||||
}
|
||||
if (isset($context['sftp']['sftp'])) {
|
||||
$sftp = $context['sftp']['sftp'];
|
||||
if (isset($context[$scheme]['sftp'])) {
|
||||
$sftp = $context[$scheme]['sftp'];
|
||||
}
|
||||
if (isset($sftp) && is_object($sftp) && get_class($sftp) == 'Net_SFTP') {
|
||||
$this->sftp = $sftp;
|
||||
return $path;
|
||||
}
|
||||
if (isset($context['sftp']['username'])) {
|
||||
$user = $context['sftp']['username'];
|
||||
if (isset($context[$scheme]['username'])) {
|
||||
$user = $context[$scheme]['username'];
|
||||
}
|
||||
if (isset($context['sftp']['password'])) {
|
||||
$pass = $context['sftp']['password'];
|
||||
if (isset($context[$scheme]['password'])) {
|
||||
$pass = $context[$scheme]['password'];
|
||||
}
|
||||
if (isset($context['sftp']['privkey']) && is_object($context['sftp']['privkey']) && get_Class($context['sftp']['privkey']) == 'Crypt_RSA') {
|
||||
$pass = $context['sftp']['privkey'];
|
||||
if (isset($context[$scheme]['privkey']) && is_object($context[$scheme]['privkey']) && get_Class($context[$scheme]['privkey']) == 'Crypt_RSA') {
|
||||
$pass = $context[$scheme]['privkey'];
|
||||
}
|
||||
|
||||
if (!isset($user) || !isset($pass)) {
|
||||
|
@ -210,6 +224,7 @@ class Net_SFTP_Stream
|
|||
$this->sftp = self::$instances[$host][$port][$user][(string) $pass];
|
||||
} else {
|
||||
$this->sftp = new Net_SFTP($host, $port);
|
||||
$this->sftp->disableStatCache();
|
||||
if (isset($this->notification) && is_callable($this->notification)) {
|
||||
/* if !is_callable($this->notification) we could do this:
|
||||
|
||||
|
@ -517,7 +532,20 @@ class Net_SFTP_Stream
|
|||
* Open directory handle
|
||||
*
|
||||
* The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
|
||||
* removed in 5.4 I'm just going to ignore it
|
||||
* removed in 5.4 I'm just going to ignore it.
|
||||
*
|
||||
* Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
|
||||
* sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
|
||||
* the SFTP specs:
|
||||
*
|
||||
* The SSH_FXP_NAME response has the following format:
|
||||
*
|
||||
* uint32 id
|
||||
* uint32 count
|
||||
* repeats count times:
|
||||
* string filename
|
||||
* string longname
|
||||
* ATTRS attrs
|
||||
*
|
||||
* @param String $path
|
||||
* @param Integer $options
|
||||
|
@ -770,6 +798,4 @@ class Net_SFTP_Stream
|
|||
}
|
||||
}
|
||||
|
||||
if (function_exists('stream_wrapper_register')) {
|
||||
stream_wrapper_register('sftp', 'Net_SFTP_Stream');
|
||||
}
|
||||
Net_SFTP_Stream::register();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Net/SSH1.php');
|
||||
* include 'Net/SSH1.php';
|
||||
*
|
||||
* $ssh = new Net_SSH1('www.domain.tld');
|
||||
* if (!$ssh->login('username', 'password')) {
|
||||
|
@ -22,7 +22,7 @@
|
|||
* Here's another short example:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Net/SSH1.php');
|
||||
* include 'Net/SSH1.php';
|
||||
*
|
||||
* $ssh = new Net_SSH1('www.domain.tld');
|
||||
* if (!$ssh->login('username', 'password')) {
|
||||
|
@ -59,7 +59,7 @@
|
|||
* @category Net
|
||||
* @package Net_SSH1
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -182,8 +182,9 @@ define('NET_SSH1_RESPONSE_DATA', 2);
|
|||
* @access private
|
||||
*/
|
||||
define('NET_SSH1_MASK_CONSTRUCTOR', 0x00000001);
|
||||
define('NET_SSH1_MASK_LOGIN', 0x00000002);
|
||||
define('NET_SSH1_MASK_SHELL', 0x00000004);
|
||||
define('NET_SSH1_MASK_CONNECTED', 0x00000002);
|
||||
define('NET_SSH1_MASK_LOGIN', 0x00000004);
|
||||
define('NET_SSH1_MASK_SHELL', 0x00000008);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
|
@ -227,7 +228,6 @@ define('NET_SSH1_READ_REGEX', 2);
|
|||
*
|
||||
* @package Net_SSH1
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Net_SSH1
|
||||
|
@ -458,6 +458,51 @@ class Net_SSH1
|
|||
*/
|
||||
var $log_short_width = 16;
|
||||
|
||||
/**
|
||||
* Hostname
|
||||
*
|
||||
* @see Net_SSH1::Net_SSH1()
|
||||
* @see Net_SSH1::_connect()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $host;
|
||||
|
||||
/**
|
||||
* Port Number
|
||||
*
|
||||
* @see Net_SSH1::Net_SSH1()
|
||||
* @see Net_SSH1::_connect()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $port;
|
||||
|
||||
/**
|
||||
* Timeout for initial connection
|
||||
*
|
||||
* Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like
|
||||
* exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor,
|
||||
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
|
||||
* 10 seconds. It is used by fsockopen() in that function.
|
||||
*
|
||||
* @see Net_SSH1::Net_SSH1()
|
||||
* @see Net_SSH1::_connect()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $connectionTimeout;
|
||||
|
||||
/**
|
||||
* Default cipher
|
||||
*
|
||||
* @see Net_SSH1::Net_SSH1()
|
||||
* @see Net_SSH1::_connect()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $cipher;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
|
@ -506,10 +551,24 @@ class Net_SSH1
|
|||
|
||||
$this->_define_array($this->protocol_flags);
|
||||
|
||||
$this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->connectionTimeout = $timeout;
|
||||
$this->cipher = $cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to an SSHv1 server
|
||||
*
|
||||
* @return Boolean
|
||||
* @access private
|
||||
*/
|
||||
function _connect()
|
||||
{
|
||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
|
||||
if (!$this->fsock) {
|
||||
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
return;
|
||||
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->server_identification = $init_line = fgets($this->fsock, 255);
|
||||
|
@ -521,11 +580,11 @@ class Net_SSH1
|
|||
|
||||
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
|
||||
user_error('Can only connect to SSH servers');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if ($parts[1][0] != 1) {
|
||||
user_error("Cannot connect to SSH $parts[1] servers");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
fputs($this->fsock, $this->identifier."\r\n");
|
||||
|
@ -533,7 +592,7 @@ class Net_SSH1
|
|||
$response = $this->_get_binary_packet();
|
||||
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
|
||||
user_error('Expected SSH_SMSG_PUBLIC_KEY');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
|
||||
|
@ -613,12 +672,12 @@ class Net_SSH1
|
|||
);
|
||||
}
|
||||
|
||||
$cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
|
||||
$cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : NET_SSH1_CIPHER_3DES;
|
||||
$data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_SESSION_KEY');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($cipher) {
|
||||
|
@ -645,7 +704,7 @@ class Net_SSH1
|
|||
break;
|
||||
//case NET_SSH1_CIPHER_RC4:
|
||||
// if (!class_exists('Crypt_RC4')) {
|
||||
// include_once('Crypt/RC4.php');
|
||||
// include_once 'Crypt/RC4.php';
|
||||
// }
|
||||
// $this->crypto = new Crypt_RC4();
|
||||
// $this->crypto->enableContinuousBuffer();
|
||||
|
@ -657,10 +716,12 @@ class Net_SSH1
|
|||
|
||||
if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
|
||||
$this->bitmap = NET_SSH1_MASK_CONNECTED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -674,6 +735,13 @@ class Net_SSH1
|
|||
function login($username, $password = '')
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH1_MASK_CONSTRUCTOR)) {
|
||||
$this->bitmap |= NET_SSH1_MASK_CONSTRUCTOR;
|
||||
if (!$this->_connect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!($this->bitmap & NET_SSH1_MASK_CONNECTED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1060,6 +1128,7 @@ class Net_SSH1
|
|||
|
||||
$padding_length = 8 - ($temp['length'] & 7);
|
||||
$length = $temp['length'] + $padding_length;
|
||||
$raw = '';
|
||||
|
||||
while ($length > 0) {
|
||||
$temp = fread($this->fsock, $length);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Here are some examples of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Net/SSH2.php');
|
||||
* include 'Net/SSH2.php';
|
||||
*
|
||||
* $ssh = new Net_SSH2('www.domain.tld');
|
||||
* if (!$ssh->login('username', 'password')) {
|
||||
|
@ -22,8 +22,8 @@
|
|||
*
|
||||
* <code>
|
||||
* <?php
|
||||
* include('Crypt/RSA.php');
|
||||
* include('Net/SSH2.php');
|
||||
* include 'Crypt/RSA.php';
|
||||
* include 'Net/SSH2.php';
|
||||
*
|
||||
* $key = new Crypt_RSA();
|
||||
* //$key->setPassword('whatever');
|
||||
|
@ -61,7 +61,7 @@
|
|||
* @category Net
|
||||
* @package Net_SSH2
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
@ -73,10 +73,11 @@
|
|||
* @access private
|
||||
*/
|
||||
define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
|
||||
define('NET_SSH2_MASK_LOGIN_REQ', 0x00000002);
|
||||
define('NET_SSH2_MASK_LOGIN', 0x00000004);
|
||||
define('NET_SSH2_MASK_SHELL', 0x00000008);
|
||||
define('NET_SSH2_MASK_WINDOW_ADJUST', 0X00000010);
|
||||
define('NET_SSH2_MASK_CONNECTED', 0x00000002);
|
||||
define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004);
|
||||
define('NET_SSH2_MASK_LOGIN', 0x00000008);
|
||||
define('NET_SSH2_MASK_SHELL', 0x00000010);
|
||||
define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020);
|
||||
/**#@-*/
|
||||
|
||||
/**#@+
|
||||
|
@ -145,7 +146,6 @@ define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024);
|
|||
*
|
||||
* @package Net_SSH2
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access public
|
||||
*/
|
||||
class Net_SSH2
|
||||
|
@ -191,100 +191,100 @@ class Net_SSH2
|
|||
* Server Identifier
|
||||
*
|
||||
* @see Net_SSH2::getServerIdentification()
|
||||
* @var String
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $server_identifier = '';
|
||||
var $server_identifier = false;
|
||||
|
||||
/**
|
||||
* Key Exchange Algorithms
|
||||
*
|
||||
* @see Net_SSH2::getKexAlgorithims()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $kex_algorithms;
|
||||
var $kex_algorithms = false;
|
||||
|
||||
/**
|
||||
* Server Host Key Algorithms
|
||||
*
|
||||
* @see Net_SSH2::getServerHostKeyAlgorithms()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $server_host_key_algorithms;
|
||||
var $server_host_key_algorithms = false;
|
||||
|
||||
/**
|
||||
* Encryption Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getEncryptionAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $encryption_algorithms_client_to_server;
|
||||
var $encryption_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Encryption Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getEncryptionAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $encryption_algorithms_server_to_client;
|
||||
var $encryption_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* MAC Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getMACAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $mac_algorithms_client_to_server;
|
||||
var $mac_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* MAC Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getMACAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $mac_algorithms_server_to_client;
|
||||
var $mac_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Compression Algorithms: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getCompressionAlgorithmsClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $compression_algorithms_client_to_server;
|
||||
var $compression_algorithms_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Compression Algorithms: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getCompressionAlgorithmsServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $compression_algorithms_server_to_client;
|
||||
var $compression_algorithms_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Languages: Server to Client
|
||||
*
|
||||
* @see Net_SSH2::getLanguagesServer2Client()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $languages_server_to_client;
|
||||
var $languages_server_to_client = false;
|
||||
|
||||
/**
|
||||
* Languages: Client to Server
|
||||
*
|
||||
* @see Net_SSH2::getLanguagesClient2Server()
|
||||
* @var Array
|
||||
* @var mixed false or Array
|
||||
* @access private
|
||||
*/
|
||||
var $languages_client_to_server;
|
||||
var $languages_client_to_server = false;
|
||||
|
||||
/**
|
||||
* Block Size for Server to Client Encryption
|
||||
|
@ -670,6 +670,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Time of first network activity
|
||||
*
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $last_packet;
|
||||
|
@ -685,6 +686,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Flag to request a PTY when using exec()
|
||||
*
|
||||
* @var Boolean
|
||||
* @see Net_SSH2::enablePTY()
|
||||
* @access private
|
||||
*/
|
||||
|
@ -693,6 +695,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Flag set while exec() is running when using enablePTY()
|
||||
*
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $in_request_pty_exec = false;
|
||||
|
@ -700,6 +703,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Flag set after startSubsystem() is called
|
||||
*
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $in_subsystem;
|
||||
|
@ -707,6 +711,7 @@ class Net_SSH2
|
|||
/**
|
||||
* Contents of stdError
|
||||
*
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $stdErrorLog;
|
||||
|
@ -715,6 +720,7 @@ class Net_SSH2
|
|||
* The Last Interactive Response
|
||||
*
|
||||
* @see Net_SSH2::_keyboard_interactive_process()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $last_interactive_response = '';
|
||||
|
@ -723,6 +729,7 @@ class Net_SSH2
|
|||
* Keyboard Interactive Request / Responses
|
||||
*
|
||||
* @see Net_SSH2::_keyboard_interactive_process()
|
||||
* @var Array
|
||||
* @access private
|
||||
*/
|
||||
var $keyboard_requests_responses = array();
|
||||
|
@ -735,6 +742,7 @@ class Net_SSH2
|
|||
*
|
||||
* @see Net_SSH2::_filter()
|
||||
* @see Net_SSH2::getBannerMessage()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $banner_message = '';
|
||||
|
@ -742,7 +750,8 @@ class Net_SSH2
|
|||
/**
|
||||
* Did read() timeout or return normally?
|
||||
*
|
||||
* @see Net_SSH2::isTimeout
|
||||
* @see Net_SSH2::isTimeout()
|
||||
* @var Boolean
|
||||
* @access private
|
||||
*/
|
||||
var $is_timeout = false;
|
||||
|
@ -750,7 +759,8 @@ class Net_SSH2
|
|||
/**
|
||||
* Log Boundary
|
||||
*
|
||||
* @see Net_SSH2::_format_log
|
||||
* @see Net_SSH2::_format_log()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $log_boundary = ':';
|
||||
|
@ -758,7 +768,8 @@ class Net_SSH2
|
|||
/**
|
||||
* Log Long Width
|
||||
*
|
||||
* @see Net_SSH2::_format_log
|
||||
* @see Net_SSH2::_format_log()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $log_long_width = 65;
|
||||
|
@ -766,19 +777,76 @@ class Net_SSH2
|
|||
/**
|
||||
* Log Short Width
|
||||
*
|
||||
* @see Net_SSH2::_format_log
|
||||
* @see Net_SSH2::_format_log()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $log_short_width = 16;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
* Hostname
|
||||
*
|
||||
* Connects to an SSHv2 server
|
||||
* @see Net_SSH2::Net_SSH2()
|
||||
* @see Net_SSH2::_connect()
|
||||
* @var String
|
||||
* @access private
|
||||
*/
|
||||
var $host;
|
||||
|
||||
/**
|
||||
* Port Number
|
||||
*
|
||||
* @see Net_SSH2::Net_SSH2()
|
||||
* @see Net_SSH2::_connect()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $port;
|
||||
|
||||
/**
|
||||
* Timeout for initial connection
|
||||
*
|
||||
* Set by the constructor call. Calling setTimeout() is optional. If it's not called functions like
|
||||
* exec() won't timeout unless some PHP setting forces it too. The timeout specified in the constructor,
|
||||
* however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be
|
||||
* 10 seconds. It is used by fsockopen() and the initial stream_select in that function.
|
||||
*
|
||||
* @see Net_SSH2::Net_SSH2()
|
||||
* @see Net_SSH2::_connect()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $connectionTimeout;
|
||||
|
||||
/**
|
||||
* Number of columns for terminal window size
|
||||
*
|
||||
* @see Net_SSH2::getWindowColumns()
|
||||
* @see Net_SSH2::setWindowColumns()
|
||||
* @see Net_SSH2::setWindowSize()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $windowColumns = 80;
|
||||
|
||||
/**
|
||||
* Number of columns for terminal window size
|
||||
*
|
||||
* @see Net_SSH2::getWindowRows()
|
||||
* @see Net_SSH2::setWindowRows()
|
||||
* @see Net_SSH2::setWindowSize()
|
||||
* @var Integer
|
||||
* @access private
|
||||
*/
|
||||
var $windowRows = 24;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param String $host
|
||||
* @param optional Integer $port
|
||||
* @param optional Integer $timeout
|
||||
* @see Net_SSH2::login()
|
||||
* @return Net_SSH2
|
||||
* @access public
|
||||
*/
|
||||
|
@ -798,7 +866,6 @@ class Net_SSH2
|
|||
include_once 'Crypt/Hash.php';
|
||||
}
|
||||
|
||||
$this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
|
||||
$this->message_numbers = array(
|
||||
1 => 'NET_SSH2_MSG_DISCONNECT',
|
||||
2 => 'NET_SSH2_MSG_IGNORE',
|
||||
|
@ -869,19 +936,43 @@ class Net_SSH2
|
|||
61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE')
|
||||
);
|
||||
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->connectionTimeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to an SSHv2 server
|
||||
*
|
||||
* @return Boolean
|
||||
* @access private
|
||||
*/
|
||||
function _connect()
|
||||
{
|
||||
if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR;
|
||||
|
||||
$timeout = $this->connectionTimeout;
|
||||
$host = $this->host . ':' . $this->port;
|
||||
|
||||
$this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5
|
||||
|
||||
$start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838
|
||||
$this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
|
||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $timeout);
|
||||
if (!$this->fsock) {
|
||||
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
$elapsed = strtok(microtime(), ' ') + strtok('') - $start;
|
||||
|
||||
$timeout-= $elapsed;
|
||||
|
||||
if ($timeout <= 0) {
|
||||
user_error(rtrim("Cannot connect to $host. Timeout error"));
|
||||
return;
|
||||
user_error("Cannot connect to $host. Timeout error");
|
||||
return false;
|
||||
}
|
||||
|
||||
$read = array($this->fsock);
|
||||
|
@ -893,8 +984,8 @@ class Net_SSH2
|
|||
// on windows this returns a "Warning: Invalid CRT parameters detected" error
|
||||
// the !count() is done as a workaround for <https://bugs.php.net/42682>
|
||||
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
|
||||
user_error(rtrim("Cannot connect to $host. Banner timeout"));
|
||||
return;
|
||||
user_error("Cannot connect to $host. Banner timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* According to the SSH2 specs,
|
||||
|
@ -933,7 +1024,7 @@ class Net_SSH2
|
|||
|
||||
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
|
||||
user_error("Cannot connect to SSH $matches[1] servers");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
fputs($this->fsock, $this->identifier . "\r\n");
|
||||
|
@ -941,19 +1032,21 @@ class Net_SSH2
|
|||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
|
||||
user_error('Expected SSH_MSG_KEXINIT');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->_key_exchange($response)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->bitmap = NET_SSH2_MASK_CONSTRUCTOR;
|
||||
$this->bitmap|= NET_SSH2_MASK_CONNECTED;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1011,7 +1104,7 @@ class Net_SSH2
|
|||
'arcfour256',
|
||||
'arcfour128',
|
||||
|
||||
'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
|
||||
|
||||
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
|
||||
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
|
||||
|
@ -1039,34 +1132,34 @@ class Net_SSH2
|
|||
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
|
||||
|
||||
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
|
||||
'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
if (!$this->_is_includable('Crypt/RC4.php')) {
|
||||
if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('arcfour256', 'arcfour128', 'arcfour')
|
||||
);
|
||||
}
|
||||
if (!$this->_is_includable('Crypt/Rijndael.php')) {
|
||||
if (phpseclib_resolve_include_path('Crypt/Rijndael.php') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc')
|
||||
);
|
||||
}
|
||||
if (!$this->_is_includable('Crypt/Twofish.php')) {
|
||||
if (phpseclib_resolve_include_path('Crypt/Twofish.php') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc')
|
||||
);
|
||||
}
|
||||
if (!$this->_is_includable('Crypt/Blowfish.php')) {
|
||||
if (phpseclib_resolve_include_path('Crypt/Blowfish.php') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('blowfish-ctr', 'blowfish-cbc')
|
||||
);
|
||||
}
|
||||
if (!$this->_is_includable('Crypt/TripleDES.php')) {
|
||||
if (phpseclib_resolve_include_path('Crypt/TripleDES.php') === false) {
|
||||
$encryption_algorithms = array_diff(
|
||||
$encryption_algorithms,
|
||||
array('3des-ctr', '3des-cbc')
|
||||
|
@ -1075,12 +1168,15 @@ class Net_SSH2
|
|||
$encryption_algorithms = array_values($encryption_algorithms);
|
||||
}
|
||||
|
||||
static $mac_algorithms = array(
|
||||
$mac_algorithms = array(
|
||||
// from <http://www.ietf.org/rfc/rfc6668.txt>:
|
||||
'hmac-sha2-256',// RECOMMENDED HMAC-SHA256 (digest length = key length = 32)
|
||||
|
||||
'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
|
||||
'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
|
||||
'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
|
||||
'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
|
||||
'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
//'none' // OPTIONAL no MAC; NOT RECOMMENDED
|
||||
);
|
||||
|
||||
static $compression_algorithms = array(
|
||||
|
@ -1605,6 +1701,10 @@ class Net_SSH2
|
|||
|
||||
$createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
|
||||
switch ($mac_algorithms[$i]) {
|
||||
case 'hmac-sha2-256':
|
||||
$this->hmac_create = new Crypt_Hash('sha256');
|
||||
$createKeyLength = 32;
|
||||
break;
|
||||
case 'hmac-sha1':
|
||||
$this->hmac_create = new Crypt_Hash('sha1');
|
||||
$createKeyLength = 20;
|
||||
|
@ -1631,6 +1731,11 @@ class Net_SSH2
|
|||
$checkKeyLength = 0;
|
||||
$this->hmac_size = 0;
|
||||
switch ($mac_algorithms[$i]) {
|
||||
case 'hmac-sha2-256':
|
||||
$this->hmac_check = new Crypt_Hash('sha256');
|
||||
$checkKeyLength = 32;
|
||||
$this->hmac_size = 32;
|
||||
break;
|
||||
case 'hmac-sha1':
|
||||
$this->hmac_check = new Crypt_Hash('sha1');
|
||||
$checkKeyLength = 20;
|
||||
|
@ -1711,6 +1816,12 @@ class Net_SSH2
|
|||
*/
|
||||
function _login($username)
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
|
||||
if (!$this->_connect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$args = array_slice(func_get_args(), 1);
|
||||
if (empty($args)) {
|
||||
return $this->_login_helper($username);
|
||||
|
@ -1736,7 +1847,7 @@ class Net_SSH2
|
|||
*/
|
||||
function _login_helper($username, $password = null)
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONNECTED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1968,7 +2079,6 @@ class Net_SSH2
|
|||
|
||||
if (!count($responses) && $num_prompts) {
|
||||
$this->last_interactive_response = $orig;
|
||||
$this->bitmap |= NET_SSH_MASK_LOGIN_INTERACTIVE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2151,11 +2261,11 @@ class Net_SSH2
|
|||
/**
|
||||
* Execute Command
|
||||
*
|
||||
* If $block is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
|
||||
* If $callback is set to false then Net_SSH2::_get_channel_packet(NET_SSH2_CHANNEL_EXEC) will need to be called manually.
|
||||
* In all likelihood, this is not a feature you want to be taking advantage of.
|
||||
*
|
||||
* @param String $command
|
||||
* @param optional Boolean $block
|
||||
* @param optional Callback $callback
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
|
@ -2173,7 +2283,7 @@ class Net_SSH2
|
|||
// be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but,
|
||||
// honestly, if you're transfering more than 2GB, you probably shouldn't be using phpseclib, anyway.
|
||||
// see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
|
||||
$this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = 0x7FFFFFFF;
|
||||
$this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size;
|
||||
// 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
|
||||
// uses 0x4000, that's what will be used here, as well.
|
||||
$packet_size = 0x4000;
|
||||
|
@ -2196,7 +2306,7 @@ class Net_SSH2
|
|||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||
$packet = pack('CNNa*CNa*N5a*',
|
||||
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
|
||||
80, 24, 0, 0, strlen($terminal_modes), $terminal_modes);
|
||||
$this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
|
||||
|
||||
if (!$this->_send_binary_packet($packet)) {
|
||||
return false;
|
||||
|
@ -2258,7 +2368,10 @@ class Net_SSH2
|
|||
return false;
|
||||
default:
|
||||
if (is_callable($callback)) {
|
||||
$callback($temp);
|
||||
if (call_user_func($callback, $temp) === true) {
|
||||
$this->_close_channel(NET_SSH2_CHANNEL_EXEC);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$output.= $temp;
|
||||
}
|
||||
|
@ -2280,7 +2393,7 @@ class Net_SSH2
|
|||
return true;
|
||||
}
|
||||
|
||||
$this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = 0x7FFFFFFF;
|
||||
$this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size;
|
||||
$packet_size = 0x4000;
|
||||
|
||||
$packet = pack('CNa*N3',
|
||||
|
@ -2300,7 +2413,7 @@ class Net_SSH2
|
|||
$terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
|
||||
$packet = pack('CNNa*CNa*N5a*',
|
||||
NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
|
||||
80, 24, 0, 0, strlen($terminal_modes), $terminal_modes);
|
||||
$this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes);
|
||||
|
||||
if (!$this->_send_binary_packet($packet)) {
|
||||
return false;
|
||||
|
@ -2557,11 +2670,12 @@ class Net_SSH2
|
|||
/**
|
||||
* Is the connection still active?
|
||||
*
|
||||
* @return boolean
|
||||
* @access public
|
||||
*/
|
||||
function isConnected()
|
||||
{
|
||||
return $this->bitmap & NET_SSH2_MASK_LOGIN;
|
||||
return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2611,6 +2725,11 @@ class Net_SSH2
|
|||
$buffer = '';
|
||||
while ($remaining_length > 0) {
|
||||
$temp = fread($this->fsock, $remaining_length);
|
||||
if ($temp === false || feof($this->fsock)) {
|
||||
user_error('Error reading from socket');
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
}
|
||||
$buffer.= $temp;
|
||||
$remaining_length-= strlen($temp);
|
||||
}
|
||||
|
@ -2624,7 +2743,11 @@ class Net_SSH2
|
|||
|
||||
if ($this->hmac_check !== false) {
|
||||
$hmac = fread($this->fsock, $this->hmac_size);
|
||||
if ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
|
||||
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
|
||||
user_error('Error reading socket');
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
} elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
|
||||
user_error('Invalid HMAC');
|
||||
return false;
|
||||
}
|
||||
|
@ -2688,7 +2811,7 @@ class Net_SSH2
|
|||
}
|
||||
|
||||
// see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
|
||||
if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
|
||||
if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
|
||||
$this->_string_shift($payload, 1);
|
||||
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
|
||||
$this->banner_message = utf8_decode($this->_string_shift($payload, $length));
|
||||
|
@ -2696,7 +2819,7 @@ class Net_SSH2
|
|||
}
|
||||
|
||||
// only called when we've already logged in
|
||||
if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) {
|
||||
if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && ($this->bitmap & NET_SSH2_MASK_LOGIN)) {
|
||||
switch (ord($payload[0])) {
|
||||
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
|
||||
$this->_string_shift($payload, 1);
|
||||
|
@ -2763,6 +2886,20 @@ class Net_SSH2
|
|||
$this->quiet_mode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Quiet Mode is enabled or not
|
||||
*
|
||||
* @see Net_SSH2::enableQuietMode()
|
||||
* @see Net_SSH2::disableQuietMode()
|
||||
*
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
function isQuietModeEnabled()
|
||||
{
|
||||
return $this->quiet_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable request-pty when using exec()
|
||||
*
|
||||
|
@ -2783,6 +2920,20 @@ class Net_SSH2
|
|||
$this->request_pty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether request-pty is enabled or not
|
||||
*
|
||||
* @see Net_SSH2::enablePTY()
|
||||
* @see Net_SSH2::disablePTY()
|
||||
*
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
function isPTYEnabled()
|
||||
{
|
||||
return $this->request_pty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets channel data
|
||||
*
|
||||
|
@ -2834,7 +2985,7 @@ class Net_SSH2
|
|||
|
||||
extract(unpack('Ctype/Nchannel', $this->_string_shift($response, 5)));
|
||||
|
||||
$this->window_size_server_to_client[$channel]-= strlen($response) + 4;
|
||||
$this->window_size_server_to_client[$channel]-= strlen($response);
|
||||
|
||||
// resize the window, if appropriate
|
||||
if ($this->window_size_server_to_client[$channel] < 0) {
|
||||
|
@ -2908,7 +3059,7 @@ class Net_SSH2
|
|||
// currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
|
||||
extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
|
||||
$data = $this->_string_shift($response, $length);
|
||||
$this->stdErrorLog .= $data;
|
||||
$this->stdErrorLog.= $data;
|
||||
if ($skip_extended || $this->quiet_mode) {
|
||||
break;
|
||||
}
|
||||
|
@ -3124,54 +3275,37 @@ class Net_SSH2
|
|||
*/
|
||||
function _send_channel_packet($client_channel, $data)
|
||||
{
|
||||
/* The maximum amount of data allowed is determined by the maximum
|
||||
packet size for the channel, and the current window size, whichever
|
||||
is smaller.
|
||||
|
||||
-- http://tools.ietf.org/html/rfc4254#section-5.2 */
|
||||
$max_size = min(
|
||||
$this->packet_size_client_to_server[$client_channel],
|
||||
$this->window_size_client_to_server[$client_channel]
|
||||
) - 4;
|
||||
while (strlen($data) > $max_size) {
|
||||
while (strlen($data)) {
|
||||
if (!$this->window_size_client_to_server[$client_channel]) {
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
// using an invalid channel will let the buffers be built up for the valid channels
|
||||
$output = $this->_get_channel_packet(-1);
|
||||
$this->_get_channel_packet(-1);
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
$max_size = min(
|
||||
$this->packet_size_client_to_server[$client_channel],
|
||||
$this->window_size_client_to_server[$client_channel]
|
||||
) - 4;
|
||||
}
|
||||
|
||||
/* The maximum amount of data allowed is determined by the maximum
|
||||
packet size for the channel, and the current window size, whichever
|
||||
is smaller.
|
||||
-- http://tools.ietf.org/html/rfc4254#section-5.2 */
|
||||
$max_size = min(
|
||||
$this->packet_size_client_to_server[$client_channel],
|
||||
$this->window_size_client_to_server[$client_channel]
|
||||
);
|
||||
|
||||
$temp = $this->_string_shift($data, $max_size);
|
||||
$packet = pack('CN2a*',
|
||||
NET_SSH2_MSG_CHANNEL_DATA,
|
||||
$this->server_channels[$client_channel],
|
||||
$max_size,
|
||||
$this->_string_shift($data, $max_size)
|
||||
strlen($temp),
|
||||
$temp
|
||||
);
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= $max_size + 4;
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= strlen($temp);
|
||||
if (!$this->_send_binary_packet($packet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen($data) >= $this->window_size_client_to_server[$client_channel] - 4) {
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
$this->_get_channel_packet(-1);
|
||||
$this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST;
|
||||
}
|
||||
|
||||
$this->window_size_client_to_server[$client_channel]-= strlen($data) + 4;
|
||||
|
||||
return $this->_send_binary_packet(pack('CN2a*',
|
||||
NET_SSH2_MSG_CHANNEL_DATA,
|
||||
$this->server_channels[$client_channel],
|
||||
strlen($data),
|
||||
$data));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3220,7 +3354,7 @@ class Net_SSH2
|
|||
*/
|
||||
function _disconnect($reason)
|
||||
{
|
||||
if ($this->bitmap) {
|
||||
if ($this->bitmap & NET_SSH2_MASK_CONNECTED) {
|
||||
$data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
|
||||
$this->_send_binary_packet($data);
|
||||
$this->bitmap = 0;
|
||||
|
@ -3374,6 +3508,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getServerIdentification()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->server_identifier;
|
||||
}
|
||||
|
||||
|
@ -3385,6 +3521,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getKexAlgorithms()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->kex_algorithms;
|
||||
}
|
||||
|
||||
|
@ -3396,6 +3534,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getServerHostKeyAlgorithms()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->server_host_key_algorithms;
|
||||
}
|
||||
|
||||
|
@ -3407,6 +3547,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getEncryptionAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->encryption_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
@ -3418,6 +3560,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getEncryptionAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->encryption_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
@ -3429,6 +3573,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getMACAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->mac_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
@ -3440,6 +3586,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getMACAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->mac_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
@ -3451,6 +3599,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getCompressionAlgorithmsClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->compression_algorithms_client_to_server;
|
||||
}
|
||||
|
||||
|
@ -3462,6 +3612,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getCompressionAlgorithmsServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->compression_algorithms_server_to_client;
|
||||
}
|
||||
|
||||
|
@ -3473,6 +3625,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getLanguagesServer2Client()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->languages_server_to_client;
|
||||
}
|
||||
|
||||
|
@ -3484,6 +3638,8 @@ class Net_SSH2
|
|||
*/
|
||||
function getLanguagesClient2Server()
|
||||
{
|
||||
$this->_connect();
|
||||
|
||||
return $this->languages_client_to_server;
|
||||
}
|
||||
|
||||
|
@ -3512,6 +3668,12 @@ class Net_SSH2
|
|||
*/
|
||||
function getServerPublicHostKey()
|
||||
{
|
||||
if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) {
|
||||
if (!$this->_connect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$signature = $this->signature;
|
||||
$server_public_host_key = $this->server_public_host_key;
|
||||
|
||||
|
@ -3589,8 +3751,9 @@ class Net_SSH2
|
|||
$e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
|
||||
|
||||
$temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
|
||||
$n = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
|
||||
$nLength = $temp['length'];
|
||||
$rawN = $this->_string_shift($server_public_host_key, $temp['length']);
|
||||
$n = new Math_BigInteger($rawN, -256);
|
||||
$nLength = strlen(ltrim($rawN, "\0"));
|
||||
|
||||
/*
|
||||
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
|
||||
|
@ -3627,7 +3790,7 @@ class Net_SSH2
|
|||
$s = $s->toBytes();
|
||||
|
||||
$h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($this->exchange_hash));
|
||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h;
|
||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
|
||||
|
||||
if ($s != $h) {
|
||||
user_error('Bad server signature');
|
||||
|
@ -3657,30 +3820,59 @@ class Net_SSH2
|
|||
}
|
||||
|
||||
/**
|
||||
* Is a path includable?
|
||||
* Returns the number of columns for the terminal window size.
|
||||
*
|
||||
* @return Boolean
|
||||
* @access private
|
||||
* @return Integer
|
||||
* @access public
|
||||
*/
|
||||
function _is_includable($suffix)
|
||||
function getWindowColumns()
|
||||
{
|
||||
// stream_resolve_include_path was introduced in PHP 5.3.2
|
||||
if (function_exists('stream_resolve_include_path')) {
|
||||
return stream_resolve_include_path($suffix) !== false;
|
||||
}
|
||||
return $this->windowColumns;
|
||||
}
|
||||
|
||||
$paths = PATH_SEPARATOR == ':' ?
|
||||
preg_split('#(?<!phar):#', get_include_path()) :
|
||||
explode(PATH_SEPARATOR, get_include_path());
|
||||
foreach ($paths as $prefix) {
|
||||
$ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR;
|
||||
$file = $prefix . $ds . $suffix;
|
||||
/**
|
||||
* Returns the number of rows for the terminal window size.
|
||||
*
|
||||
* @return Integer
|
||||
* @access public
|
||||
*/
|
||||
function getWindowRows()
|
||||
{
|
||||
return $this->windowRows;
|
||||
}
|
||||
|
||||
if (file_exists($file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the number of columns for the terminal window size.
|
||||
*
|
||||
* @param Integer $value
|
||||
* @access public
|
||||
*/
|
||||
function setWindowColumns($value)
|
||||
{
|
||||
$this->windowColumns = $value;
|
||||
}
|
||||
|
||||
return false;
|
||||
/**
|
||||
* Sets the number of rows for the terminal window size.
|
||||
*
|
||||
* @param Integer $value
|
||||
* @access public
|
||||
*/
|
||||
function setWindowRows($value)
|
||||
{
|
||||
$this->windowRows = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of columns and rows for the terminal window size.
|
||||
*
|
||||
* @param Integer $columns
|
||||
* @param Integer $rows
|
||||
* @access public
|
||||
*/
|
||||
function setWindowSize($columns = 80, $rows = 24)
|
||||
{
|
||||
$this->windowColumns = $columns;
|
||||
$this->windowRows = $rows;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,313 @@
|
|||
<?php
|
||||
/**
|
||||
* Pure-PHP ssh-agent client.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* Here are some examples of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'System/SSH/Agent.php';
|
||||
* include 'Net/SSH2.php';
|
||||
*
|
||||
* $agent = new System_SSH_Agent();
|
||||
*
|
||||
* $ssh = new Net_SSH2('www.domain.tld');
|
||||
* if (!$ssh->login('username', $agent)) {
|
||||
* exit('Login Failed');
|
||||
* }
|
||||
*
|
||||
* echo $ssh->exec('pwd');
|
||||
* echo $ssh->exec('ls -la');
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @category System
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2014 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* Message numbers
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
|
||||
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
|
||||
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
|
||||
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
|
||||
define('SYSTEM_SSH_AGENT_FAILURE', 5);
|
||||
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
|
||||
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
||||
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
||||
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Pure-PHP ssh-agent client identity object
|
||||
*
|
||||
* Instantiation should only be performed by System_SSH_Agent class.
|
||||
* This could be thought of as implementing an interface that Crypt_RSA
|
||||
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
||||
* The methods in this interface would be getPublicKey, setSignatureMode
|
||||
* and sign since those are the methods phpseclib looks for to perform
|
||||
* public key authentication.
|
||||
*
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access internal
|
||||
*/
|
||||
class System_SSH_Agent_Identity
|
||||
{
|
||||
/**
|
||||
* Key Object
|
||||
*
|
||||
* @var Crypt_RSA
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::getPublicKey()
|
||||
*/
|
||||
var $key;
|
||||
|
||||
/**
|
||||
* Key Blob
|
||||
*
|
||||
* @var String
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::sign()
|
||||
*/
|
||||
var $key_blob;
|
||||
|
||||
/**
|
||||
* Socket Resource
|
||||
*
|
||||
* @var Resource
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::sign()
|
||||
*/
|
||||
var $fsock;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param Resource $fsock
|
||||
* @return System_SSH_Agent_Identity
|
||||
* @access private
|
||||
*/
|
||||
function System_SSH_Agent_Identity($fsock)
|
||||
{
|
||||
$this->fsock = $fsock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Key
|
||||
*
|
||||
* Called by System_SSH_Agent::requestIdentities()
|
||||
*
|
||||
* @param Crypt_RSA $key
|
||||
* @access private
|
||||
*/
|
||||
function setPublicKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->key->setPublicKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Key
|
||||
*
|
||||
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
|
||||
* but this saves a small amount of computation.
|
||||
*
|
||||
* @param String $key_blob
|
||||
* @access private
|
||||
*/
|
||||
function setPublicKeyBlob($key_blob)
|
||||
{
|
||||
$this->key_blob = $key_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Public Key
|
||||
*
|
||||
* Wrapper for $this->key->getPublicKey()
|
||||
*
|
||||
* @param Integer $format optional
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function getPublicKey($format = null)
|
||||
{
|
||||
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Signature Mode
|
||||
*
|
||||
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
|
||||
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
|
||||
*
|
||||
* @param Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function setSignatureMode($mode)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a signature
|
||||
*
|
||||
* See "2.6.2 Protocol 2 private key signature request"
|
||||
*
|
||||
* @param String $message
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function sign($message)
|
||||
{
|
||||
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
||||
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
||||
$packet = pack('Na*', strlen($packet), $packet);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed during signing');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
|
||||
user_error('Unable to retreive signature');
|
||||
}
|
||||
|
||||
$signature_blob = fread($this->fsock, $length - 1);
|
||||
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
|
||||
// the + 12 is for the other various SSH added length fields
|
||||
return substr($signature_blob, strlen('ssh-rsa') + 12);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP ssh-agent client identity factory
|
||||
*
|
||||
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
|
||||
*
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @access internal
|
||||
*/
|
||||
class System_SSH_Agent
|
||||
{
|
||||
/**
|
||||
* Socket Resource
|
||||
*
|
||||
* @var Resource
|
||||
* @access private
|
||||
*/
|
||||
var $fsock;
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*
|
||||
* @return System_SSH_Agent
|
||||
* @access public
|
||||
*/
|
||||
function System_SSH_Agent()
|
||||
{
|
||||
switch (true) {
|
||||
case isset($_SERVER['SSH_AUTH_SOCK']):
|
||||
$address = $_SERVER['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
case isset($_ENV['SSH_AUTH_SOCK']):
|
||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
default:
|
||||
user_error('SSH_AUTH_SOCK not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||
if (!$this->fsock) {
|
||||
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request Identities
|
||||
*
|
||||
* See "2.5.2 Requesting a list of protocol 2 keys"
|
||||
* Returns an array containing zero or more System_SSH_Agent_Identity objects
|
||||
*
|
||||
* @return Array
|
||||
* @access public
|
||||
*/
|
||||
function requestIdentities()
|
||||
{
|
||||
if (!$this->fsock) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed while requesting identities');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
|
||||
user_error('Unable to request identities');
|
||||
}
|
||||
|
||||
$identities = array();
|
||||
$keyCount = current(unpack('N', fread($this->fsock, 4)));
|
||||
for ($i = 0; $i < $keyCount; $i++) {
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$key_blob = fread($this->fsock, $length);
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$key_comment = fread($this->fsock, $length);
|
||||
$length = current(unpack('N', substr($key_blob, 0, 4)));
|
||||
$key_type = substr($key_blob, 4, $length);
|
||||
switch ($key_type) {
|
||||
case 'ssh-rsa':
|
||||
if (!class_exists('Crypt_RSA')) {
|
||||
include_once 'Crypt/RSA.php';
|
||||
}
|
||||
$key = new Crypt_RSA();
|
||||
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
|
||||
break;
|
||||
case 'ssh-dss':
|
||||
// not currently supported
|
||||
break;
|
||||
}
|
||||
// resources are passed by reference by default
|
||||
if (isset($key)) {
|
||||
$identity = new System_SSH_Agent_Identity($this->fsock);
|
||||
$identity->setPublicKey($key);
|
||||
$identity->setPublicKeyBlob($key_blob);
|
||||
$identities[] = $identity;
|
||||
unset($key);
|
||||
}
|
||||
}
|
||||
|
||||
return $identities;
|
||||
}
|
||||
}
|
|
@ -1,26 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* Pure-PHP ssh-agent client.
|
||||
* Pure-PHP ssh-agent client wrapper
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* Here are some examples of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include('System/SSH_Agent.php');
|
||||
* include('Net/SSH2.php');
|
||||
*
|
||||
* $agent = new System_SSH_Agent();
|
||||
*
|
||||
* $ssh = new Net_SSH2('www.domain.tld');
|
||||
* if (!$ssh->login('username', $agent)) {
|
||||
* exit('Login Failed');
|
||||
* }
|
||||
*
|
||||
* echo $ssh->exec('pwd');
|
||||
* echo $ssh->exec('ls -la');
|
||||
* ?>
|
||||
* </code>
|
||||
* Originally System_SSH_Agent was accessed as System/SSH_Agent.php instead of
|
||||
* System/SSH/Agent.php. The problem with this is that PSR0 compatible autoloaders
|
||||
* don't support that kind of directory layout hence the package being moved and
|
||||
* this "alias" being created to maintain backwards compatibility.
|
||||
*
|
||||
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -43,273 +30,10 @@
|
|||
* @category System
|
||||
* @package System_SSH_Agent
|
||||
* @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
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
* @internal See http://api.libssh.org/rfc/PROTOCOL.agent
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* Message numbers
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
|
||||
define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11);
|
||||
// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
|
||||
define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12);
|
||||
define('SYSTEM_SSH_AGENT_FAILURE', 5);
|
||||
// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
|
||||
define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13);
|
||||
// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
|
||||
define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14);
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Pure-PHP ssh-agent client identity object
|
||||
*
|
||||
* Instantiation should only be performed by System_SSH_Agent class.
|
||||
* This could be thought of as implementing an interface that Crypt_RSA
|
||||
* implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
|
||||
* The methods in this interface would be getPublicKey, setSignatureMode
|
||||
* and sign since those are the methods phpseclib looks for to perform
|
||||
* public key authentication.
|
||||
*
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access internal
|
||||
*/
|
||||
class System_SSH_Agent_Identity
|
||||
{
|
||||
/**
|
||||
* Key Object
|
||||
*
|
||||
* @var Crypt_RSA
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::getPublicKey()
|
||||
*/
|
||||
var $key;
|
||||
|
||||
/**
|
||||
* Key Blob
|
||||
*
|
||||
* @var String
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::sign()
|
||||
*/
|
||||
var $key_blob;
|
||||
|
||||
/**
|
||||
* Socket Resource
|
||||
*
|
||||
* @var Resource
|
||||
* @access private
|
||||
* @see System_SSH_Agent_Identity::sign()
|
||||
*/
|
||||
var $fsock;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param Resource $fsock
|
||||
* @return System_SSH_Agent_Identity
|
||||
* @access private
|
||||
*/
|
||||
function System_SSH_Agent_Identity($fsock)
|
||||
{
|
||||
$this->fsock = $fsock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Key
|
||||
*
|
||||
* Called by System_SSH_Agent::requestIdentities()
|
||||
*
|
||||
* @param Crypt_RSA $key
|
||||
* @access private
|
||||
*/
|
||||
function setPublicKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->key->setPublicKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Public Key
|
||||
*
|
||||
* Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key
|
||||
* but this saves a small amount of computation.
|
||||
*
|
||||
* @param String $key_blob
|
||||
* @access private
|
||||
*/
|
||||
function setPublicKeyBlob($key_blob)
|
||||
{
|
||||
$this->key_blob = $key_blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Public Key
|
||||
*
|
||||
* Wrapper for $this->key->getPublicKey()
|
||||
*
|
||||
* @param Integer $format optional
|
||||
* @return Mixed
|
||||
* @access public
|
||||
*/
|
||||
function getPublicKey($format = null)
|
||||
{
|
||||
return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Signature Mode
|
||||
*
|
||||
* Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie.
|
||||
* ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1
|
||||
*
|
||||
* @param Integer $mode
|
||||
* @access public
|
||||
*/
|
||||
function setSignatureMode($mode)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a signature
|
||||
*
|
||||
* See "2.6.2 Protocol 2 private key signature request"
|
||||
*
|
||||
* @param String $message
|
||||
* @return String
|
||||
* @access public
|
||||
*/
|
||||
function sign($message)
|
||||
{
|
||||
// the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
|
||||
$packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0);
|
||||
$packet = pack('Na*', strlen($packet), $packet);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed during signing');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) {
|
||||
user_error('Unable to retreive signature');
|
||||
}
|
||||
|
||||
$signature_blob = fread($this->fsock, $length - 1);
|
||||
// the only other signature format defined - ssh-dss - is the same length as ssh-rsa
|
||||
// the + 12 is for the other various SSH added length fields
|
||||
return substr($signature_blob, strlen('ssh-rsa') + 12);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP ssh-agent client identity factory
|
||||
*
|
||||
* requestIdentities() method pumps out System_SSH_Agent_Identity objects
|
||||
*
|
||||
* @package System_SSH_Agent
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @version 0.1.0
|
||||
* @access internal
|
||||
*/
|
||||
class System_SSH_Agent
|
||||
{
|
||||
/**
|
||||
* Socket Resource
|
||||
*
|
||||
* @var Resource
|
||||
* @access private
|
||||
*/
|
||||
var $fsock;
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*
|
||||
* @return System_SSH_Agent
|
||||
* @access public
|
||||
*/
|
||||
function System_SSH_Agent()
|
||||
{
|
||||
switch (true) {
|
||||
case isset($_SERVER['SSH_AUTH_SOCK']):
|
||||
$address = $_SERVER['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
case isset($_ENV['SSH_AUTH_SOCK']):
|
||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
default:
|
||||
user_error('SSH_AUTH_SOCK not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||
if (!$this->fsock) {
|
||||
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request Identities
|
||||
*
|
||||
* See "2.5.2 Requesting a list of protocol 2 keys"
|
||||
* Returns an array containing zero or more System_SSH_Agent_Identity objects
|
||||
*
|
||||
* @return Array
|
||||
* @access public
|
||||
*/
|
||||
function requestIdentities()
|
||||
{
|
||||
if (!$this->fsock) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed while requesting identities');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) {
|
||||
user_error('Unable to request identities');
|
||||
}
|
||||
|
||||
$identities = array();
|
||||
$keyCount = current(unpack('N', fread($this->fsock, 4)));
|
||||
for ($i = 0; $i < $keyCount; $i++) {
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$key_blob = fread($this->fsock, $length);
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$key_comment = fread($this->fsock, $length);
|
||||
$length = current(unpack('N', substr($key_blob, 0, 4)));
|
||||
$key_type = substr($key_blob, 4, $length);
|
||||
switch ($key_type) {
|
||||
case 'ssh-rsa':
|
||||
if (!class_exists('Crypt_RSA')) {
|
||||
include_once 'Crypt/RSA.php';
|
||||
}
|
||||
$key = new Crypt_RSA();
|
||||
$key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment);
|
||||
break;
|
||||
case 'ssh-dss':
|
||||
// not currently supported
|
||||
break;
|
||||
}
|
||||
// resources are passed by reference by default
|
||||
if (isset($key)) {
|
||||
$identity = new System_SSH_Agent_Identity($this->fsock);
|
||||
$identity->setPublicKey($key);
|
||||
$identity->setPublicKeyBlob($key_blob);
|
||||
$identities[] = $identity;
|
||||
unset($key);
|
||||
}
|
||||
}
|
||||
|
||||
return $identities;
|
||||
}
|
||||
}
|
||||
require_once 'SSH/Agent.php';
|
||||
|
|
Loading…
Reference in New Issue