mirror of
https://github.com/phpseclib/phpseclib.git
synced 2024-06-06 10:30:49 +00:00
Merge branch '2.0'
This commit is contained in:
commit
2d1becc950
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -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))
|
||||
|
|
|
@ -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/)
|
||||
|
||||
|
|
|
@ -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
2
composer.lock
generated
|
@ -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": [
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
BIN
phpseclib/phpseclib1.0.0.zip
Normal file
BIN
phpseclib/phpseclib1.0.0.zip
Normal file
Binary file not shown.
|
@ -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.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user