Merge branch '2.0'

This commit is contained in:
terrafrost 2015-08-03 23:23:49 -05:00
commit 2d1becc950
8 changed files with 308 additions and 303 deletions

View File

@ -1,5 +1,21 @@
# Changelog
## 1.0.0 - 2015-08-02
- OpenSSL support for symmetric ciphers ([#507](https://github.com/phpseclib/phpseclib/pull/507))
- rewritten vt100 terminal emulator (File_ANSI) ([#689](https://github.com/phpseclib/phpseclib/pull/689))
- agent-forwarding support (System_SSH_Agent) ([#592](https://github.com/phpseclib/phpseclib/pull/592))
- Net_SSH2 improvements
- diffie-hellman-group-exchange-sha1/sha256 support ([#714](https://github.com/phpseclib/phpseclib/pull/714))
- window size handling updates ([#717](https://github.com/phpseclib/phpseclib/pull/717))
- Net_SFTP improvements
- add callback support to put() ([#655](https://github.com/phpseclib/phpseclib/pull/655))
- stat cache fixes ([#743](https://github.com/phpseclib/phpseclib/issues/743), [#730](https://github.com/phpseclib/phpseclib/issues/730), [#709](https://github.com/phpseclib/phpseclib/issues/709), [#726](https://github.com/phpseclib/phpseclib/issues/726))
- add "none" encryption mode to Crypt_RSA ([#692](https://github.com/phpseclib/phpseclib/pull/692))
- misc ASN.1 / X.509 parsing fixes ([#721](https://github.com/phpseclib/phpseclib/pull/721), [#627](https://github.com/phpseclib/phpseclib/pull/627))
- use a random serial number for new X509 certs ([#740](https://github.com/phpseclib/phpseclib/pull/740))
- add getPublicKeyFingerprint() to Crypt_RSA ([#677](https://github.com/phpseclib/phpseclib/pull/677))
## 0.3.10 - 2015-02-04
- simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538))

View File

@ -6,7 +6,7 @@ MIT-licensed pure-PHP implementations of an arbitrary-precision integer
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* [Download (0.3.10)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.10.zip/download)
* [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/php5/latest/)

View File

@ -1,4 +1,4 @@
{
{
"name": "phpseclib/phpseclib",
"type": "library",
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
@ -55,8 +55,11 @@
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.",
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 5.0.0."
},
"include-path": ["phpseclib/"],
"autoload": {

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "a8adabfa04c250bbec41c87f79a59b31",
"hash": "b24ab20be15b6312e532ee2ffa18d5fa",
"packages": [],
"packages-dev": [
{

View File

@ -869,7 +869,9 @@ class SSH2
/**
* Default Constructor.
*
* @param String $host
* $host can either be a string, representing the host, or a stream resource.
*
* @param Mixed $host
* @param optional Integer $port
* @param optional Integer $timeout
* @see \phpseclib\Net\SSH2::login()
@ -951,12 +953,22 @@ class SSH2
31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP',
32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT',
33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY',
34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST')
34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'),
// RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
array(30 => 'NET_SSH2_MSG_KEX_ECDH_INIT',
31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY')
);
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
if (is_resource($host)) {
$this->fsock = $host;
return;
}
if (is_string($host)) {
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
}
}
/**
@ -989,23 +1001,24 @@ class SSH2
$this->curTimeout = $this->timeout;
$host = $this->host . ':' . $this->port;
$this->last_packet = microtime(true);
$start = microtime(true);
$this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
if (!$this->fsock) {
user_error(rtrim("Cannot connect to $host. Error $errno. $errstr"));
return false;
}
$elapsed = microtime(true) - $start;
if (!is_resource($this->fsock)) {
$start = microtime(true);
$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;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
$this->curTimeout-= $elapsed;
if ($this->curTimeout <= 0) {
$this->is_timeout = true;
return false;
if ($this->curTimeout <= 0) {
$this->is_timeout = true;
return false;
}
}
/* According to the SSH2 specs,
@ -1100,9 +1113,13 @@ class SSH2
*/
function _generate_identifier()
{
$identifier = 'SSH-2.0-phpseclib_0.3';
$identifier = 'SSH-2.0-phpseclib_2.0';
$ext = array();
if (extension_loaded('libsodium')) {
$ext[] = 'libsodium';
}
if (extension_loaded('openssl')) {
$ext[] = 'openssl';
} elseif (extension_loaded('mcrypt')) {
@ -1131,11 +1148,24 @@ class SSH2
function _key_exchange($kexinit_payload_server)
{
static $kex_algorithms = array(
// Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
// Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
// libssh repository for more information.
'curve25519-sha256@libssh.org',
// Diffie-Hellman Key Agreement (DH) using integer modulo prime
// groups.
'diffie-hellman-group1-sha1', // REQUIRED
'diffie-hellman-group14-sha1', // REQUIRED
'diffie-hellman-group-exchange-sha1', // RFC 4419
'diffie-hellman-group-exchange-sha256', // RFC 4419
);
if (!class_exists('\Sodium')) {
$kex_algorithms = array_diff(
$kex_algorithms,
array('curve25519-sha256@libssh.org')
);
}
static $server_host_key_algorithms = array(
'ssh-rsa', // RECOMMENDED sign Raw RSA Key
@ -1336,198 +1366,137 @@ class SSH2
// 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);
switch ($decrypt) {
case '3des-cbc':
case '3des-ctr':
$decryptKeyLength = 24; // eg. 192 / 8
break;
case 'aes256-cbc':
case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$decryptKeyLength = 32; // eg. 256 / 8
break;
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$decryptKeyLength = 24; // eg. 192 / 8
break;
case 'aes128-cbc':
case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
case 'blowfish-cbc':
case 'blowfish-ctr':
$decryptKeyLength = 16; // eg. 128 / 8
break;
case 'arcfour':
case 'arcfour128':
$decryptKeyLength = 16; // eg. 128 / 8
break;
case 'arcfour256':
$decryptKeyLength = 32; // eg. 128 / 8
break;
case 'none':
$decryptKeyLength = 0;
break;
default:
user_error('No compatible server to client encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
$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);
}
$encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server);
switch ($encrypt) {
case '3des-cbc':
case '3des-ctr':
$encryptKeyLength = 24;
break;
case 'aes256-cbc':
case 'aes256-ctr':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
$encryptKeyLength = 32;
break;
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
$encryptKeyLength = 24;
break;
case 'aes128-cbc':
case 'aes128-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
case 'blowfish-cbc':
case 'blowfish-ctr':
$encryptKeyLength = 16;
break;
case 'arcfour':
case 'arcfour128':
$encryptKeyLength = 16;
break;
case 'arcfour256':
$encryptKeyLength = 32;
break;
case 'none':
$encryptKeyLength = 0;
break;
default:
user_error('No compatible client to server encryption algorithms found');
return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
$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);
}
$keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
// 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);
}
if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
$dh_group_sizes_packed = pack(
'NNN',
$this->kex_dh_group_size_min,
$this->kex_dh_group_size_preferred,
$this->kex_dh_group_size_max
);
$packet = pack(
'Ca*',
NET_SSH2_MSG_KEXDH_GEX_REQUEST,
$dh_group_sizes_packed
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
return false;
}
// Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
$exchange_hash_rfc4419 = '';
extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
$primeBytes = $this->_string_shift($response, $primeLength);
$prime = new BigInteger($primeBytes, -256);
extract(unpack('NgLength', $this->_string_shift($response, 4)));
$gBytes = $this->_string_shift($response, $gLength);
$g = new BigInteger($gBytes, -256);
$exchange_hash_rfc4419 = pack(
'a*Na*Na*',
$dh_group_sizes_packed,
$primeLength,
$primeBytes,
$gLength,
$gBytes
);
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
$x = Random::string(32);
$eBytes = \Sodium::crypto_box_publickey_from_secretkey($x);
$clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY;
$kexHash = new Hash('sha256');
} else {
switch ($kex_algorithm) {
// see http://tools.ietf.org/html/rfc2409#section-6.2 and
// http://tools.ietf.org/html/rfc2412, appendex E
case 'diffie-hellman-group1-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
break;
// see http://tools.ietf.org/html/rfc3526#section-3
case 'diffie-hellman-group14-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
'98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
'9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
'3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
break;
if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
$dh_group_sizes_packed = pack(
'NNN',
$this->kex_dh_group_size_min,
$this->kex_dh_group_size_preferred,
$this->kex_dh_group_size_max
);
$packet = pack(
'Ca*',
NET_SSH2_MSG_KEXDH_GEX_REQUEST,
$dh_group_sizes_packed
);
if (!$this->_send_binary_packet($packet)) {
return false;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
extract(unpack('Ctype', $this->_string_shift($response, 1)));
if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP');
return false;
}
extract(unpack('NprimeLength', $this->_string_shift($response, 4)));
$primeBytes = $this->_string_shift($response, $primeLength);
$prime = new BigInteger($primeBytes, -256);
extract(unpack('NgLength', $this->_string_shift($response, 4)));
$gBytes = $this->_string_shift($response, $gLength);
$g = new BigInteger($gBytes, -256);
$exchange_hash_rfc4419 = pack(
'a*Na*Na*',
$dh_group_sizes_packed,
$primeLength,
$primeBytes,
$gLength,
$gBytes
);
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY;
} else {
switch ($kex_algorithm) {
// see http://tools.ietf.org/html/rfc2409#section-6.2 and
// http://tools.ietf.org/html/rfc2412, appendex E
case 'diffie-hellman-group1-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
break;
// see http://tools.ietf.org/html/rfc3526#section-3
case 'diffie-hellman-group14-sha1':
$prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' .
'020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' .
'4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' .
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' .
'98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' .
'9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' .
'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' .
'3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
break;
}
// For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
// the generator field element is 2 (decimal) and the hash function is sha1.
$g = new BigInteger(2);
$prime = new BigInteger($prime, 16);
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
}
// For both diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1
// the generator field element is 2 (decimal) and the hash function is sha1.
$g = new BigInteger(2);
$prime = new BigInteger($prime, 16);
$exchange_hash_rfc4419 = '';
$clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT;
$serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY;
switch ($kex_algorithm) {
case 'diffie-hellman-group-exchange-sha256':
$kexHash = new Hash('sha256');
break;
default:
$kexHash = new Hash('sha1');
}
/* To increase the speed of the key exchange, both client and server may
reduce the size of their private exponents. It should be at least
twice as long as the key material that is generated from the shared
secret. For more details, see the paper by van Oorschot and Wiener
[VAN-OORSCHOT].
-- http://tools.ietf.org/html/rfc4419#section-6.2 */
$one = new BigInteger(1);
$keyLength = min($kexHash->getLength(), max($encryptKeyLength, $decryptKeyLength));
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
$max = $max->subtract($one);
$x = $one->random($one, $max);
$e = $g->modPow($x, $prime);
$eBytes = $e->toBytes(true);
}
switch ($kex_algorithm) {
case 'diffie-hellman-group-exchange-sha256':
$kexHash = new Hash('sha256');
break;
default:
$kexHash = new Hash('sha1');
}
/* To increase the speed of the key exchange, both client and server may
reduce the size of their private exponents. It should be at least
twice as long as the key material that is generated from the shared
secret. For more details, see the paper by van Oorschot and Wiener
[VAN-OORSCHOT].
-- http://tools.ietf.org/html/rfc4419#section-6.2 */
$one = new BigInteger(1);
$keyLength = min($keyLength, $kexHash->getLength());
$max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength
$max = $max->subtract($one);
$x = $one->random($one, $max);
$e = $g->modPow($x, $prime);
$eBytes = $e->toBytes(true);
$data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes);
if (!$this->_send_binary_packet($data)) {
@ -1555,7 +1524,6 @@ class SSH2
$temp = unpack('Nlength', $this->_string_shift($response, 4));
$fBytes = $this->_string_shift($response, $temp['length']);
$f = new BigInteger($fBytes, -256);
$temp = unpack('Nlength', $this->_string_shift($response, 4));
$this->signature = $this->_string_shift($response, $temp['length']);
@ -1563,7 +1531,17 @@ class SSH2
$temp = unpack('Nlength', $this->_string_shift($this->signature, 4));
$this->signature_format = $this->_string_shift($this->signature, $temp['length']);
$key = $f->modPow($x, $prime);
if ($kex_algorithm === 'curve25519-sha256@libssh.org') {
if (strlen($fBytes) !== 32) {
user_error('Received curve25519 public key of invalid length.');
return false;
}
$key = new BigInteger(\Sodium::crypto_scalarmult($x, $fBytes), 256);
\Sodium::sodium_memzero($x);
} else {
$f = new BigInteger($fBytes, -256);
$key = $f->modPow($x, $prime);
}
$keyBytes = $key->toBytes(true);
$this->exchange_hash = pack(
@ -1627,112 +1605,16 @@ class SSH2
return false;
}
switch ($encrypt) {
case '3des-cbc':
$this->encrypt = new TripleDES();
// $this->encrypt_block_size = 64 / 8 == the default
break;
case '3des-ctr':
$this->encrypt = new TripleDES(Base::MODE_CTR);
// $this->encrypt_block_size = 64 / 8 == the default
break;
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
$this->encrypt = new Rijndael();
$this->encrypt_block_size = 16; // eg. 128 / 8
break;
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
$this->encrypt = new Rijndael(Base::MODE_CTR);
$this->encrypt_block_size = 16; // eg. 128 / 8
break;
case 'blowfish-cbc':
$this->encrypt = new Blowfish();
$this->encrypt_block_size = 8;
break;
case 'blowfish-ctr':
$this->encrypt = new Blowfish(Base::MODE_CTR);
$this->encrypt_block_size = 8;
break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
$this->encrypt = new Twofish();
$this->encrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
$this->encrypt = new Twofish(Base::MODE_CTR);
$this->encrypt_block_size = 16;
break;
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
$this->encrypt = new RC4();
break;
case 'none':
//$this->encrypt = new Null();
}
switch ($decrypt) {
case '3des-cbc':
$this->decrypt = new TripleDES();
break;
case '3des-ctr':
$this->decrypt = new TripleDES(Base::MODE_CTR);
break;
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
$this->decrypt = new Rijndael();
$this->decrypt_block_size = 16;
break;
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
$this->decrypt = new Rijndael(Base::MODE_CTR);
$this->decrypt_block_size = 16;
break;
case 'blowfish-cbc':
$this->decrypt = new Blowfish();
$this->decrypt_block_size = 8;
break;
case 'blowfish-ctr':
$this->decrypt = new Blowfish(Base::MODE_CTR);
$this->decrypt_block_size = 8;
break;
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
$this->decrypt = new Twofish();
$this->decrypt_block_size = 16;
break;
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
$this->decrypt = new Twofish(Base::MODE_CTR);
$this->decrypt_block_size = 16;
break;
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
$this->decrypt = new RC4();
break;
case 'none':
//$this->decrypt = new Null();
}
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
$this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
if ($this->encrypt) {
if ($this->crypto_engine) {
$this->encrypt->setEngine($this->crypto_engine);
}
if ($this->encrypt->block_size) {
$this->encrypt_block_size = $this->encrypt->block_size;
}
$this->encrypt->enableContinuousBuffer();
$this->encrypt->disablePadding();
@ -1749,10 +1631,14 @@ class SSH2
$this->encrypt->setKey(substr($key, 0, $encryptKeyLength));
}
$this->decrypt = $this->_encryption_algorithm_to_crypt_instance($decrypt);
if ($this->decrypt) {
if ($this->crypto_engine) {
$this->decrypt->setEngine($this->crypto_engine);
}
if ($this->decrypt->block_size) {
$this->decrypt_block_size = $this->decrypt->block_size;
}
$this->decrypt->enableContinuousBuffer();
$this->decrypt->disablePadding();
@ -1876,6 +1762,89 @@ class SSH2
return true;
}
/**
* Maps an encryption algorithm name to the number of key bytes.
*
* @param String $algorithm Name of the encryption algorithm
* @return Mixed Number of bytes as an integer or null for unknown
* @access private
*/
function _encryption_algorithm_to_key_size($algorithm)
{
switch ($algorithm) {
case 'none':
return 0;
case 'aes128-cbc':
case 'aes128-ctr':
case 'arcfour':
case 'arcfour128':
case 'blowfish-cbc':
case 'blowfish-ctr':
case 'twofish128-cbc':
case 'twofish128-ctr':
return 16;
case '3des-cbc':
case '3des-ctr':
case 'aes192-cbc':
case 'aes192-ctr':
case 'twofish192-cbc':
case 'twofish192-ctr':
return 24;
case 'aes256-cbc':
case 'aes256-ctr':
case 'arcfour256':
case 'twofish-cbc':
case 'twofish256-cbc':
case 'twofish256-ctr':
return 32;
}
return null;
}
/**
* Maps an encryption algorithm name to an instance of a subclass of
* \phpseclib\Crypt\Base.
*
* @param String $algorithm Name of the encryption algorithm
* @return Mixed Instance of \phpseclib\Crypt\Base or null for unknown
* @access private
*/
function _encryption_algorithm_to_crypt_instance($algorithm)
{
switch ($algorithm) {
case '3des-cbc':
return new TripleDES();
case '3des-ctr':
return new TripleDES(Base::MODE_CTR);
case 'aes256-cbc':
case 'aes192-cbc':
case 'aes128-cbc':
return new Rijndael();
case 'aes256-ctr':
case 'aes192-ctr':
case 'aes128-ctr':
return new Rijndael(Base::MODE_CTR);
case 'blowfish-cbc':
return new Blowfish();
case 'blowfish-ctr':
return new Blowfish(Base::MODE_CTR);
case 'twofish128-cbc':
case 'twofish192-cbc':
case 'twofish256-cbc':
case 'twofish-cbc':
return new Twofish();
case 'twofish128-ctr':
case 'twofish192-ctr':
case 'twofish256-ctr':
return new Twofish(Base::MODE_CTR);
case 'arcfour':
case 'arcfour128':
case 'arcfour256':
return new RC4();
}
return null;
}
/**
* Login
*

Binary file not shown.

View File

@ -87,4 +87,17 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
$this->assertInternalType('string', $ssh->getServerPublicHostKey());
}
public function testOpenSocketConnect()
{
$fsock = fsockopen($this->getEnv('SSH_HOSTNAME'), 22);
$ssh = new SSH2($fsock);
$username = $this->getEnv('SSH_USERNAME');
$password = $this->getEnv('SSH_PASSWORD');
$this->assertTrue(
$ssh->login($username, $password),
'SSH2 login using an open socket failed.'
);
}
}

View File

@ -39,7 +39,11 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase
public function testGenerateIdentifier()
{
$identifier = $this->createSSHMock()->_generate_identifier();
$this->assertStringStartsWith('SSH-2.0-phpseclib_0.3', $identifier);
$this->assertStringStartsWith('SSH-2.0-phpseclib_2.0', $identifier);
if (extension_loaded('libsodium')) {
$this->assertContains('libsodium', $identifier);
}
if (extension_loaded('openssl')) {
$this->assertContains('openssl', $identifier);