diff --git a/phpseclib/Crypt/AES.php b/phpseclib/Crypt/AES.php index 40e78ede..8521eb5e 100644 --- a/phpseclib/Crypt/AES.php +++ b/phpseclib/Crypt/AES.php @@ -65,6 +65,7 @@ class AES extends Rijndael * * @see \phpseclib\Crypt\Rijndael::setBlockLength() * @access public + * @param int $length * @throws \BadMethodCallException anytime it's called */ function setBlockLength($length) @@ -90,7 +91,7 @@ class AES extends Rijndael case 256: break; default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); + throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported'); } parent::setKeyLength($length); } diff --git a/phpseclib/Crypt/Base.php b/phpseclib/Crypt/Base.php index 9ef68546..92a6f62b 100644 --- a/phpseclib/Crypt/Base.php +++ b/phpseclib/Crypt/Base.php @@ -793,7 +793,7 @@ abstract class Base $this->changed = false; } if ($this->enchanged) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV)); $this->enchanged = false; } @@ -856,7 +856,7 @@ abstract class Base $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); if (!$this->continuousBuffer) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV)); } return $ciphertext; @@ -1010,8 +1010,8 @@ abstract class Base */ function decrypt($ciphertext) { - if ($this->paddable) { - throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_length . ')'); + if ($this->paddable && strlen($ciphertext) % $this->block_size) { + throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')'); } if ($this->engine === self::ENGINE_OPENSSL) { @@ -1104,7 +1104,7 @@ abstract class Base $this->changed = false; } if ($this->dechanged) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); + mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV)); $this->dechanged = false; } @@ -1149,7 +1149,7 @@ abstract class Base $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); if (!$this->continuousBuffer) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); + mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV)); } return $this->paddable ? $this->_unpad($plaintext) : $plaintext; @@ -1286,6 +1286,22 @@ abstract class Base return $this->paddable ? $this->_unpad($plaintext) : $plaintext; } + /** + * Get the IV + * + * mcrypt requires an IV even if ECB is used + * + * @see self::encrypt() + * @see self::decrypt() + * @param string $iv + * @return string + * @access private + */ + function _getIV($iv) + { + return $this->mode == self::MODE_ECB ? str_repeat("\0", $this->block_size) : $iv; + } + /** * OpenSSL CTR Processor * diff --git a/phpseclib/Crypt/RC4.php b/phpseclib/Crypt/RC4.php index a2cb80ab..3da70b6e 100644 --- a/phpseclib/Crypt/RC4.php +++ b/phpseclib/Crypt/RC4.php @@ -209,7 +209,7 @@ class RC4 extends Base throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long'); } - parent::setKey($length); + parent::setKey($key); } /** diff --git a/phpseclib/Crypt/RSA/PKCS.php b/phpseclib/Crypt/RSA/PKCS.php index c019b52b..9d3e6425 100644 --- a/phpseclib/Crypt/RSA/PKCS.php +++ b/phpseclib/Crypt/RSA/PKCS.php @@ -264,7 +264,7 @@ abstract class PKCS return false; } - $crypto = new DES(); + $crypto = new DES(DES::MODE_CBC); $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); $key = $crypto->decrypt($key); if ($key === false) { diff --git a/phpseclib/Crypt/RSA/PKCS8.php b/phpseclib/Crypt/RSA/PKCS8.php index 9de3ca01..164fca19 100644 --- a/phpseclib/Crypt/RSA/PKCS8.php +++ b/phpseclib/Crypt/RSA/PKCS8.php @@ -107,7 +107,7 @@ class PKCS8 extends PKCS $salt = Random::string(8); $iterationCount = 2048; - $crypto = new DES(); + $crypto = new DES(DES::MODE_CBC); $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); diff --git a/phpseclib/Crypt/RSA/PuTTY.php b/phpseclib/Crypt/RSA/PuTTY.php index 71170110..302eb2b1 100644 --- a/phpseclib/Crypt/RSA/PuTTY.php +++ b/phpseclib/Crypt/RSA/PuTTY.php @@ -126,7 +126,7 @@ class PuTTY switch ($encryption) { case 'aes256-cbc': $symkey = static::generateSymmetricKey($password, 32); - $crypto = new AES(); + $crypto = new AES(AES::MODE_CBC); } if ($encryption != 'none') { diff --git a/phpseclib/Crypt/TripleDES.php b/phpseclib/Crypt/TripleDES.php index 3772cf3d..29c6eb9d 100644 --- a/phpseclib/Crypt/TripleDES.php +++ b/phpseclib/Crypt/TripleDES.php @@ -275,7 +275,7 @@ class TripleDES extends DES $this->changed = true; $this->_setEngine(); - if ($this->mode_3cbc && $length > 8) { + if ($this->mode_3cbc) { $this->des[0]->setKey(substr($key, 0, 8)); $this->des[1]->setKey(substr($key, 8, 8)); $this->des[2]->setKey(substr($key, 16, 8)); diff --git a/phpseclib/Net/SSH1.php b/phpseclib/Net/SSH1.php index 5379baaf..2a8c1d8d 100644 --- a/phpseclib/Net/SSH1.php +++ b/phpseclib/Net/SSH1.php @@ -662,6 +662,7 @@ class SSH1 $this->crypto->disablePadding(); $this->crypto->enableContinuousBuffer(); $this->crypto->setKey(substr($session_key, 0, 8)); + // "The iv (initialization vector) is initialized to all zeroes." $this->crypto->setIV(str_repeat("\0", 8)); break; case self::CIPHER_3DES: @@ -669,6 +670,7 @@ class SSH1 $this->crypto->disablePadding(); $this->crypto->enableContinuousBuffer(); $this->crypto->setKey(substr($session_key, 0, 24)); + // "All three initialization vectors are initialized to zero." $this->crypto->setIV(str_repeat("\0", 8)); break; //case self::CIPHER_RC4: diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index fe9d15b5..7111b860 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1815,26 +1815,26 @@ class SSH2 { switch ($algorithm) { case '3des-cbc': - return new TripleDES(); + return new TripleDES(Base::MODE_CBC); case '3des-ctr': return new TripleDES(Base::MODE_CTR); case 'aes256-cbc': case 'aes192-cbc': case 'aes128-cbc': - return new Rijndael(); + return new Rijndael(Base::MODE_CBC); case 'aes256-ctr': case 'aes192-ctr': case 'aes128-ctr': return new Rijndael(Base::MODE_CTR); case 'blowfish-cbc': - return new Blowfish(); + return new Blowfish(Base::MODE_CBC); case 'blowfish-ctr': return new Blowfish(Base::MODE_CTR); case 'twofish128-cbc': case 'twofish192-cbc': case 'twofish256-cbc': case 'twofish-cbc': - return new Twofish(); + return new Twofish(Base::MODE_CBC); case 'twofish128-ctr': case 'twofish192-ctr': case 'twofish256-ctr': diff --git a/tests/Unit/Crypt/AES/TestCase.php b/tests/Unit/Crypt/AES/TestCase.php index 0550b4e2..d89516ea 100644 --- a/tests/Unit/Crypt/AES/TestCase.php +++ b/tests/Unit/Crypt/AES/TestCase.php @@ -388,7 +388,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase */ public function testContinuousBuffer() { - $aes = new AES(); + $aes = new AES(AES::MODE_CBC); $aes->disablePadding(); $aes->enableContinuousBuffer(); $aes->setIV(pack('H*', '0457bdb4a6712986688349a29eb82535'));