Merge remote-tracking branch 'upstream/master' into rsa-plugins

Conflicts:
	phpseclib/Crypt/RSA.php
	phpseclib/Net/SSH2.php
This commit is contained in:
terrafrost 2015-10-01 15:57:31 -05:00
commit 91887c957d
30 changed files with 755 additions and 1230 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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)) {

View File

@ -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);

View 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
{
}

View 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
{
}

View 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
{
}

View 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
{
}

View File

@ -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;
}

View File

@ -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');
}
/**

View File

@ -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');
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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);
*/

View File

@ -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;
}
}

View File

@ -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 = '';

View File

@ -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);

View File

@ -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(

View File

@ -13,6 +13,9 @@ use phpseclib\Net\SFTP;
*/
abstract class Functional_Net_SFTPTestCase extends PhpseclibFunctionalTestCase
{
/**
* @var SFTP
*/
protected $sftp;
protected $scratchDir;

View File

@ -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.'
);
}
}

View 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();
}

View File

@ -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'),
);
}
}

View File

@ -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',
),
);
}
}

View File

@ -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));
}
}

View File

@ -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',
),
);
}
}

View File

@ -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));
}
}

View File

@ -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
)
);
}
}

View 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),
);
}
}

View File

@ -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
*/