mirror of
https://github.com/phpseclib/phpseclib.git
synced 2025-01-26 00:28:27 +00:00
Merge remote-tracking branch 'upstream/master' into rsa-plugins
Conflicts: phpseclib/Crypt/RSA.php phpseclib/Net/SSH2.php
This commit is contained in:
commit
91887c957d
@ -1,6 +1,6 @@
|
||||
# phpseclib - PHP Secure Communications Library
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/phpseclib/phpseclib.png?branch=2.0)](http://travis-ci.org/phpseclib/phpseclib)
|
||||
[![Build Status](https://secure.travis-ci.org/phpseclib/phpseclib.png?branch=master)](http://travis-ci.org/phpseclib/phpseclib)
|
||||
|
||||
MIT-licensed pure-PHP implementations of an arbitrary-precision integer
|
||||
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
|
||||
@ -8,7 +8,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
|
||||
|
||||
* [Download (1.0.0)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.0.zip/download)
|
||||
* [Browse Git](https://github.com/phpseclib/phpseclib)
|
||||
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/2.0/latest/)
|
||||
* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/latest/)
|
||||
|
||||
<img src="http://phpseclib.sourceforge.net/pear-icon.png" alt="PEAR Channel" width="16" height="16">
|
||||
PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm)
|
||||
@ -16,7 +16,7 @@ PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.
|
||||
## Documentation
|
||||
|
||||
* [Documentation / Manual](http://phpseclib.sourceforge.net/)
|
||||
* [API Documentation](http://phpseclib.bantux.org/api/2.0/) (generated by Sami)
|
||||
* [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami)
|
||||
|
||||
## Support
|
||||
|
||||
|
@ -605,6 +605,7 @@ abstract class Base
|
||||
* @see Crypt/Hash.php
|
||||
* @param string $password
|
||||
* @param string $method
|
||||
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
||||
* @return bool
|
||||
* @access public
|
||||
* @internal Could, but not must, extend by the child Crypt_* class
|
||||
@ -639,8 +640,7 @@ abstract class Base
|
||||
$hashObj = new Hash();
|
||||
$hashObj->setHash($hash);
|
||||
if ($dkLen > $hashObj->getLength()) {
|
||||
user_error('Derived key too long');
|
||||
return false;
|
||||
throw new \LengthException('Derived key length cannot be longer than the hash length');
|
||||
}
|
||||
$t = $password . $salt;
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
@ -1827,6 +1827,7 @@ abstract class Base
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base::_unpad()
|
||||
* @param string $text
|
||||
* @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
@ -1838,8 +1839,7 @@ abstract class Base
|
||||
if ($length % $this->block_size == 0) {
|
||||
return $text;
|
||||
} else {
|
||||
user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
|
||||
$this->padding = true;
|
||||
throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1856,6 +1856,7 @@ abstract class Base
|
||||
*
|
||||
* @see \phpseclib\Crypt\Base::_pad()
|
||||
* @param string $text
|
||||
* @throws \LengthException if the ciphertext's length is not a multiple of the block size
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
@ -1868,7 +1869,7 @@ abstract class Base
|
||||
$length = ord($text[strlen($text) - 1]);
|
||||
|
||||
if (!$length || $length > $this->block_size) {
|
||||
return false;
|
||||
throw new \LengthException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})");
|
||||
}
|
||||
|
||||
return substr($text, 0, -$length);
|
||||
|
@ -1,26 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||
* Wrapper around hash() and hash_hmac() functions supporting truncated hashes
|
||||
* such as sha256-96. Any hash algorithm returned by hash_algos() (and
|
||||
* truncated versions thereof) are supported.
|
||||
*
|
||||
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
||||
*
|
||||
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
||||
*
|
||||
* If {@link \phpseclib\Crypt\Hash::setKey() setKey()} is called, {@link \phpseclib\Crypt\Hash::hash() hash()} will return the HMAC as opposed to
|
||||
* the hash. If no valid algorithm is provided, sha1 will be used.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* {@internal The variable names are the same as those in
|
||||
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
|
||||
* If {@link \phpseclib\Crypt\Hash::setKey() setKey()} is called,
|
||||
* {@link \phpseclib\Crypt\Hash::hash() hash()} will return the HMAC as opposed
|
||||
* to the hash.
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'vendor/autoload.php';
|
||||
*
|
||||
* $hash = new \phpseclib\Crypt\Hash('sha1');
|
||||
* $hash = new \phpseclib\Crypt\Hash('sha512');
|
||||
*
|
||||
* $hash->setKey('abcdefg');
|
||||
*
|
||||
@ -31,42 +25,25 @@
|
||||
* @category Crypt
|
||||
* @package Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2007 Jim Wigginton
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2015 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\Crypt;
|
||||
|
||||
use phpseclib\Math\BigInteger;
|
||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
||||
*
|
||||
* @package Hash
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @access public
|
||||
*/
|
||||
class Hash
|
||||
{
|
||||
/**#@+
|
||||
* @access private
|
||||
* @see \phpseclib\Crypt\Hash::__construct()
|
||||
*/
|
||||
/**
|
||||
* Toggles the internal implementation
|
||||
*/
|
||||
const MODE_INTERNAL = 1;
|
||||
/**
|
||||
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
|
||||
*/
|
||||
const MODE_MHASH = 2;
|
||||
/**
|
||||
* Toggles the hash() implementation, which works on PHP 5.1.2+.
|
||||
*/
|
||||
const MODE_HASH = 3;
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Hash Parameter
|
||||
*
|
||||
@ -76,15 +53,6 @@ class Hash
|
||||
*/
|
||||
var $hashParam;
|
||||
|
||||
/**
|
||||
* Byte-length of compression blocks / key (Internal HMAC)
|
||||
*
|
||||
* @see \phpseclib\Crypt\Hash::setAlgorithm()
|
||||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
var $b;
|
||||
|
||||
/**
|
||||
* Byte-length of hash output (Internal HMAC)
|
||||
*
|
||||
@ -92,7 +60,7 @@ class Hash
|
||||
* @var int
|
||||
* @access private
|
||||
*/
|
||||
var $l = false;
|
||||
var $length;
|
||||
|
||||
/**
|
||||
* Hash Algorithm
|
||||
@ -112,46 +80,14 @@ class Hash
|
||||
*/
|
||||
var $key = false;
|
||||
|
||||
/**
|
||||
* Outer XOR (Internal HMAC)
|
||||
*
|
||||
* @see \phpseclib\Crypt\Hash::setKey()
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $opad;
|
||||
|
||||
/**
|
||||
* Inner XOR (Internal HMAC)
|
||||
*
|
||||
* @see \phpseclib\Crypt\Hash::setKey()
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $ipad;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return \phpseclib\Crypt\Hash
|
||||
* @access public
|
||||
*/
|
||||
function __construct($hash = 'sha1')
|
||||
function __construct($hash = 'sha256')
|
||||
{
|
||||
if (!defined('CRYPT_HASH_MODE')) {
|
||||
switch (true) {
|
||||
case extension_loaded('hash'):
|
||||
define('CRYPT_HASH_MODE', self::MODE_HASH);
|
||||
break;
|
||||
case extension_loaded('mhash'):
|
||||
define('CRYPT_HASH_MODE', self::MODE_MHASH);
|
||||
break;
|
||||
default:
|
||||
define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setHash($hash);
|
||||
}
|
||||
|
||||
@ -196,96 +132,47 @@ class Hash
|
||||
case 'sha256-96':
|
||||
case 'sha512-96':
|
||||
$hash = substr($hash, 0, -3);
|
||||
$this->l = 12; // 96 / 8 = 12
|
||||
$this->length = 12; // 96 / 8 = 12
|
||||
break;
|
||||
case 'md2':
|
||||
case 'md5':
|
||||
$this->l = 16;
|
||||
$this->length = 16;
|
||||
break;
|
||||
case 'sha1':
|
||||
$this->l = 20;
|
||||
$this->length = 20;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->l = 32;
|
||||
$this->length = 32;
|
||||
break;
|
||||
case 'sha384':
|
||||
$this->l = 48;
|
||||
$this->length = 48;
|
||||
break;
|
||||
case 'sha512':
|
||||
$this->l = 64;
|
||||
}
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2':
|
||||
$mode = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
|
||||
self::MODE_HASH : self::MODE_INTERNAL;
|
||||
break;
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||
$this->length = 64;
|
||||
break;
|
||||
default:
|
||||
$mode = CRYPT_HASH_MODE;
|
||||
}
|
||||
|
||||
switch ($mode) {
|
||||
case self::MODE_MHASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
$this->hash = MHASH_MD5;
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->hash = MHASH_SHA256;
|
||||
break;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->hash = MHASH_SHA1;
|
||||
// see if the hash isn't "officially" supported see if it can
|
||||
// be "unofficially" supported and calculate the length
|
||||
// accordingly.
|
||||
if (in_array($hash, hash_algos())) {
|
||||
$this->length = strlen(hash($hash, '', true));
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case self::MODE_HASH:
|
||||
switch ($hash) {
|
||||
case 'md5':
|
||||
$this->hash = 'md5';
|
||||
return;
|
||||
case 'md2':
|
||||
case 'sha256':
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$this->hash = $hash;
|
||||
return;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->hash = 'sha1';
|
||||
// if the hash algorithm doens't exist maybe it's a truncated
|
||||
// hash, e.g. whirlpool-12 or some such.
|
||||
if (preg_match('#(-\d+)$#', $hash, $matches)) {
|
||||
$hash = substr($hash, 0, -strlen($matches[1]));
|
||||
if (in_array($hash, hash_algos())) {
|
||||
$this->length = abs($matches[1]) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
throw new UnsupportedAlgorithmException(
|
||||
"$hash is not a supported algorithm"
|
||||
);
|
||||
}
|
||||
|
||||
switch ($hash) {
|
||||
case 'md2':
|
||||
$this->b = 16;
|
||||
$this->hash = array($this, '_md2');
|
||||
break;
|
||||
case 'md5':
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_md5');
|
||||
break;
|
||||
case 'sha256':
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_sha256');
|
||||
break;
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
$this->b = 128;
|
||||
$this->hash = array($this, '_sha512');
|
||||
break;
|
||||
case 'sha1':
|
||||
default:
|
||||
$this->b = 64;
|
||||
$this->hash = array($this, '_sha1');
|
||||
}
|
||||
|
||||
$this->ipad = str_repeat(chr(0x36), $this->b);
|
||||
$this->opad = str_repeat(chr(0x5C), $this->b);
|
||||
$this->hash = $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,45 +184,13 @@ class Hash
|
||||
*/
|
||||
function hash($text)
|
||||
{
|
||||
$mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
||||
$output = !empty($this->key) || is_string($this->key) ?
|
||||
hash_hmac($this->hash, $text, $this->key, true) :
|
||||
hash($this->hash, $text, true);
|
||||
|
||||
if (!empty($this->key) || is_string($this->key)) {
|
||||
switch ($mode) {
|
||||
case self::MODE_MHASH:
|
||||
$output = mhash($this->hash, $text, $this->key);
|
||||
break;
|
||||
case self::MODE_HASH:
|
||||
$output = hash_hmac($this->hash, $text, $this->key, true);
|
||||
break;
|
||||
case self::MODE_INTERNAL:
|
||||
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
|
||||
resultant L byte string as the actual key to HMAC."
|
||||
|
||||
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
||||
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
|
||||
|
||||
$key = str_pad($key, $this->b, chr(0)); // step 1
|
||||
$temp = $this->ipad ^ $key; // step 2
|
||||
$temp .= $text; // step 3
|
||||
$temp = call_user_func($this->hash, $temp); // step 4
|
||||
$output = $this->opad ^ $key; // step 5
|
||||
$output.= $temp; // step 6
|
||||
$output = call_user_func($this->hash, $output); // step 7
|
||||
}
|
||||
} else {
|
||||
switch ($mode) {
|
||||
case self::MODE_MHASH:
|
||||
$output = mhash($this->hash, $text);
|
||||
break;
|
||||
case self::MODE_HASH:
|
||||
$output = hash($this->hash, $text, true);
|
||||
break;
|
||||
case self::MODE_INTERNAL:
|
||||
$output = call_user_func($this->hash, $text);
|
||||
}
|
||||
}
|
||||
|
||||
return substr($output, 0, $this->l);
|
||||
return strlen($output) > $this->length
|
||||
? substr($output, 0, $this->length)
|
||||
: $output;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,480 +201,6 @@ class Hash
|
||||
*/
|
||||
function getLength()
|
||||
{
|
||||
return $this->l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for MD5
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _md5($m)
|
||||
{
|
||||
return pack('H*', md5($m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for SHA1
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha1($m)
|
||||
{
|
||||
return pack('H*', sha1($m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of MD2
|
||||
*
|
||||
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _md2($m)
|
||||
{
|
||||
static $s = array(
|
||||
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
||||
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
||||
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
||||
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
||||
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
||||
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
||||
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
||||
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
||||
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
||||
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
||||
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
||||
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
||||
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
||||
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
||||
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
||||
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
||||
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
||||
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
||||
);
|
||||
|
||||
// Step 1. Append Padding Bytes
|
||||
$pad = 16 - (strlen($m) & 0xF);
|
||||
$m.= str_repeat(chr($pad), $pad);
|
||||
|
||||
$length = strlen($m);
|
||||
|
||||
// Step 2. Append Checksum
|
||||
$c = str_repeat(chr(0), 16);
|
||||
$l = chr(0);
|
||||
for ($i = 0; $i < $length; $i+= 16) {
|
||||
for ($j = 0; $j < 16; $j++) {
|
||||
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
|
||||
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
||||
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
|
||||
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
|
||||
$l = $c[$j];
|
||||
}
|
||||
}
|
||||
$m.= $c;
|
||||
|
||||
$length+= 16;
|
||||
|
||||
// Step 3. Initialize MD Buffer
|
||||
$x = str_repeat(chr(0), 48);
|
||||
|
||||
// Step 4. Process Message in 16-Byte Blocks
|
||||
for ($i = 0; $i < $length; $i+= 16) {
|
||||
for ($j = 0; $j < 16; $j++) {
|
||||
$x[$j + 16] = $m[$i + $j];
|
||||
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
|
||||
}
|
||||
$t = chr(0);
|
||||
for ($j = 0; $j < 18; $j++) {
|
||||
for ($k = 0; $k < 48; $k++) {
|
||||
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
|
||||
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
|
||||
}
|
||||
$t = chr(ord($t) + $j);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5. Output
|
||||
return substr($x, 0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SHA256
|
||||
*
|
||||
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha256($m)
|
||||
{
|
||||
if (extension_loaded('suhosin')) {
|
||||
return pack('H*', sha256($m));
|
||||
}
|
||||
|
||||
// Initialize variables
|
||||
$hash = array(
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
);
|
||||
// Initialize table of round constants
|
||||
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
||||
static $k = array(
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
);
|
||||
|
||||
// Pre-processing
|
||||
$length = strlen($m);
|
||||
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
|
||||
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
|
||||
$m[$length] = chr(0x80);
|
||||
// we don't support hashing strings 512MB long
|
||||
$m.= pack('N2', 0, $length << 3);
|
||||
|
||||
// Process the message in successive 512-bit chunks
|
||||
$chunks = str_split($m, 64);
|
||||
foreach ($chunks as $chunk) {
|
||||
$w = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
|
||||
$w[] = $temp;
|
||||
}
|
||||
|
||||
// Extend the sixteen 32-bit words into sixty-four 32-bit words
|
||||
for ($i = 16; $i < 64; $i++) {
|
||||
// @codingStandardsIgnoreStart
|
||||
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
|
||||
$this->_rightRotate($w[$i - 15], 18) ^
|
||||
$this->_rightShift( $w[$i - 15], 3);
|
||||
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
|
||||
$this->_rightRotate($w[$i - 2], 19) ^
|
||||
$this->_rightShift( $w[$i - 2], 10);
|
||||
// @codingStandardsIgnoreEnd
|
||||
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
|
||||
|
||||
}
|
||||
|
||||
// Initialize hash value for this chunk
|
||||
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
|
||||
|
||||
// Main loop
|
||||
for ($i = 0; $i < 64; $i++) {
|
||||
$s0 = $this->_rightRotate($a, 2) ^
|
||||
$this->_rightRotate($a, 13) ^
|
||||
$this->_rightRotate($a, 22);
|
||||
$maj = ($a & $b) ^
|
||||
($a & $c) ^
|
||||
($b & $c);
|
||||
$t2 = $this->_add($s0, $maj);
|
||||
|
||||
$s1 = $this->_rightRotate($e, 6) ^
|
||||
$this->_rightRotate($e, 11) ^
|
||||
$this->_rightRotate($e, 25);
|
||||
$ch = ($e & $f) ^
|
||||
($this->_not($e) & $g);
|
||||
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
|
||||
|
||||
$h = $g;
|
||||
$g = $f;
|
||||
$f = $e;
|
||||
$e = $this->_add($d, $t1);
|
||||
$d = $c;
|
||||
$c = $b;
|
||||
$b = $a;
|
||||
$a = $this->_add($t1, $t2);
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far
|
||||
$hash = array(
|
||||
$this->_add($hash[0], $a),
|
||||
$this->_add($hash[1], $b),
|
||||
$this->_add($hash[2], $c),
|
||||
$this->_add($hash[3], $d),
|
||||
$this->_add($hash[4], $e),
|
||||
$this->_add($hash[5], $f),
|
||||
$this->_add($hash[6], $g),
|
||||
$this->_add($hash[7], $h)
|
||||
);
|
||||
}
|
||||
|
||||
// Produce the final hash value (big-endian)
|
||||
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SHA384 and SHA512
|
||||
*
|
||||
* @access private
|
||||
* @param string $m
|
||||
*/
|
||||
function _sha512($m)
|
||||
{
|
||||
static $init384, $init512, $k;
|
||||
|
||||
if (!isset($k)) {
|
||||
// Initialize variables
|
||||
$init384 = array( // initial values for SHA384
|
||||
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
|
||||
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
|
||||
);
|
||||
$init512 = array( // initial values for SHA512
|
||||
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
|
||||
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
|
||||
);
|
||||
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$init384[$i] = new BigInteger($init384[$i], 16);
|
||||
$init384[$i]->setPrecision(64);
|
||||
$init512[$i] = new BigInteger($init512[$i], 16);
|
||||
$init512[$i]->setPrecision(64);
|
||||
}
|
||||
|
||||
// Initialize table of round constants
|
||||
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
||||
$k = array(
|
||||
'428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
|
||||
'3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
|
||||
'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
|
||||
'72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
|
||||
'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
|
||||
'2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
|
||||
'983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
|
||||
'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
|
||||
'27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
|
||||
'650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
|
||||
'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
|
||||
'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
|
||||
'19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
|
||||
'391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
|
||||
'748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
|
||||
'90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
|
||||
'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
|
||||
'06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
|
||||
'28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
|
||||
'4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
|
||||
);
|
||||
|
||||
for ($i = 0; $i < 80; $i++) {
|
||||
$k[$i] = new BigInteger($k[$i], 16);
|
||||
}
|
||||
}
|
||||
|
||||
$hash = $this->l == 48 ? $init384 : $init512;
|
||||
|
||||
// Pre-processing
|
||||
$length = strlen($m);
|
||||
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
||||
$m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
|
||||
$m[$length] = chr(0x80);
|
||||
// we don't support hashing strings 512MB long
|
||||
$m.= pack('N4', 0, 0, 0, $length << 3);
|
||||
|
||||
// Process the message in successive 1024-bit chunks
|
||||
$chunks = str_split($m, 128);
|
||||
foreach ($chunks as $chunk) {
|
||||
$w = array();
|
||||
for ($i = 0; $i < 16; $i++) {
|
||||
$temp = new BigInteger($this->_string_shift($chunk, 8), 256);
|
||||
$temp->setPrecision(64);
|
||||
$w[] = $temp;
|
||||
}
|
||||
|
||||
// Extend the sixteen 32-bit words into eighty 32-bit words
|
||||
for ($i = 16; $i < 80; $i++) {
|
||||
$temp = array(
|
||||
$w[$i - 15]->bitwise_rightRotate(1),
|
||||
$w[$i - 15]->bitwise_rightRotate(8),
|
||||
$w[$i - 15]->bitwise_rightShift(7)
|
||||
);
|
||||
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
||||
$s0 = $s0->bitwise_xor($temp[2]);
|
||||
$temp = array(
|
||||
$w[$i - 2]->bitwise_rightRotate(19),
|
||||
$w[$i - 2]->bitwise_rightRotate(61),
|
||||
$w[$i - 2]->bitwise_rightShift(6)
|
||||
);
|
||||
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||
$s1 = $s1->bitwise_xor($temp[2]);
|
||||
$w[$i] = $w[$i - 16]->copy();
|
||||
$w[$i] = $w[$i]->add($s0);
|
||||
$w[$i] = $w[$i]->add($w[$i - 7]);
|
||||
$w[$i] = $w[$i]->add($s1);
|
||||
}
|
||||
|
||||
// Initialize hash value for this chunk
|
||||
$a = $hash[0]->copy();
|
||||
$b = $hash[1]->copy();
|
||||
$c = $hash[2]->copy();
|
||||
$d = $hash[3]->copy();
|
||||
$e = $hash[4]->copy();
|
||||
$f = $hash[5]->copy();
|
||||
$g = $hash[6]->copy();
|
||||
$h = $hash[7]->copy();
|
||||
|
||||
// Main loop
|
||||
for ($i = 0; $i < 80; $i++) {
|
||||
$temp = array(
|
||||
$a->bitwise_rightRotate(28),
|
||||
$a->bitwise_rightRotate(34),
|
||||
$a->bitwise_rightRotate(39)
|
||||
);
|
||||
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
||||
$s0 = $s0->bitwise_xor($temp[2]);
|
||||
$temp = array(
|
||||
$a->bitwise_and($b),
|
||||
$a->bitwise_and($c),
|
||||
$b->bitwise_and($c)
|
||||
);
|
||||
$maj = $temp[0]->bitwise_xor($temp[1]);
|
||||
$maj = $maj->bitwise_xor($temp[2]);
|
||||
$t2 = $s0->add($maj);
|
||||
|
||||
$temp = array(
|
||||
$e->bitwise_rightRotate(14),
|
||||
$e->bitwise_rightRotate(18),
|
||||
$e->bitwise_rightRotate(41)
|
||||
);
|
||||
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
||||
$s1 = $s1->bitwise_xor($temp[2]);
|
||||
$temp = array(
|
||||
$e->bitwise_and($f),
|
||||
$g->bitwise_and($e->bitwise_not())
|
||||
);
|
||||
$ch = $temp[0]->bitwise_xor($temp[1]);
|
||||
$t1 = $h->add($s1);
|
||||
$t1 = $t1->add($ch);
|
||||
$t1 = $t1->add($k[$i]);
|
||||
$t1 = $t1->add($w[$i]);
|
||||
|
||||
$h = $g->copy();
|
||||
$g = $f->copy();
|
||||
$f = $e->copy();
|
||||
$e = $d->add($t1);
|
||||
$d = $c->copy();
|
||||
$c = $b->copy();
|
||||
$b = $a->copy();
|
||||
$a = $t1->add($t2);
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far
|
||||
$hash = array(
|
||||
$hash[0]->add($a),
|
||||
$hash[1]->add($b),
|
||||
$hash[2]->add($c),
|
||||
$hash[3]->add($d),
|
||||
$hash[4]->add($e),
|
||||
$hash[5]->add($f),
|
||||
$hash[6]->add($g),
|
||||
$hash[7]->add($h)
|
||||
);
|
||||
}
|
||||
|
||||
// Produce the final hash value (big-endian)
|
||||
// (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
|
||||
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
|
||||
$hash[4]->toBytes() . $hash[5]->toBytes();
|
||||
if ($this->l != 48) {
|
||||
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
|
||||
}
|
||||
|
||||
return $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Rotate
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @param int $amt
|
||||
* @see _sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _rightRotate($int, $amt)
|
||||
{
|
||||
$invamt = 32 - $amt;
|
||||
$mask = (1 << $invamt) - 1;
|
||||
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Shift
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @param int $amt
|
||||
* @see _sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _rightShift($int, $amt)
|
||||
{
|
||||
$mask = (1 << (32 - $amt)) - 1;
|
||||
return ($int >> $amt) & $mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not
|
||||
*
|
||||
* @access private
|
||||
* @param int $int
|
||||
* @see _sha256()
|
||||
* @return int
|
||||
*/
|
||||
function _not($int)
|
||||
{
|
||||
return ~$int & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add
|
||||
*
|
||||
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
||||
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
|
||||
*
|
||||
* @param int $...
|
||||
* @return int
|
||||
* @see _sha256()
|
||||
* @access private
|
||||
*/
|
||||
function _add()
|
||||
{
|
||||
static $mod;
|
||||
if (!isset($mod)) {
|
||||
$mod = pow(2, 32);
|
||||
}
|
||||
|
||||
$result = 0;
|
||||
$arguments = func_get_args();
|
||||
foreach ($arguments as $argument) {
|
||||
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
|
||||
}
|
||||
|
||||
return fmod($result, $mod);
|
||||
}
|
||||
|
||||
/**
|
||||
* String Shift
|
||||
*
|
||||
* Inspired by array_shift
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $index
|
||||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
function _string_shift(&$string, $index = 1)
|
||||
{
|
||||
$substr = substr($string, 0, $index);
|
||||
$string = substr($string, $index);
|
||||
return $substr;
|
||||
return $this->length;
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,9 @@
|
||||
*
|
||||
* $plaintext = 'terrafrost';
|
||||
*
|
||||
* $rsa->loadKey($privatekey);
|
||||
* $signature = $rsa->sign($plaintext);
|
||||
* $signature = $privatekey->sign($plaintext);
|
||||
*
|
||||
* $rsa->loadKey($publickey);
|
||||
* echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified';
|
||||
* echo $publickey->verify($plaintext, $signature) ? 'verified' : 'unverified';
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
@ -351,6 +349,20 @@ class RSA
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize static variables
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
static function _initialize_static_variables()
|
||||
{
|
||||
if (!isset(self::$zero)) {
|
||||
self::$zero= new BigInteger(0);
|
||||
self::$one = new BigInteger(1);
|
||||
self::$configFile = __DIR__ . '/../openssl.cnf';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*
|
||||
@ -664,7 +676,6 @@ class RSA
|
||||
$this->encryptionMode = $key->encryptionMode;
|
||||
$this->signatureMode = $key->signatureMode;
|
||||
$this->password = $key->password;
|
||||
$this->configFile = $key->configFile;
|
||||
$this->comment = $key->comment;
|
||||
|
||||
if (is_object($key->hash)) {
|
||||
|
@ -49,6 +49,7 @@ class Random
|
||||
* eg. for RSA key generation.
|
||||
*
|
||||
* @param int $length
|
||||
* @throws \RuntimeException if a symmetric cipher is needed but not loaded
|
||||
* @return string
|
||||
*/
|
||||
static function string($length)
|
||||
@ -211,8 +212,7 @@ class Random
|
||||
$crypto = new RC4();
|
||||
break;
|
||||
default:
|
||||
user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||
return false;
|
||||
throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
|
||||
}
|
||||
|
||||
$crypto->setKey($key);
|
||||
|
26
phpseclib/Exception/BadConfigurationException.php
Normal file
26
phpseclib/Exception/BadConfigurationException.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* BadConfigurationException
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Exception
|
||||
* @package BadConfigurationException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\Exception;
|
||||
|
||||
/**
|
||||
* BadConfigurationException
|
||||
*
|
||||
* @package BadConfigurationException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class BadConfigurationException extends \RuntimeException
|
||||
{
|
||||
}
|
26
phpseclib/Exception/FileNotFoundException.php
Normal file
26
phpseclib/Exception/FileNotFoundException.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* FileNotFoundException
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Exception
|
||||
* @package FileNotFoundException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\Exception;
|
||||
|
||||
/**
|
||||
* FileNotFoundException
|
||||
*
|
||||
* @package FileNotFoundException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class FileNotFoundException extends \RuntimeException
|
||||
{
|
||||
}
|
26
phpseclib/Exception/NoSupportedAlgorithmsException.php
Normal file
26
phpseclib/Exception/NoSupportedAlgorithmsException.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* NoSupportedAlgorithmsException
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Exception
|
||||
* @package NoSupportedAlgorithmsException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\Exception;
|
||||
|
||||
/**
|
||||
* NoSupportedAlgorithmsException
|
||||
*
|
||||
* @package NoSupportedAlgorithmsException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class NoSupportedAlgorithmsException extends \RuntimeException
|
||||
{
|
||||
}
|
26
phpseclib/Exception/UnsupportedAlgorithmException.php
Normal file
26
phpseclib/Exception/UnsupportedAlgorithmException.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UnsupportedAlgorithmException
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Exception
|
||||
* @package UnsupportedAlgorithmException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @copyright 2015 Jim Wigginton
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @link http://phpseclib.sourceforge.net
|
||||
*/
|
||||
|
||||
namespace phpseclib\Exception;
|
||||
|
||||
/**
|
||||
* UnsupportedAlgorithmException
|
||||
*
|
||||
* @package UnsupportedAlgorithmException
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
*/
|
||||
class UnsupportedAlgorithmException extends \RuntimeException
|
||||
{
|
||||
}
|
@ -793,6 +793,7 @@ class ASN1
|
||||
* @param string $mapping
|
||||
* @param int $idx
|
||||
* @return string
|
||||
* @throws \RuntimeException if the input has an error in it
|
||||
* @access private
|
||||
*/
|
||||
function _encode_der($source, $mapping, $idx = null, $special = array())
|
||||
@ -985,7 +986,7 @@ class ASN1
|
||||
case self::TYPE_OBJECT_IDENTIFIER:
|
||||
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
||||
if ($oid === false) {
|
||||
user_error('Invalid OID');
|
||||
throw new \RuntimeException('Invalid OID');
|
||||
return false;
|
||||
}
|
||||
$value = '';
|
||||
@ -1038,7 +1039,7 @@ class ASN1
|
||||
$filters = $filters[$part];
|
||||
}
|
||||
if ($filters === false) {
|
||||
user_error('No filters defined for ' . implode('/', $loc));
|
||||
throw new \RuntimeException('No filters defined for ' . implode('/', $loc));
|
||||
return false;
|
||||
}
|
||||
return $this->_encode_der($source, $filters + $mapping, null, $special);
|
||||
@ -1062,7 +1063,7 @@ class ASN1
|
||||
$value = $source ? "\xFF" : "\x00";
|
||||
break;
|
||||
default:
|
||||
user_error('Mapping provides no type definition for ' . implode('/', $this->location));
|
||||
throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', $this->location));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ use phpseclib\Crypt\Random;
|
||||
use phpseclib\File\ASN1;
|
||||
use phpseclib\File\ASN1\Element;
|
||||
use phpseclib\Math\BigInteger;
|
||||
use phpseclib\Exception\UnsupportedAlgorithmException;
|
||||
|
||||
/**
|
||||
* Pure-PHP X.509 Parser
|
||||
@ -1641,7 +1642,7 @@ class X509
|
||||
$map = $this->_getMapping($id);
|
||||
if (is_bool($map)) {
|
||||
if (!$map) {
|
||||
user_error($id . ' is not a currently supported extension');
|
||||
//user_error($id . ' is not a currently supported extension');
|
||||
unset($extensions[$i]);
|
||||
}
|
||||
} else {
|
||||
@ -1714,7 +1715,7 @@ class X509
|
||||
$id = $attributes[$i]['type'];
|
||||
$map = $this->_getMapping($id);
|
||||
if ($map === false) {
|
||||
user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
||||
//user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
||||
unset($attributes[$i]);
|
||||
} elseif (is_array($attributes[$i]['value'])) {
|
||||
$values = &$attributes[$i]['value'];
|
||||
@ -2107,7 +2108,8 @@ class X509
|
||||
/**
|
||||
* Validates a signature
|
||||
*
|
||||
* Returns true if the signature is verified, false if it is not correct or null on error
|
||||
* Returns true if the signature is verified and false if it is not correct.
|
||||
* If the algorithms are unsupposed an exception is thrown.
|
||||
*
|
||||
* @param string $publicKeyAlgorithm
|
||||
* @param string $publicKey
|
||||
@ -2115,7 +2117,8 @@ class X509
|
||||
* @param string $signature
|
||||
* @param string $signatureSubject
|
||||
* @access private
|
||||
* @return int
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @return bool
|
||||
*/
|
||||
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
|
||||
{
|
||||
@ -2139,11 +2142,11 @@ class X509
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
throw new UnsupportedAlgorithmException('Public key algorithm unsupported');
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3628,6 +3631,7 @@ class X509
|
||||
* @param \phpseclib\File\X509 $subject
|
||||
* @param string $signatureAlgorithm
|
||||
* @access public
|
||||
* @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
|
||||
* @return mixed
|
||||
*/
|
||||
function _sign($key, $signatureAlgorithm)
|
||||
@ -3646,10 +3650,12 @@ class X509
|
||||
|
||||
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
|
||||
return $this->currentCert;
|
||||
default:
|
||||
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
throw new UnsupportedAlgorithmException('Unsupported public key algorithm');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,7 @@ namespace phpseclib\Net;
|
||||
|
||||
use phpseclib\Net\SSH1;
|
||||
use phpseclib\Net\SSH2;
|
||||
use phpseclib\Exception\FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of SCP.
|
||||
@ -140,6 +141,7 @@ class SCP
|
||||
* @param string $data
|
||||
* @param int $mode
|
||||
* @param callable $callback
|
||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -168,8 +170,7 @@ class SCP
|
||||
$size = strlen($data);
|
||||
} else {
|
||||
if (!is_file($data)) {
|
||||
user_error("$data is not a valid file", E_USER_NOTICE);
|
||||
return false;
|
||||
throw new FileNotFoundException("$data is not a valid file");
|
||||
}
|
||||
|
||||
$fp = @fopen($data, 'rb');
|
||||
@ -289,6 +290,7 @@ class SCP
|
||||
* Receives a packet from an SSH server
|
||||
*
|
||||
* @return string
|
||||
* @throws \UnexpectedValueException on receipt of an unexpected packet
|
||||
* @access private
|
||||
*/
|
||||
function _receive()
|
||||
@ -314,8 +316,7 @@ class SCP
|
||||
$this->ssh->bitmap = 0;
|
||||
return false;
|
||||
default:
|
||||
user_error('Unknown packet received', E_USER_NOTICE);
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Unknown packet received');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
namespace phpseclib\Net;
|
||||
|
||||
use phpseclib\Net\SSH2;
|
||||
use phpseclib\Exception\FileNotFoundException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementations of SFTP.
|
||||
@ -383,6 +384,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -470,8 +472,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_VERSION) {
|
||||
user_error('Expected SSH_FXP_VERSION');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_VERSION');
|
||||
}
|
||||
|
||||
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
||||
@ -610,6 +611,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @see \phpseclib\Net\SFTP::chdir()
|
||||
* @param string $path
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access private
|
||||
*/
|
||||
@ -634,8 +636,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,6 +667,7 @@ class SFTP extends SSH2
|
||||
* Changes the current directory
|
||||
*
|
||||
* @param string $dir
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -710,8 +712,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (!$this->_close_handle($handle)) {
|
||||
@ -813,6 +814,7 @@ class SFTP extends SSH2
|
||||
* @param string $dir
|
||||
* @param bool $raw
|
||||
* @return mixed
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _list($dir, $raw = true)
|
||||
@ -844,8 +846,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
$this->_update_stat_cache($dir, array());
|
||||
@ -899,8 +900,7 @@ class SFTP extends SSH2
|
||||
}
|
||||
break 2;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1259,6 +1259,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $type
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access private
|
||||
*/
|
||||
@ -1279,8 +1280,7 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1306,6 +1306,7 @@ class SFTP extends SSH2
|
||||
* @param string $filename
|
||||
* @param int $time
|
||||
* @param int $atime
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -1342,8 +1343,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
break;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
return $this->_setstat($filename, $attr, false);
|
||||
@ -1396,6 +1396,7 @@ class SFTP extends SSH2
|
||||
* @param int $mode
|
||||
* @param string $filename
|
||||
* @param bool $recursive
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
@ -1433,8 +1434,7 @@ class SFTP extends SSH2
|
||||
return false;
|
||||
}
|
||||
|
||||
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1443,6 +1443,7 @@ class SFTP extends SSH2
|
||||
* @param string $filename
|
||||
* @param string $attr
|
||||
* @param bool $recursive
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access private
|
||||
*/
|
||||
@ -1481,8 +1482,7 @@ class SFTP extends SSH2
|
||||
*/
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -1570,6 +1570,7 @@ class SFTP extends SSH2
|
||||
* Return the target of a symbolic link
|
||||
*
|
||||
* @param string $link
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
@ -1593,8 +1594,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
||||
@ -1614,6 +1614,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param string $target
|
||||
* @param string $link
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -1633,8 +1634,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -1686,6 +1686,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _mkdir_helper($dir, $attr)
|
||||
@ -1696,8 +1697,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -1713,6 +1713,7 @@ class SFTP extends SSH2
|
||||
* Removes a directory.
|
||||
*
|
||||
* @param string $dir
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
@ -1733,8 +1734,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -1794,6 +1794,9 @@ class SFTP extends SSH2
|
||||
* @param int $start
|
||||
* @param int $local_start
|
||||
* @param callable|null $progressCallback
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid
|
||||
* @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
|
||||
* @return bool
|
||||
* @access public
|
||||
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
|
||||
@ -1841,8 +1844,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
||||
@ -1850,7 +1852,7 @@ class SFTP extends SSH2
|
||||
switch (true) {
|
||||
case $mode & self::SOURCE_CALLBACK:
|
||||
if (!is_callable($data)) {
|
||||
user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
||||
throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
|
||||
}
|
||||
$dataCallback = $data;
|
||||
// do nothing
|
||||
@ -1861,8 +1863,7 @@ class SFTP extends SSH2
|
||||
break;
|
||||
case $mode & self::SOURCE_LOCAL_FILE:
|
||||
if (!is_file($data)) {
|
||||
user_error("$data is not a valid file");
|
||||
return false;
|
||||
throw new FileNotFoundException("$data is not a valid file");
|
||||
}
|
||||
$fp = @fopen($data, 'rb');
|
||||
if (!$fp) {
|
||||
@ -1876,10 +1877,7 @@ class SFTP extends SSH2
|
||||
|
||||
if ($local_start >= 0) {
|
||||
fseek($fp, $local_start);
|
||||
} elseif ($mode & self::RESUME_START) {
|
||||
// do nothing
|
||||
} else {
|
||||
fseek($fp, $offset);
|
||||
$size-= $local_start;
|
||||
}
|
||||
} elseif ($dataCallback) {
|
||||
$size = 0;
|
||||
@ -1950,6 +1948,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param int $i
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _read_put_responses($i)
|
||||
@ -1957,8 +1956,7 @@ class SFTP extends SSH2
|
||||
while ($i--) {
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -1976,6 +1974,7 @@ class SFTP extends SSH2
|
||||
*
|
||||
* @param string $handle
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access private
|
||||
*/
|
||||
function _close_handle($handle)
|
||||
@ -1988,8 +1987,7 @@ class SFTP extends SSH2
|
||||
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
||||
@ -2014,6 +2012,7 @@ class SFTP extends SSH2
|
||||
* @param string $local_file
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
@ -2042,8 +2041,7 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
return false;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if (is_resource($local_file)) {
|
||||
@ -2091,11 +2089,10 @@ class SFTP extends SSH2
|
||||
$this->_logError($response);
|
||||
break 2;
|
||||
default:
|
||||
user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
||||
if ($fclose_check) {
|
||||
fclose($fp);
|
||||
}
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
if ($length > 0 && $length <= $offset - $start) {
|
||||
@ -2129,6 +2126,7 @@ class SFTP extends SSH2
|
||||
* @param string $path
|
||||
* @param bool $recursive
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function delete($path, $recursive = true)
|
||||
@ -2149,8 +2147,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
@ -2482,6 +2479,7 @@ class SFTP extends SSH2
|
||||
* @param string $oldname
|
||||
* @param string $newname
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function rename($oldname, $newname)
|
||||
@ -2504,8 +2502,7 @@ class SFTP extends SSH2
|
||||
|
||||
$response = $this->_get_sftp_packet();
|
||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
||||
user_error('Expected SSH_FXP_STATUS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_FXP_STATUS');
|
||||
}
|
||||
|
||||
// if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||
|
@ -19,6 +19,7 @@ namespace phpseclib\Net\SFTP;
|
||||
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\Net\SFTP;
|
||||
use phpseclib\Net\SSH2;
|
||||
|
||||
/**
|
||||
* SFTP Stream Wrapper
|
||||
@ -166,13 +167,12 @@ class Stream
|
||||
}
|
||||
}
|
||||
|
||||
if ($host[0] == '$') {
|
||||
$host = substr($host, 1);
|
||||
global $$host;
|
||||
if (($$host instanceof SFTP) === false) {
|
||||
if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
|
||||
$host = SSH2::getConnectionByResourceId($host);
|
||||
if ($host === false) {
|
||||
return false;
|
||||
}
|
||||
$this->sftp = $$host;
|
||||
$this->sftp = $host;
|
||||
} else {
|
||||
if (isset($this->context)) {
|
||||
$context = stream_context_get_options($this->context);
|
||||
|
@ -537,14 +537,15 @@ class SSH1
|
||||
* Connect to an SSHv1 server
|
||||
*
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _connect()
|
||||
{
|
||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
|
||||
if (!$this->fsock) {
|
||||
user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr"));
|
||||
return false;
|
||||
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
}
|
||||
|
||||
$this->server_identification = $init_line = fgets($this->fsock, 255);
|
||||
@ -555,20 +556,17 @@ class SSH1
|
||||
}
|
||||
|
||||
if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) {
|
||||
user_error('Can only connect to SSH servers');
|
||||
return false;
|
||||
throw new \RuntimeException('Can only connect to SSH servers');
|
||||
}
|
||||
if ($parts[1][0] != 1) {
|
||||
user_error("Cannot connect to SSH $parts[1] servers");
|
||||
return false;
|
||||
throw new \RuntimeException("Cannot connect to $parts[1] servers");
|
||||
}
|
||||
|
||||
fputs($this->fsock, $this->identifier."\r\n");
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
|
||||
user_error('Expected SSH_SMSG_PUBLIC_KEY');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY');
|
||||
}
|
||||
|
||||
$anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8);
|
||||
@ -652,8 +650,7 @@ class SSH1
|
||||
$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 false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY');
|
||||
}
|
||||
|
||||
switch ($cipher) {
|
||||
@ -682,8 +679,7 @@ class SSH1
|
||||
$response = $this->_get_binary_packet();
|
||||
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
||||
}
|
||||
|
||||
$this->bitmap = self::MASK_CONNECTED;
|
||||
@ -697,6 +693,8 @@ class SSH1
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access public
|
||||
*/
|
||||
function login($username, $password = '')
|
||||
@ -715,8 +713,7 @@ class SSH1
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_USER');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_USER');
|
||||
}
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
@ -728,15 +725,13 @@ class SSH1
|
||||
$this->bitmap |= self::MASK_LOGIN;
|
||||
return true;
|
||||
} elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_AUTH_PASSWORD');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD');
|
||||
}
|
||||
|
||||
// remove the username and password from the last logged packet
|
||||
@ -756,8 +751,7 @@ class SSH1
|
||||
} elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) {
|
||||
return false;
|
||||
} else {
|
||||
user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE');
|
||||
}
|
||||
}
|
||||
|
||||
@ -792,20 +786,19 @@ class SSH1
|
||||
* @see \phpseclib\Net\SSH1::interactiveWrite()
|
||||
* @param string $cmd
|
||||
* @return mixed
|
||||
* @throws \RuntimeException on error sending command
|
||||
* @access public
|
||||
*/
|
||||
function exec($cmd, $block = true)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_EXEC_CMD');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD');
|
||||
}
|
||||
|
||||
if (!$block) {
|
||||
@ -841,6 +834,8 @@ class SSH1
|
||||
* @see \phpseclib\Net\SSH1::interactiveRead()
|
||||
* @see \phpseclib\Net\SSH1::interactiveWrite()
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _initShell()
|
||||
@ -851,8 +846,7 @@ class SSH1
|
||||
$data = pack('CNa*N4C', NET_SSH1_CMSG_REQUEST_PTY, strlen('vt100'), 'vt100', 24, 80, 0, 0, self::TTY_OP_END);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_REQUEST_PTY');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY');
|
||||
}
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
@ -861,15 +855,13 @@ class SSH1
|
||||
return false;
|
||||
}
|
||||
if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
|
||||
user_error('Expected SSH_SMSG_SUCCESS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS');
|
||||
}
|
||||
|
||||
$data = pack('C', NET_SSH1_CMSG_EXEC_SHELL);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_EXEC_SHELL');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL');
|
||||
}
|
||||
|
||||
$this->bitmap |= self::MASK_SHELL;
|
||||
@ -902,18 +894,17 @@ class SSH1
|
||||
* @param string $expect
|
||||
* @param int $mode
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function read($expect, $mode = self::READ__SIMPLE)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$match = $expect;
|
||||
@ -941,25 +932,23 @@ class SSH1
|
||||
* @see \phpseclib\Net\SSH1::interactiveRead()
|
||||
* @param string $cmd
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function interactiveWrite($cmd)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Error sending SSH_CMSG_STDIN');
|
||||
return false;
|
||||
throw new \RuntimeException('Error sending SSH_CMSG_STDIN');
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -976,18 +965,17 @@ class SSH1
|
||||
*
|
||||
* @see \phpseclib\Net\SSH1::interactiveRead()
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function interactiveRead()
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$read = array($this->fsock);
|
||||
@ -1313,7 +1301,7 @@ class SSH1
|
||||
{
|
||||
/*
|
||||
$rsa = new RSA();
|
||||
$rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW);
|
||||
$rsa->load($key, RSA::PUBLIC_FORMAT_RAW);
|
||||
$rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1);
|
||||
return $rsa->encrypt($m);
|
||||
*/
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
* $key = new \phpseclib\Crypt\RSA();
|
||||
* //$key->setPassword('whatever');
|
||||
* $key->loadKey(file_get_contents('privatekey'));
|
||||
* $key->load(file_get_contents('privatekey'));
|
||||
*
|
||||
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
|
||||
* if (!$ssh->login('username', $key)) {
|
||||
@ -60,6 +60,7 @@ use phpseclib\Crypt\TripleDES;
|
||||
use phpseclib\Crypt\Twofish;
|
||||
use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
|
||||
use phpseclib\System\SSH\Agent;
|
||||
use phpseclib\Exception\NoSupportedAlgorithmsException;
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SSHv2.
|
||||
@ -866,6 +867,14 @@ class SSH2
|
||||
*/
|
||||
var $agent;
|
||||
|
||||
/**
|
||||
* Connection storage to replicates ssh2 extension functionality:
|
||||
* {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
|
||||
*
|
||||
* @var SSH2[]
|
||||
*/
|
||||
static $connections;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*
|
||||
@ -959,6 +968,8 @@ class SSH2
|
||||
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
|
||||
);
|
||||
|
||||
self::$connections[$this->getResourceId()] = $this;
|
||||
|
||||
if (is_resource($host)) {
|
||||
$this->fsock = $host;
|
||||
return;
|
||||
@ -989,6 +1000,8 @@ class SSH2
|
||||
* Connect to an SSHv2 server
|
||||
*
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _connect()
|
||||
@ -1008,8 +1021,7 @@ class SSH2
|
||||
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
|
||||
if (!$this->fsock) {
|
||||
$host = $this->host . ':' . $this->port;
|
||||
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
return false;
|
||||
throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
|
||||
}
|
||||
$elapsed = microtime(true) - $start;
|
||||
|
||||
@ -1060,8 +1072,7 @@ class SSH2
|
||||
}
|
||||
|
||||
if (feof($this->fsock)) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
$this->identifier = $this->_generate_identifier();
|
||||
@ -1077,21 +1088,18 @@ class SSH2
|
||||
}
|
||||
|
||||
if ($matches[1] != '1.99' && $matches[1] != '2.0') {
|
||||
user_error("Cannot connect to SSH $matches[1] servers");
|
||||
return false;
|
||||
throw new \RuntimeException("Cannot connect to SSH $matches[1] servers");
|
||||
}
|
||||
|
||||
fputs($this->fsock, $this->identifier . "\r\n");
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
|
||||
user_error('Expected SSH_MSG_KEXINIT');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
|
||||
}
|
||||
|
||||
if (!$this->_key_exchange($response)) {
|
||||
@ -1143,6 +1151,9 @@ class SSH2
|
||||
* Key Exchange
|
||||
*
|
||||
* @param string $kexinit_payload_server
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @throws \phpseclib\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible
|
||||
* @access private
|
||||
*/
|
||||
function _key_exchange($kexinit_payload_server)
|
||||
@ -1354,27 +1365,28 @@ class SSH2
|
||||
// here ends the second place.
|
||||
|
||||
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
|
||||
|
||||
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
|
||||
// diffie-hellman key exchange as fast as possible
|
||||
$decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client);
|
||||
$decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt);
|
||||
if ($decryptKeyLength === null) {
|
||||
user_error('No compatible server to client encryption algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found');
|
||||
}
|
||||
|
||||
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
|
||||
$encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt);
|
||||
if ($encryptKeyLength === null) {
|
||||
user_error('No compatible client to server encryption algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found');
|
||||
}
|
||||
|
||||
// through diffie-hellman key exchange a symmetric key is obtained
|
||||
$kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms);
|
||||
if ($kex_algorithm === false) {
|
||||
user_error('No compatible key exchange algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found');
|
||||
}
|
||||
|
||||
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
|
||||
@ -1491,20 +1503,17 @@ class SSH2
|
||||
$data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
|
||||
|
||||
if (!$this->_send_binary_packet($data)) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
|
||||
if ($type != $serverKexReplyMessage) {
|
||||
user_error('Expected SSH_MSG_KEXDH_REPLY');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_MSG_KEXDH_REPLY');
|
||||
}
|
||||
|
||||
$temp = unpack('Nlength', $this->_string_shift($response, 4));
|
||||
@ -1564,13 +1573,13 @@ class SSH2
|
||||
|
||||
$server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
|
||||
if ($server_host_key_algorithm === false) {
|
||||
user_error('No compatible server host key algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found');
|
||||
}
|
||||
|
||||
if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) {
|
||||
user_error('Server Host Key Algorithm Mismatch');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new \RuntimeException('Server Host Key Algorithm Mismatch');
|
||||
}
|
||||
|
||||
$packet = pack(
|
||||
@ -1585,15 +1594,13 @@ class SSH2
|
||||
$response = $this->_get_binary_packet();
|
||||
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
|
||||
if ($type != NET_SSH2_MSG_NEWKEYS) {
|
||||
user_error('Expected SSH_MSG_NEWKEYS');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS');
|
||||
}
|
||||
|
||||
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
|
||||
@ -1662,8 +1669,8 @@ class SSH2
|
||||
|
||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server);
|
||||
if ($mac_algorithm === false) {
|
||||
user_error('No compatible client to server message authentication algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found');
|
||||
}
|
||||
|
||||
$createKeyLength = 0; // ie. $mac_algorithm == 'none'
|
||||
@ -1691,8 +1698,8 @@ class SSH2
|
||||
|
||||
$mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client);
|
||||
if ($mac_algorithm === false) {
|
||||
user_error('No compatible server to client message authentication algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found');
|
||||
}
|
||||
|
||||
$checkKeyLength = 0;
|
||||
@ -1738,15 +1745,15 @@ class SSH2
|
||||
|
||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client);
|
||||
if ($compression_algorithm === false) {
|
||||
user_error('No compatible server to client compression algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found');
|
||||
}
|
||||
$this->decompress = $compression_algorithm == 'zlib';
|
||||
|
||||
$compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server);
|
||||
if ($compression_algorithm === false) {
|
||||
user_error('No compatible client to server compression algorithms found');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found');
|
||||
}
|
||||
$this->compress = $compression_algorithm == 'zlib';
|
||||
|
||||
@ -1891,6 +1898,8 @@ class SSH2
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
||||
* by sending dummy SSH_MSG_IGNORE messages.
|
||||
@ -1915,15 +1924,13 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
|
||||
if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) {
|
||||
user_error('Expected SSH_MSG_SERVICE_ACCEPT');
|
||||
return false;
|
||||
throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT');
|
||||
}
|
||||
$this->bitmap |= self::MASK_LOGIN_REQ;
|
||||
}
|
||||
@ -1964,8 +1971,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
@ -2019,8 +2025,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
@ -2096,6 +2101,7 @@ class SSH2
|
||||
*
|
||||
* @param string $responses...
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access private
|
||||
*/
|
||||
function _keyboard_interactive_process()
|
||||
@ -2107,8 +2113,7 @@ class SSH2
|
||||
} else {
|
||||
$orig = $response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
}
|
||||
|
||||
@ -2232,6 +2237,7 @@ class SSH2
|
||||
* @param string $username
|
||||
* @param \phpseclib\Crypt\RSA $password
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access private
|
||||
* @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
|
||||
* by sending dummy SSH_MSG_IGNORE messages.
|
||||
@ -2277,8 +2283,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
@ -2312,8 +2317,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
extract(unpack('Ctype', $this->_string_shift($response, 1)));
|
||||
@ -2363,6 +2367,7 @@ class SSH2
|
||||
* @param string $command
|
||||
* @param Callback $callback
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function exec($command, $callback = null)
|
||||
@ -2430,8 +2435,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
||||
@ -2441,8 +2445,8 @@ class SSH2
|
||||
break;
|
||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||
default:
|
||||
user_error('Unable to request pseudo-terminal');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \RuntimeException('Unable to request pseudo-terminal');
|
||||
}
|
||||
$this->in_request_pty_exec = true;
|
||||
}
|
||||
@ -2510,6 +2514,8 @@ class SSH2
|
||||
* @see \phpseclib\Net\SSH2::read()
|
||||
* @see \phpseclib\Net\SSH2::write()
|
||||
* @return bool
|
||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||
* @throws \RuntimeException on other errors
|
||||
* @access private
|
||||
*/
|
||||
function _initShell()
|
||||
@ -2566,8 +2572,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
|
||||
list(, $type) = unpack('C', $this->_string_shift($response, 1));
|
||||
@ -2578,8 +2583,8 @@ class SSH2
|
||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||
break;
|
||||
default:
|
||||
user_error('Unable to request pseudo-terminal');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \UnexpectedValueException('Unable to request pseudo-terminal');
|
||||
}
|
||||
|
||||
$packet = pack(
|
||||
@ -2656,6 +2661,7 @@ class SSH2
|
||||
* @param string $expect
|
||||
* @param int $mode
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function read($expect = '', $mode = self::READ_SIMPLE)
|
||||
@ -2664,13 +2670,11 @@ class SSH2
|
||||
$this->is_timeout = false;
|
||||
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
$channel = $this->_get_interactive_channel();
|
||||
@ -2701,18 +2705,17 @@ class SSH2
|
||||
* @see \phpseclib\Net\SSH2::read()
|
||||
* @param string $cmd
|
||||
* @return bool
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access public
|
||||
*/
|
||||
function write($cmd)
|
||||
{
|
||||
if (!($this->bitmap & self::MASK_LOGIN)) {
|
||||
user_error('Operation disallowed prior to login()');
|
||||
return false;
|
||||
throw new \RuntimeException('Operation disallowed prior to login()');
|
||||
}
|
||||
|
||||
if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) {
|
||||
user_error('Unable to initiate an interactive shell session');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to initiate an interactive shell session');
|
||||
}
|
||||
|
||||
return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd);
|
||||
@ -2836,6 +2839,7 @@ class SSH2
|
||||
if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
|
||||
fclose($this->realtime_log_file);
|
||||
}
|
||||
unset(self::$connections[$this->getResourceId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2869,14 +2873,14 @@ class SSH2
|
||||
*
|
||||
* @see \phpseclib\Net\SSH2::_send_binary_packet()
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access private
|
||||
*/
|
||||
function _get_binary_packet()
|
||||
{
|
||||
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
||||
user_error('Connection closed prematurely');
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed prematurely');
|
||||
}
|
||||
|
||||
$start = microtime(true);
|
||||
@ -2890,8 +2894,7 @@ class SSH2
|
||||
$raw = $this->decrypt->decrypt($raw);
|
||||
}
|
||||
if ($raw === false) {
|
||||
user_error('Unable to decrypt content');
|
||||
return false;
|
||||
throw new \RuntimeException('Unable to decrypt content');
|
||||
}
|
||||
|
||||
extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5)));
|
||||
@ -2902,17 +2905,15 @@ class SSH2
|
||||
// "implementations SHOULD check that the packet length is reasonable"
|
||||
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
|
||||
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
|
||||
user_error('Invalid size');
|
||||
return false;
|
||||
throw new \RuntimeException('Invalid size');
|
||||
}
|
||||
|
||||
$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;
|
||||
throw new \RuntimeException('Error reading from socket');
|
||||
}
|
||||
$buffer.= $temp;
|
||||
$remaining_length-= strlen($temp);
|
||||
@ -2928,12 +2929,10 @@ class SSH2
|
||||
if ($this->hmac_check !== false) {
|
||||
$hmac = fread($this->fsock, $this->hmac_size);
|
||||
if ($hmac === false || strlen($hmac) != $this->hmac_size) {
|
||||
user_error('Error reading socket');
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
throw new \RuntimeException('Error reading socket');
|
||||
} elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) {
|
||||
user_error('Invalid HMAC');
|
||||
return false;
|
||||
throw new \RuntimeException('Invalid HMAC');
|
||||
}
|
||||
}
|
||||
|
||||
@ -3161,6 +3160,7 @@ class SSH2
|
||||
*
|
||||
* @param $client_channel
|
||||
* @return mixed
|
||||
* @throws \RuntimeException on connection error
|
||||
* @access private
|
||||
*/
|
||||
function _get_channel_packet($client_channel, $skip_extended = false)
|
||||
@ -3193,8 +3193,7 @@ class SSH2
|
||||
|
||||
$response = $this->_get_binary_packet();
|
||||
if ($response === false) {
|
||||
user_error('Connection closed by server');
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed by server');
|
||||
}
|
||||
if ($client_channel == -1 && $response === true) {
|
||||
return true;
|
||||
@ -3243,8 +3242,8 @@ class SSH2
|
||||
return $result;
|
||||
//case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
|
||||
default:
|
||||
user_error('Unable to open channel');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \RuntimeException('Unable to open channel');
|
||||
}
|
||||
break;
|
||||
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||
@ -3254,8 +3253,8 @@ class SSH2
|
||||
case NET_SSH2_MSG_CHANNEL_FAILURE:
|
||||
return false;
|
||||
default:
|
||||
user_error('Unable to fulfill channel request');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \RuntimeException('Unable to fulfill channel request');
|
||||
}
|
||||
case NET_SSH2_MSG_CHANNEL_CLOSE:
|
||||
return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended);
|
||||
@ -3364,8 +3363,8 @@ class SSH2
|
||||
case NET_SSH2_MSG_CHANNEL_EOF:
|
||||
break;
|
||||
default:
|
||||
user_error('Error reading channel data');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
|
||||
throw new \RuntimeException('Error reading channel data');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3384,9 +3383,8 @@ class SSH2
|
||||
function _send_binary_packet($data, $logged = null)
|
||||
{
|
||||
if (!is_resource($this->fsock) || feof($this->fsock)) {
|
||||
user_error('Connection closed prematurely');
|
||||
$this->bitmap = 0;
|
||||
return false;
|
||||
throw new \RuntimeException('Connection closed prematurely');
|
||||
}
|
||||
|
||||
//if ($this->compress) {
|
||||
@ -3945,6 +3943,8 @@ class SSH2
|
||||
* is recommended. Returns false if the server signature is not signed correctly with the public host key.
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \RuntimeException on badly formatted keys
|
||||
* @throws \phpseclib\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format
|
||||
* @access public
|
||||
*/
|
||||
function getServerPublicHostKey()
|
||||
@ -3990,8 +3990,8 @@ class SSH2
|
||||
padding, unsigned, and in network byte order). */
|
||||
$temp = unpack('Nlength', $this->_string_shift($signature, 4));
|
||||
if ($temp['length'] != 40) {
|
||||
user_error('Invalid signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new \RuntimeException('Invalid signature');
|
||||
}
|
||||
|
||||
$r = new BigInteger($this->_string_shift($signature, 20), 256);
|
||||
@ -4002,8 +4002,8 @@ class SSH2
|
||||
case $r->compare($q) >= 0:
|
||||
case $s->equals($zero):
|
||||
case $s->compare($q) >= 0:
|
||||
user_error('Invalid signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new \RuntimeException('Invalid signature');
|
||||
}
|
||||
|
||||
$w = $s->modInverse($q);
|
||||
@ -4022,7 +4022,7 @@ class SSH2
|
||||
list(, $v) = $v->divide($q);
|
||||
|
||||
if (!$v->equals($r)) {
|
||||
user_error('Bad server signature');
|
||||
//user_error('Bad server signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||
}
|
||||
|
||||
@ -4042,9 +4042,9 @@ class SSH2
|
||||
|
||||
$rsa = new RSA();
|
||||
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||
$rsa->loadKey(array('e' => $e, 'n' => $n), 'Raw');
|
||||
$rsa->load(array('e' => $e, 'n' => $n), 'Raw');
|
||||
if (!$rsa->verify($this->exchange_hash, $signature)) {
|
||||
user_error('Bad server signature');
|
||||
//user_error('Bad server signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||
}
|
||||
*/
|
||||
@ -4059,8 +4059,8 @@ class SSH2
|
||||
// also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
|
||||
|
||||
if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) {
|
||||
user_error('Invalid signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||
throw new \RuntimeException('Invalid signature');
|
||||
}
|
||||
|
||||
$s = $s->modPow($e, $n);
|
||||
@ -4070,13 +4070,13 @@ class SSH2
|
||||
$h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h;
|
||||
|
||||
if ($s != $h) {
|
||||
user_error('Bad server signature');
|
||||
//user_error('Bad server signature');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
user_error('Unsupported signature format');
|
||||
return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||
$this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
|
||||
throw new NoSupportedAlgorithmsException('Unsupported signature format');
|
||||
}
|
||||
|
||||
return $this->signature_format . ' ' . base64_encode($this->server_public_host_key);
|
||||
@ -4152,4 +4152,47 @@ class SSH2
|
||||
$this->windowColumns = $columns;
|
||||
$this->windowRows = $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function __toString()
|
||||
{
|
||||
return $this->getResourceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* We use {} because that symbols should not be in URL according to
|
||||
* {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}.
|
||||
* It will safe us from any conflicts, because otherwise regexp will
|
||||
* match all alphanumeric domains.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getResourceId()
|
||||
{
|
||||
return '{' . spl_object_hash($this) . '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return existing connection
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return bool|SSH2 will return false if no such connection
|
||||
*/
|
||||
static function getConnectionByResourceId($id)
|
||||
{
|
||||
return isset(self::$connections[$id]) ? self::$connections[$id] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all excising connections
|
||||
*
|
||||
* @return SSH2[]
|
||||
*/
|
||||
static function getConnections()
|
||||
{
|
||||
return self::$connections;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ namespace phpseclib\System\SSH;
|
||||
|
||||
use phpseclib\Crypt\RSA;
|
||||
use phpseclib\System\SSH\Agent\Identity;
|
||||
use phpseclib\Exception\BadConfigurationException;
|
||||
|
||||
/**
|
||||
* Pure-PHP ssh-agent client identity factory
|
||||
@ -115,6 +116,8 @@ class Agent
|
||||
* Default Constructor
|
||||
*
|
||||
* @return \phpseclib\System\SSH\Agent
|
||||
* @throws \phpseclib\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access public
|
||||
*/
|
||||
function __construct()
|
||||
@ -127,13 +130,12 @@ class Agent
|
||||
$address = $_ENV['SSH_AUTH_SOCK'];
|
||||
break;
|
||||
default:
|
||||
user_error('SSH_AUTH_SOCK not found');
|
||||
return false;
|
||||
throw new \BadConfigurationException('SSH_AUTH_SOCK not found');
|
||||
}
|
||||
|
||||
$this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr);
|
||||
if (!$this->fsock) {
|
||||
user_error("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +146,7 @@ class Agent
|
||||
* Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects
|
||||
*
|
||||
* @return array
|
||||
* @throws \RuntimeException on receipt of unexpected packets
|
||||
* @access public
|
||||
*/
|
||||
function requestIdentities()
|
||||
@ -154,13 +157,13 @@ class Agent
|
||||
|
||||
$packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
|
||||
if (strlen($packet) != fputs($this->fsock, $packet)) {
|
||||
user_error('Connection closed while requesting identities');
|
||||
throw new \RuntimeException('Connection closed while requesting identities');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
|
||||
user_error('Unable to request identities');
|
||||
throw new \RuntimeException('Unable to request identities');
|
||||
}
|
||||
|
||||
$identities = array();
|
||||
@ -271,6 +274,7 @@ class Agent
|
||||
*
|
||||
* @param string $data
|
||||
* @return data from SSH Agent
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access private
|
||||
*/
|
||||
function _forward_data($data)
|
||||
@ -289,7 +293,7 @@ class Agent
|
||||
}
|
||||
|
||||
if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
|
||||
user_error('Connection closed attempting to forward data to SSH agent');
|
||||
throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
|
||||
}
|
||||
|
||||
$this->socket_buffer = '';
|
||||
|
@ -134,6 +134,7 @@ class Identity
|
||||
*
|
||||
* @param string $message
|
||||
* @return string
|
||||
* @throws \RuntimeException on connection errors
|
||||
* @access public
|
||||
*/
|
||||
function sign($message)
|
||||
@ -142,13 +143,13 @@ class Identity
|
||||
$packet = pack('CNa*Na*N', Agent::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');
|
||||
throw new \RuntimeException('Connection closed during signing');
|
||||
}
|
||||
|
||||
$length = current(unpack('N', fread($this->fsock, 4)));
|
||||
$type = ord(fread($this->fsock, 1));
|
||||
if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
|
||||
user_error('Unable to retreive signature');
|
||||
throw new \RuntimeException('Unable to retreive signature');
|
||||
}
|
||||
|
||||
$signature_blob = fread($this->fsock, $length - 1);
|
||||
|
@ -27,6 +27,19 @@ class Functional_Net_SFTPStreamTest extends Functional_Net_SFTPTestCase
|
||||
$this->assertSame(0, $this->sftp->size('fooo.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests connection reuse functionality same as ssh2 extension:
|
||||
* {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
|
||||
*/
|
||||
public function testConnectionReuse()
|
||||
{
|
||||
$originalConnectionsCount = count(\phpseclib\Net\SSH2::getConnections());
|
||||
$session = $this->sftp;
|
||||
$dirs = scandir("sftp://$session/");
|
||||
$this->assertCount($originalConnectionsCount, \phpseclib\Net\SSH2::getConnections());
|
||||
$this->assertEquals(array('.', '..'), array_slice($dirs, 0, 2));
|
||||
}
|
||||
|
||||
protected function buildUrl($suffix)
|
||||
{
|
||||
return sprintf(
|
||||
|
@ -13,6 +13,9 @@ use phpseclib\Net\SFTP;
|
||||
*/
|
||||
abstract class Functional_Net_SFTPTestCase extends PhpseclibFunctionalTestCase
|
||||
{
|
||||
/**
|
||||
* @var SFTP
|
||||
*/
|
||||
protected $sftp;
|
||||
protected $scratchDir;
|
||||
|
||||
|
@ -651,5 +651,28 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
|
||||
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
|
||||
|
||||
$sftp->enableStatCache();
|
||||
|
||||
return $sftp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testStatVsLstat
|
||||
* @group github830
|
||||
*/
|
||||
public function testUploadOffsets($sftp)
|
||||
{
|
||||
$sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, 0, 10);
|
||||
$this->assertSame(
|
||||
substr(self::$exampleData, 10),
|
||||
$sftp->get('offset.txt'),
|
||||
'Failed asserting that portions of a file could be uploaded.'
|
||||
);
|
||||
|
||||
$sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, self::$exampleDataLength - 100);
|
||||
$this->assertSame(
|
||||
substr(self::$exampleData, 10, -90) . self::$exampleData,
|
||||
$sftp->get('offset.txt'),
|
||||
'Failed asserting that you could upload into the middle of a file.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,7 @@ abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase
|
||||
'Should have gmp or bcmath extension for functional test.'
|
||||
);
|
||||
}
|
||||
self::ensureConstant('CRYPT_HASH_MODE', Hash::MODE_HASH);
|
||||
self::reRequireFile('Math/BigInteger.php');
|
||||
self::reRequireFile('Crypt/Hash.php');
|
||||
}
|
||||
parent::setUpBeforeClass();
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2012 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new Hash('md5');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($message, $result)
|
||||
{
|
||||
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||
}
|
||||
|
||||
public static function hashData()
|
||||
{
|
||||
return array(
|
||||
array('', 'd41d8cd98f00b204e9800998ecf8427e'),
|
||||
array('The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'),
|
||||
array('The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($key, $message, $result)
|
||||
{
|
||||
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||
}
|
||||
|
||||
public static function hmacData()
|
||||
{
|
||||
return array(
|
||||
array('', '', '74e6f7298a9c2d168935f58c001bad88'),
|
||||
array('key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2014 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new Hash('sha256');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($message, $result)
|
||||
{
|
||||
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||
}
|
||||
|
||||
public static function hashData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'',
|
||||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
||||
),
|
||||
array(
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592',
|
||||
),
|
||||
array(
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($key, $message, $result)
|
||||
{
|
||||
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||
}
|
||||
|
||||
public static function hmacData()
|
||||
{
|
||||
return array(
|
||||
// RFC 4231
|
||||
// Test Case 1
|
||||
array(
|
||||
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||
pack('H*', '4869205468657265'),
|
||||
'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7',
|
||||
),
|
||||
// Test Case 2
|
||||
array(
|
||||
pack('H*', '4a656665'),
|
||||
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||
'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843',
|
||||
),
|
||||
// Test Case 3
|
||||
array(
|
||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||
'773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe',
|
||||
),
|
||||
// Test Case 4
|
||||
array(
|
||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||
'82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2014 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_Hash_SHA256_96Test extends Unit_Crypt_Hash_SHA256Test
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new Hash('sha256-96');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($message, $longResult)
|
||||
{
|
||||
parent::testHash($message, substr($longResult, 0, 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($key, $message, $longResult)
|
||||
{
|
||||
parent::testHMAC($key, $message, substr($longResult, 0, 24));
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2014 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new Hash('sha512');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($message, $result)
|
||||
{
|
||||
$this->assertHashesTo($this->getInstance(), $message, $result);
|
||||
}
|
||||
|
||||
public static function hashData()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'',
|
||||
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'
|
||||
),
|
||||
array(
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6',
|
||||
),
|
||||
array(
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($key, $message, $result)
|
||||
{
|
||||
$this->assertHMACsTo($this->getInstance(), $key, $message, $result);
|
||||
}
|
||||
|
||||
public static function hmacData()
|
||||
{
|
||||
return array(
|
||||
// RFC 4231
|
||||
// Test Case 1
|
||||
array(
|
||||
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||
pack('H*', '4869205468657265'),
|
||||
'87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
|
||||
),
|
||||
// Test Case 2
|
||||
array(
|
||||
pack('H*', '4a656665'),
|
||||
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||
'164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
|
||||
),
|
||||
// Test Case 3
|
||||
array(
|
||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||
'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb',
|
||||
),
|
||||
// Test Case 4
|
||||
array(
|
||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||
'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2014 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_Hash_SHA512_96Test extends Unit_Crypt_Hash_SHA512Test
|
||||
{
|
||||
public function getInstance()
|
||||
{
|
||||
return new Hash('sha512-96');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($message, $longResult)
|
||||
{
|
||||
parent::testHash($message, substr($longResult, 0, 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($key, $message, $longResult)
|
||||
{
|
||||
parent::testHMAC($key, $message, substr($longResult, 0, 24));
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2012 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
abstract class Unit_Crypt_Hash_TestCase extends PhpseclibTestCase
|
||||
{
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
if (!defined('CRYPT_HASH_MODE')) {
|
||||
define('CRYPT_HASH_MODE', Hash::MODE_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
if (defined('CRYPT_HASH_MODE') && CRYPT_HASH_MODE !== Hash::MODE_INTERNAL) {
|
||||
$this->markTestSkipped(
|
||||
'Skipping test because CRYPT_HASH_MODE is not defined as \phpseclib\Crypt\Hash::MODE_INTERNAL.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertHashesTo(Hash $hash, $message, $expected)
|
||||
{
|
||||
$this->assertEquals(
|
||||
strtolower($expected),
|
||||
bin2hex($hash->hash($message)),
|
||||
sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected)
|
||||
);
|
||||
}
|
||||
|
||||
protected function assertHMACsTo(Hash $hash, $key, $message, $expected)
|
||||
{
|
||||
$hash->setKey($key);
|
||||
|
||||
$this->assertEquals(
|
||||
strtolower($expected),
|
||||
bin2hex($hash->hash($message)),
|
||||
sprintf(
|
||||
"Failed asserting that '%s' HMACs to '%s' with key '%s'.",
|
||||
$message,
|
||||
$expected,
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
265
tests/Unit/Crypt/HashTest.php
Normal file
265
tests/Unit/Crypt/HashTest.php
Normal file
@ -0,0 +1,265 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Andreas Fischer <bantu@phpbb.com>
|
||||
* @copyright 2012 Andreas Fischer
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
*/
|
||||
|
||||
use phpseclib\Crypt\Hash;
|
||||
|
||||
class Unit_Crypt_HashTest extends PhpseclibTestCase
|
||||
{
|
||||
protected function assertHashesTo($hash, $message, $expected)
|
||||
{
|
||||
$hash = new Hash($hash);
|
||||
|
||||
$this->assertSame(
|
||||
strtolower($expected),
|
||||
bin2hex($hash->hash($message)),
|
||||
sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected)
|
||||
);
|
||||
}
|
||||
|
||||
protected function assertHMACsTo($hash, $key, $message, $expected)
|
||||
{
|
||||
$hash = new Hash($hash);
|
||||
$hash->setKey($key);
|
||||
|
||||
$this->assertSame(
|
||||
strtolower($expected),
|
||||
bin2hex($hash->hash($message)),
|
||||
sprintf(
|
||||
"Failed asserting that '%s' HMACs to '%s' with key '%s'.",
|
||||
$message,
|
||||
$expected,
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function hashData()
|
||||
{
|
||||
return array(
|
||||
array('md5', '', 'd41d8cd98f00b204e9800998ecf8427e'),
|
||||
array('md5', 'The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'),
|
||||
array('md5', 'The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'),
|
||||
array('sha1', 'The quick brown fox jumps over the lazy dog', '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'),
|
||||
array('sha1', 'The quick brown fox jumps over the lazy dog.', '408d94384216f890ff7a0c3528e8bed1e0b01621'),
|
||||
array(
|
||||
'sha256',
|
||||
'',
|
||||
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
||||
),
|
||||
array(
|
||||
'sha256',
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592',
|
||||
),
|
||||
array(
|
||||
'sha256',
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c',
|
||||
),
|
||||
array(
|
||||
'sha384',
|
||||
'',
|
||||
'38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b'
|
||||
),
|
||||
array(
|
||||
'sha384',
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1',
|
||||
),
|
||||
array(
|
||||
'sha512',
|
||||
'',
|
||||
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'
|
||||
),
|
||||
array(
|
||||
'sha512',
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6',
|
||||
),
|
||||
array(
|
||||
'sha512',
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed',
|
||||
),
|
||||
array(
|
||||
'whirlpool',
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba'
|
||||
),
|
||||
array(
|
||||
'whirlpool',
|
||||
'The quick brown fox jumps over the lazy dog.',
|
||||
'87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC($hash, $key, $message, $result)
|
||||
{
|
||||
$this->assertHMACsTo($hash, $key, $message, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hmacData()
|
||||
*/
|
||||
public function testHMAC96($hash, $key, $message, $result)
|
||||
{
|
||||
$this->assertHMACsTo($hash . '-96', $key, $message, substr($result, 0, 24));
|
||||
}
|
||||
|
||||
public static function hmacData()
|
||||
{
|
||||
return array(
|
||||
array('md5', '', '', '74e6f7298a9c2d168935f58c001bad88'),
|
||||
array('md5', 'key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'),
|
||||
// RFC 4231
|
||||
// Test Case 1
|
||||
array(
|
||||
'sha256',
|
||||
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||
pack('H*', '4869205468657265'),
|
||||
'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7',
|
||||
),
|
||||
// Test Case 2
|
||||
array(
|
||||
'sha256',
|
||||
pack('H*', '4a656665'),
|
||||
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||
'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843',
|
||||
),
|
||||
// Test Case 3
|
||||
array(
|
||||
'sha256',
|
||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||
'773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe',
|
||||
),
|
||||
// Test Case 4
|
||||
array(
|
||||
'sha256',
|
||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||
'82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b',
|
||||
),
|
||||
// RFC 4231
|
||||
// Test Case 1
|
||||
array(
|
||||
'sha512',
|
||||
pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
|
||||
pack('H*', '4869205468657265'),
|
||||
'87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
|
||||
),
|
||||
// Test Case 2
|
||||
array(
|
||||
'sha512',
|
||||
pack('H*', '4a656665'),
|
||||
pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'),
|
||||
'164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
|
||||
),
|
||||
// Test Case 3
|
||||
array(
|
||||
'sha512',
|
||||
pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
||||
pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'),
|
||||
'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb',
|
||||
),
|
||||
// Test Case 4
|
||||
array(
|
||||
'sha512',
|
||||
pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'),
|
||||
pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'),
|
||||
'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd',
|
||||
),
|
||||
array(
|
||||
'whirlpool',
|
||||
'abcd',
|
||||
'The quick brown fox jumps over the lazy dog',
|
||||
'e71aabb2588d789292fa6fef00b35cc269ec3ea912b1c1cd7127daf95f004a5df5392ee563d322bac7e19d9eab161932fe9c257d63e0d09eca0d91ab4010125e',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash($hash, $message, $result)
|
||||
{
|
||||
$this->assertHashesTo($hash, $message, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hashData()
|
||||
*/
|
||||
public function testHash96($hash, $message, $result)
|
||||
{
|
||||
$this->assertHashesTo($hash . '-96', $message, substr($result, 0, 24));
|
||||
}
|
||||
|
||||
public function testConstructorDefault()
|
||||
{
|
||||
$hash = new Hash();
|
||||
$this->assertSame($hash->getHash(), 'sha256');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
|
||||
*/
|
||||
public function testConstructorArgumentInvalid()
|
||||
{
|
||||
new Hash('abcdefghijklmnopqrst');
|
||||
}
|
||||
|
||||
public function testConstructorArgumentValid()
|
||||
{
|
||||
$hash = new Hash('whirlpool');
|
||||
$this->assertSame($hash->getHash(), 'whirlpool');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \phpseclib\Exception\UnsupportedAlgorithmException
|
||||
*/
|
||||
public function testSetHashInvalid()
|
||||
{
|
||||
$hash = new Hash('md5');
|
||||
$hash->setHash('abcdefghijklmnopqrst-96');
|
||||
}
|
||||
|
||||
public function testSetHashValid()
|
||||
{
|
||||
$hash = new Hash('md5');
|
||||
$this->assertSame($hash->getHash(), 'md5');
|
||||
$hash->setHash('sha1');
|
||||
$this->assertSame($hash->getHash(), 'sha1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider lengths
|
||||
*/
|
||||
public function testGetLengthKnown($algorithm, $length)
|
||||
{
|
||||
$hash = new Hash($algorithm);
|
||||
$this->assertSame($hash->getLength(), $length);
|
||||
}
|
||||
|
||||
public function lengths()
|
||||
{
|
||||
return array(
|
||||
// known
|
||||
array('md5-96', 12),
|
||||
array('md5', 16),
|
||||
array('sha1', 20),
|
||||
array('sha256', 32),
|
||||
array('sha384', 48),
|
||||
array('sha512', 64),
|
||||
// unknown
|
||||
array('whirlpool', 64),
|
||||
);
|
||||
}
|
||||
}
|
@ -110,6 +110,18 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase
|
||||
$this->assertFalse($ssh->isQuietModeEnabled());
|
||||
}
|
||||
|
||||
public function testGetConnectionByResourceId()
|
||||
{
|
||||
$ssh = new \phpseclib\Net\SSH2('localhost');
|
||||
$this->assertSame($ssh, \phpseclib\Net\SSH2::getConnectionByResourceId($ssh->getResourceId()));
|
||||
}
|
||||
|
||||
public function testGetResourceId()
|
||||
{
|
||||
$ssh = new \phpseclib\Net\SSH2('localhost');
|
||||
$this->assertSame('{' . spl_object_hash($ssh) . '}', $ssh->getResourceId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \phpseclib\Net\SSH2
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user