diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f2273a..ff05fccc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 2.0.7 - 2017-10-22 + +- SSH2: + - add new READ_NEXT mode (#1140) + - add sendIdentificationStringFirst() + - add sendKEXINITFirst() + - add sendIdentificationStringLast() + - add sendKEXINITLast() (#1162) + - assume any SSH server >= 1.99 supports SSH2 (#1170) + - workaround for bad arcfour256 implementations (#1171) + - don't choke when getting response from diff channel in exec() (#1167) +- SFTP: + - add enablePathCanonicalization() + - add disablePathCanonicalization() (#1137) + - fix put() with remote file stream resource (#1177) +- ANSI: misc fixes (#1150, #1161) +- X509: use DateTime instead of unix time (#1166) +- Ciphers: use eval() instead of create_function() for >= 5.3 + ## 2.0.6 - 2017-06-05 - Crypt: fix OpenSSL engine on <= PHP 5.3.6 (#1122) @@ -67,6 +86,25 @@ - Classes were renamed and namespaced ([#243](https://github.com/phpseclib/phpseclib/issues/243)) - The use of an autoloader is now required (e.g. Composer) +## 1.0.8 - 2017-10-22 + +- SSH2: + - add new READ_NEXT mode (#1140) + - add sendIdentificationStringFirst() + - add sendKEXINITFirst() + - add sendIdentificationStringLast() + - add sendKEXINITLast() (#1162) + - assume any SSH server >= 1.99 supports SSH2 (#1170) + - workaround for bad arcfour256 implementations (#1171) + - don't choke when getting response from diff channel in exec() (#1167) +- SFTP: + - add enablePathCanonicalization() + - add disablePathCanonicalization() (#1137) + - fix put() with remote file stream resource (#1177) +- ANSI: misc fixes (#1150, #1161) +- X509: use DateTime instead of unix time (#1166) +- Ciphers: use eval() instead of create_function() for >= 5.3 + ## 1.0.7 - 2017-06-05 - Crypt: fix OpenSSL engine on <= PHP 5.3.6 (#1122) @@ -139,11 +177,11 @@ - 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)) + - 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 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)) @@ -188,21 +226,21 @@ ## 0.3.5 - 2013-07-11 - numerous SFTP changes: - - chown - - chgrp - - truncate - - improved file type detection - - put() can write to te middle of a file - - mkdir accepts the same parameters that PHP's mkdir does - - the ability to upload/download 2GB files + - chown + - chgrp + - truncate + - improved file type detection + - put() can write to the middle of a file + - mkdir accepts the same parameters that PHP's mkdir does + - the ability to upload/download 2GB files - across-the-board speedups for the various encryption algorithms - multi-factor authentication support for Net_SSH2 - a $callback parameter for Net_SSH2::exec - new classes: - - Net_SFTP_StreamWrapper - - Net_SCP - - Crypt_Twofish - - Crypt_Blowfish + - Net_SFTP_StreamWrapper + - Net_SCP + - Crypt_Twofish + - Crypt_Blowfish ## 0.3.1 - 2012-11-20 @@ -232,7 +270,7 @@ - Net_SSH2 now has limited keyboard_interactive authentication support - support was added for PuTTY formatted RSA private keys and XML formatted RSA private keys - Crypt_RSA::loadKey() will now try all key types automatically -= add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys +- add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys - add Net_SFTP::stat(), Net_SFTP::lstat() and Net_SFTP::rawlist() - logging was added to Net_SSH1 - the license was changed to the less restrictive MIT license diff --git a/README.md b/README.md index ba4cedff..15f55f06 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509 * Composer compatible (PSR-0 autoloading) * Install using Composer: `composer require phpseclib/phpseclib ~1.0` * Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm) -* [Download 1.0.7 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.7.zip/download) +* [Download 1.0.8 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.8.zip/download) ## Support diff --git a/phpseclib/Crypt/Common/SymmetricKey.php b/phpseclib/Crypt/Common/SymmetricKey.php index 888a7e9b..d6b22eeb 100644 --- a/phpseclib/Crypt/Common/SymmetricKey.php +++ b/phpseclib/Crypt/Common/SymmetricKey.php @@ -80,6 +80,10 @@ abstract class SymmetricKey * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 */ const MODE_CFB = 3; + /** + * Encrypt / decrypt using the Cipher Feedback mode (8bit) + */ + const MODE_CFB8 = 38; /** * Encrypt / decrypt using the Output Feedback mode. * @@ -99,11 +103,12 @@ abstract class SymmetricKey * @see \phpseclib\Crypt\Common\SymmetricKey::__construct() */ const MODE_MAP = [ - 'ctr' => self::MODE_CTR, - 'ecb' => self::MODE_ECB, - 'cbc' => self::MODE_CBC, - 'cfb' => self::MODE_CFB, - 'ofb' => self::MODE_OFB, + 'ctr' => self::MODE_CTR, + 'ecb' => self::MODE_ECB, + 'cbc' => self::MODE_CBC, + 'cfb' => self::MODE_CFB, + 'cfb8' => self::MODE_CFB8, + 'ofb' => self::MODE_OFB, 'stream' => self::MODE_STREAM ]; @@ -481,7 +486,7 @@ abstract class SymmetricKey * * - ofb * - * @param int $mode + * @param string $mode * @access public * @throws \InvalidArgumentException if an invalid / unsupported mode is provided */ @@ -504,6 +509,7 @@ abstract class SymmetricKey break; case self::MODE_CTR: case self::MODE_CFB: + case self::MODE_CFB8: case self::MODE_OFB: case self::MODE_STREAM: $this->paddable = false; @@ -925,6 +931,16 @@ abstract class SymmetricKey $iv = substr($ciphertext, -$this->block_size); } + return $ciphertext; + case self::MODE_CFB8: + $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV); + if ($this->continuousBuffer) { + if (($len = strlen($ciphertext)) >= $this->block_size) { + $this->encryptIV = substr($ciphertext, -$this->block_size); + } else { + $this->encryptIV = substr($this->encryptIV, $len - $this->block_size) . substr($ciphertext, -$len); + } + } return $ciphertext; case self::MODE_OFB: return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); @@ -1105,6 +1121,24 @@ abstract class SymmetricKey $pos = $len; } break; + case self::MODE_CFB8: + $ciphertext = ''; + $len = strlen($plaintext); + $iv = $this->encryptIV; + + for ($i = 0; $i < $len; ++$i) { + $ciphertext .= ($c = $plaintext[$i] ^ $this->encryptBlock($iv)); + $iv = substr($iv, 1) . $c; + } + + if ($this->continuousBuffer) { + if ($len >= $block_size) { + $this->encryptIV = substr($ciphertext, -$block_size); + } else { + $this->encryptIV = substr($this->encryptIV, $len - $block_size) . substr($ciphertext, -$len); + } + } + break; case self::MODE_OFB: $xor = $this->encryptIV; if (strlen($buffer['xor'])) { @@ -1225,6 +1259,16 @@ abstract class SymmetricKey $iv = substr($ciphertext, -$this->block_size); } break; + case self::MODE_CFB8: + $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV); + if ($this->continuousBuffer) { + if (($len = strlen($ciphertext)) >= $this->block_size) { + $this->decryptIV = substr($ciphertext, -$this->block_size); + } else { + $this->decryptIV = substr($this->decryptIV, $len - $this->block_size) . substr($ciphertext, -$len); + } + } + break; case self::MODE_OFB: $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); } @@ -1388,6 +1432,24 @@ abstract class SymmetricKey $pos = $len; } break; + case self::MODE_CFB8: + $plaintext = ''; + $len = strlen($ciphertext); + $iv = $this->decryptIV; + + for ($i = 0; $i < $len; ++$i) { + $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv); + $iv = substr($iv, 1) . $ciphertext[$i]; + } + + if ($this->continuousBuffer) { + if ($len >= $block_size) { + $this->decryptIV = substr($ciphertext, -$block_size); + } else { + $this->decryptIV = substr($this->decryptIV, $len - $block_size) . substr($ciphertext, -$len); + } + } + break; case self::MODE_OFB: $xor = $this->decryptIV; if (strlen($buffer['xor'])) { @@ -1598,6 +1660,8 @@ abstract class SymmetricKey return 'ctr'; case self::MODE_CFB: return 'cfb'; + case self::MODE_CFB8: + return 'cfb8'; case self::MODE_OFB: return 'ofb'; } @@ -1795,7 +1859,7 @@ abstract class SymmetricKey * If the preferred crypt engine is not available the fastest available one will be used * * @see self::__construct() - * @param int $engine + * @param string $engine * @access public */ public function setPreferredEngine($engine) @@ -1967,6 +2031,7 @@ abstract class SymmetricKey self::MODE_ECB => MCRYPT_MODE_ECB, self::MODE_CBC => MCRYPT_MODE_CBC, self::MODE_CFB => 'ncfb', + self::MODE_CFB8 => MCRYPT_MODE_CFB, self::MODE_OFB => MCRYPT_MODE_NOFB, self::MODE_STREAM => MCRYPT_MODE_STREAM, ]; @@ -2493,6 +2558,52 @@ abstract class SymmetricKey $_pos = $_len; } + return $_plaintext; + '; + break; + case self::MODE_CFB8: + $encrypt = $init_encrypt . ' + $_ciphertext = ""; + $_len = strlen($_text); + $_iv = $this->encryptIV; + + for ($_i = 0; $_i < $_len; ++$_i) { + $in = $_iv; + '.$encrypt_block.' + $_ciphertext .= ($_c = $_text[$_i] ^ $in); + $_iv = substr($_iv, 1) . $_c; + } + + if ($this->continuousBuffer) { + if ($_len >= '.$block_size.') { + $this->encryptIV = substr($_ciphertext, -'.$block_size.'); + } else { + $this->encryptIV = substr($this->encryptIV, $_len - '.$block_size.') . substr($_ciphertext, -$_len); + } + } + + return $_ciphertext; + '; + $decrypt = $init_encrypt . ' + $_plaintext = ""; + $_len = strlen($_text); + $_iv = $this->decryptIV; + + for ($_i = 0; $_i < $_len; ++$_i) { + $in = $_iv; + '.$encrypt_block.' + $_plaintext .= $_text[$_i] ^ $in; + $_iv = substr($_iv, 1) . $_text[$_i]; + } + + if ($this->continuousBuffer) { + if ($_len >= '.$block_size.') { + $this->decryptIV = substr($_text, -'.$block_size.'); + } else { + $this->decryptIV = substr($this->decryptIV, $_len - '.$block_size.') . substr($_text, -$_len); + } + } + return $_plaintext; '; break; diff --git a/tests/Unit/Crypt/AES/TestCase.php b/tests/Unit/Crypt/AES/TestCase.php index ceef6a41..09458fd3 100644 --- a/tests/Unit/Crypt/AES/TestCase.php +++ b/tests/Unit/Crypt/AES/TestCase.php @@ -31,6 +31,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase 'ctr', 'ofb', 'cfb', + 'cfb8' ); $plaintexts = array( '', @@ -131,6 +132,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase 'ctr', 'ofb', 'cfb', + 'cfb8', ); $combos = array(