Merge branch 'getkeylength' into getkeylength-2.0-2

Conflicts:
	phpseclib/Crypt/Blowfish.php
	phpseclib/Crypt/DES.php
	phpseclib/Crypt/RC2.php
	phpseclib/Crypt/RC4.php
	phpseclib/Crypt/Rijndael.php
	phpseclib/Crypt/TripleDES.php
	phpseclib/Crypt/Twofish.php
This commit is contained in:
terrafrost 2015-09-22 21:26:00 -05:00
commit 604dddc82b
9 changed files with 225 additions and 187 deletions

View File

@ -440,6 +440,24 @@ abstract class Base
*/ */
var $openssl_options; var $openssl_options;
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see setKeyLength()
* @var bool
* @access private
*/
var $explicit_key_length = false;
/**
* Don't truncate / null pad key
*
* @see Crypt_Base::_clearBuffers
* @var bool
* @access private
*/
var $skip_key_adjustment = false;
/** /**
* Default Constructor. * Default Constructor.
* *
@ -512,6 +530,32 @@ abstract class Base
$this->changed = true; $this->changed = true;
} }
/**
* Sets the key length.
*
* Keys with explicitly set lengths need to be treated accordingly
*
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$this->explicit_key_length = true;
$this->changed = true;
$this->_setEngine();
}
/**
* Returns the current key length
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->key_size << 3;
}
/** /**
* Sets the key. * Sets the key.
* *
@ -528,6 +572,11 @@ abstract class Base
*/ */
function setKey($key) function setKey($key)
{ {
if (!$this->explicit_key_length) {
$this->setKeyLength(strlen($key) << 3);
$this->explicit_key_length = false;
}
$this->key = $key; $this->key = $key;
$this->changed = true; $this->changed = true;
$this->_setEngine(); $this->_setEngine();
@ -571,7 +620,7 @@ abstract class Base
if (isset($func_args[5])) { if (isset($func_args[5])) {
$dkLen = $func_args[5]; $dkLen = $func_args[5];
} else { } else {
$dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size; $dkLen = $method == 'pbkdf1' ? 2 * $this->key_size : $this->key_size;
} }
switch (true) { switch (true) {
@ -1831,6 +1880,10 @@ abstract class Base
// mcrypt's handling of invalid's $iv: // mcrypt's handling of invalid's $iv:
// $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size); // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
$this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0"); $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
if (!$this->skip_key_adjustment) {
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
}
} }
/** /**

View File

@ -58,16 +58,6 @@ class Blowfish extends Base
*/ */
var $block_size = 8; var $block_size = 8;
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var int
* @access private
*/
var $password_key_size = 56;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
@ -283,37 +273,43 @@ class Blowfish extends Base
var $kl; var $kl;
/** /**
* Sets the key. * The Key Length
* *
* Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long. * @see setKeyLength()
* If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible * @var int
* with mcrypt because mcrypt act this way with blowfish key's < 32 bits. * @access private
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
* because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
* derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
* of that, we'll just precompute it once.
*/
var $key_size = 16;
/**
* Sets the key length.
* *
* If the key is more than 448-bits, we trim the excess bits. * Key lengths can be between 32 and 448 bits.
*
* If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes.
* *
* @access public * @access public
* @see \phpseclib\Crypt\Base::setKey() * @param int $length
* @param string $key
*/ */
function setKey($key) function setKeyLength($length)
{ {
$keylength = strlen($key); if ($length < 32) {
$this->key_size = 7;
if (!$keylength) { } elseif ($length > 448) {
$key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; $this->key_size = 56;
} elseif ($keylength > 56) { } else {
$key = substr($key, 0, 56); $this->key_size = $length >> 3;
} }
parent::setKey($key); parent::setKeyLength($length);
} }
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::isValidEngine() * @see \phpseclib\Crypt\Base::isValidEngine()
* @param int $engine * @param int $engine
@ -323,7 +319,7 @@ class Blowfish extends Base
function isValidEngine($engine) function isValidEngine($engine)
{ {
if ($engine == self::ENGINE_OPENSSL) { if ($engine == self::ENGINE_OPENSSL) {
if (strlen($this->key) != 16) { if ($this->key_size != 16) {
return false; return false;
} }
$this->cipher_name_openssl_ecb = 'bf-ecb'; $this->cipher_name_openssl_ecb = 'bf-ecb';

View File

@ -78,24 +78,13 @@ class DES extends Base
var $block_size = 8; var $block_size = 8;
/** /**
* The Key * Key Length
* *
* @see \phpseclib\Crypt\Base::key * @see \phpseclib\Crypt\Base::setKeyLength()
* @see setKey()
* @var string
* @access private
*/
var $key = "\0\0\0\0\0\0\0\0";
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var int * @var int
* @access private * @access private
*/ */
var $password_key_size = 8; var $key_size = 8;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
@ -594,7 +583,7 @@ class DES extends Base
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::isValidEngine() * @see \phpseclib\Crypt\Base::isValidEngine()
* @param int $engine * @param int $engine

View File

@ -77,14 +77,22 @@ class RC2 extends Base
var $orig_key; var $orig_key;
/** /**
* The default password key_size used by setPassword() * Don't truncate / null pad key
* *
* @see \phpseclib\Crypt\Base::password_key_size * @see \phpseclib\Crypt\Base::_clearBuffers
* @see \phpseclib\Crypt\Base::setPassword() * @var bool
* @access private
*/
var $skip_key_adjustment = true;
/**
* Key Length
*
* @see \phpseclib\Crypt\RC2::setKeyLength()
* @var int * @var int
* @access private * @access private
*/ */
var $password_key_size = 16; // = 128 bits var $key_size = 16; // = 128 bits
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
@ -256,9 +264,9 @@ class RC2 extends Base
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param int $engine * @param int $engine
* @access public * @access public
* @return bool * @return bool
@ -267,7 +275,7 @@ class RC2 extends Base
{ {
switch ($engine) { switch ($engine) {
case self::ENGINE_OPENSSL: case self::ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) != 16) { if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
return false; return false;
} }
$this->cipher_name_openssl_ecb = 'rc2-ecb'; $this->cipher_name_openssl_ecb = 'rc2-ecb';
@ -278,7 +286,7 @@ class RC2 extends Base
} }
/** /**
* Sets the key length * Sets the key length.
* *
* Valid key lengths are 1 to 1024. * Valid key lengths are 1 to 1024.
* Calling this function after setting the key has no effect until the next * Calling this function after setting the key has no effect until the next
@ -294,6 +302,17 @@ class RC2 extends Base
} }
} }
/**
* Returns the current key length
*
* @access public
* @return int
*/
function getKeyLength()
{
return $this->current_key_length;
}
/** /**
* Sets the key. * Sets the key.
* *
@ -349,13 +368,14 @@ class RC2 extends Base
// Prepare the key for mcrypt. // Prepare the key for mcrypt.
$l[0] = $this->invpitable[$l[0]]; $l[0] = $this->invpitable[$l[0]];
array_unshift($l, 'C*'); array_unshift($l, 'C*');
parent::setKey(call_user_func_array('pack', $l)); parent::setKey(call_user_func_array('pack', $l));
} }
/** /**
* Encrypts a message. * Encrypts a message.
* *
* Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
* *
* @see decrypt() * @see decrypt()
* @access public * @access public
@ -378,7 +398,7 @@ class RC2 extends Base
/** /**
* Decrypts a message. * Decrypts a message.
* *
* Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
* *
* @see encrypt() * @see encrypt()
* @access public * @access public

View File

@ -76,14 +76,13 @@ class RC4 extends Base
var $block_size = 0; var $block_size = 0;
/** /**
* The default password key_size used by setPassword() * Key Length
* *
* @see \phpseclib\Crypt\Base::password_key_size * @see \phpseclib\Crypt\RC4::setKeyLength()
* @see \phpseclib\Crypt\Base::setPassword()
* @var int * @var int
* @access private * @access private
*/ */
var $password_key_size = 128; // = 1024 bits var $key_size = 128; // = 1024 bits
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
@ -138,9 +137,9 @@ class RC4 extends Base
/** /**
* Test for engine validity * Test for engine validity
* *
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see Crypt_Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param int $engine * @param int $engine
* @access public * @access public
* @return bool * @return bool
@ -191,18 +190,24 @@ class RC4 extends Base
} }
/** /**
* Sets the key. * Sets the key length
* *
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will * Keys can be between 1 and 256 bytes long.
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
* *
* @access public * @access public
* @see \phpseclib\Crypt\Base::setKey() * @param int $length
* @param string $key
*/ */
function setKey($key) function setKeyLength($length)
{ {
parent::setKey(substr($key, 0, 256)); if ($length < 8) {
$this->key_size = 1;
} elseif ($length > 2048) {
$this->key_size = 248;
} else {
$this->key_size = $length >> 3;
}
parent::setKeyLength($length);
} }
/** /**

View File

@ -65,16 +65,6 @@ use phpseclib\Crypt\Base;
*/ */
class Rijndael extends Base class Rijndael extends Base
{ {
/**
* The default password key_size used by setPassword()
*
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var int
* @access private
*/
var $password_key_size = 16;
/** /**
* The mcrypt specific name of the cipher * The mcrypt specific name of the cipher
* *
@ -101,15 +91,6 @@ class Rijndael extends Base
*/ */
var $password_default_salt = 'phpseclib'; var $password_default_salt = 'phpseclib';
/**
* Has the key length explicitly been set or should it be derived from the key, itself?
*
* @see setKeyLength()
* @var bool
* @access private
*/
var $explicit_key_length = false;
/** /**
* The Key Schedule * The Key Schedule
* *
@ -190,48 +171,7 @@ class Rijndael extends Base
var $kl; var $kl;
/** /**
* Sets the key. * Sets the key length.
*
* Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
* whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
* up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the
* excess bits.
*
* If the key is not explicitly set, it'll be assumed to be all null bytes.
*
* Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits.
*
* @see \phpseclib\Crypt\Base:setKey()
* @see setKeyLength()
* @access public
* @param string $key
*/
function setKey($key)
{
if (!$this->explicit_key_length) {
$length = strlen($key);
switch (true) {
case $length <= 16:
$this->key_size = 16;
break;
case $length <= 20:
$this->key_size = 20;
break;
case $length <= 24:
$this->key_size = 24;
break;
case $length <= 28:
$this->key_size = 28;
break;
default:
$this->key_size = 32;
}
}
parent::setKey($key);
}
/**
* Sets the key length
* *
* Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
* 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount. * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
@ -253,25 +193,23 @@ class Rijndael extends Base
function setKeyLength($length) function setKeyLength($length)
{ {
switch (true) { switch (true) {
case $length == 160:
$this->key_size = 20;
break;
case $length == 224:
$this->key_size = 28;
break;
case $length <= 128: case $length <= 128:
$this->key_size = 16; $this->key_size = 16;
break; break;
case $length <= 160:
$this->key_size = 20;
break;
case $length <= 192: case $length <= 192:
$this->key_size = 24; $this->key_size = 24;
break; break;
case $length <= 224:
$this->key_size = 28;
break;
default: default:
$this->key_size = 32; $this->key_size = 32;
} }
$this->explicit_key_length = true; parent::setKeyLength($length);
$this->changed = true;
$this->_setEngine();
} }
/** /**
@ -302,7 +240,7 @@ class Rijndael extends Base
* *
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param int $engine * @param int $engine
* @access public * @access public
* @return bool * @return bool
@ -328,18 +266,6 @@ class Rijndael extends Base
return parent::isValidEngine($engine); return parent::isValidEngine($engine);
} }
/**
* Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
*
* @see \phpseclib\Crypt\Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
parent::_setupMcrypt();
}
/** /**
* Encrypts a block * Encrypts a block
* *
@ -550,8 +476,6 @@ class Rijndael extends Base
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
); );
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0");
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) { if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) {
// already expanded // already expanded
return; return;
@ -668,9 +592,9 @@ class Rijndael extends Base
/** /**
* Provides the mixColumns and sboxes tables * Provides the mixColumns and sboxes tables
* *
* @see Crypt_Rijndael:_encryptBlock() * @see \phpseclib\Crypt\Rijndael:_encryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt() * @see \phpseclib\Crypt\Rijndael:_setupInlineCrypt()
* @see Crypt_Rijndael:_subWord() * @see \phpseclib\Crypt\Rijndael:_subWord()
* @access private * @access private
* @return array &$tables * @return array &$tables
*/ */
@ -757,9 +681,9 @@ class Rijndael extends Base
/** /**
* Provides the inverse mixColumns and inverse sboxes tables * Provides the inverse mixColumns and inverse sboxes tables
* *
* @see Crypt_Rijndael:_decryptBlock() * @see \phpseclib\Crypt\Rijndael:_decryptBlock()
* @see Crypt_Rijndael:_setupInlineCrypt() * @see \phpseclib\Crypt\Rijndael:_setupInlineCrypt()
* @see Crypt_Rijndael:_setupKey() * @see \phpseclib\Crypt\Rijndael:_setupKey()
* @access private * @access private
* @return array &$tables * @return array &$tables
*/ */

View File

@ -64,15 +64,13 @@ class TripleDES extends DES
const MODE_CBC3 = Base::MODE_CBC; const MODE_CBC3 = Base::MODE_CBC;
/** /**
* The default password key_size used by setPassword() * Key Length
* *
* @see \phpseclib\Crypt\DES::password_key_size * @see \phpseclib\Crypt\TripleDES::setKeyLength()
* @see \phpseclib\Crypt\Base::password_key_size
* @see \phpseclib\Crypt\Base::setPassword()
* @var int * @var int
* @access private * @access private
*/ */
var $password_key_size = 24; var $key_size = 24;
/** /**
* The default salt used by setPassword() * The default salt used by setPassword()
@ -189,7 +187,7 @@ class TripleDES extends DES
* *
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @param int $engine * @param int $engine
* @access public * @access public
* @return bool * @return bool
@ -225,6 +223,32 @@ class TripleDES extends DES
} }
} }
/**
* Sets the key length.
*
* Valid key lengths are 64, 128 and 192
*
* @see \phpseclib\Crypt\Base:setKeyLength()
* @access public
* @param int $length
*/
function setKeyLength($length)
{
$length >>= 3;
switch (true) {
case $length <= 8:
$this->key_size = 8;
break;
case $length <= 16:
$this->key_size = 16;
break;
default:
$this->key_size = 24;
}
parent::setKeyLength($length);
}
/** /**
* Sets the key. * Sets the key.
* *
@ -242,7 +266,7 @@ class TripleDES extends DES
*/ */
function setKey($key) function setKey($key)
{ {
$length = strlen($key); $length = $this->explicit_key_length ? $this->key_size : strlen($key);
if ($length > 8) { if ($length > 8) {
$key = str_pad(substr($key, 0, 24), 24, chr(0)); $key = str_pad(substr($key, 0, 24), 24, chr(0));
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this: // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
@ -421,7 +445,7 @@ class TripleDES extends DES
/** /**
* Sets the internal crypt engine * Sets the internal crypt engine
* *
* @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::__construct()
* @see \phpseclib\Crypt\Base::setPreferredEngine() * @see \phpseclib\Crypt\Base::setPreferredEngine()
* @param int $engine * @param int $engine
* @access public * @access public

View File

@ -362,35 +362,27 @@ class Twofish extends Base
var $kl; var $kl;
/** /**
* Sets the key. * Sets the key length.
* *
* Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long. * Valid key lengths are 128, 192 or 256 bits
* If the key is less than 256-bits we round the length up to the closest valid key length,
* padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits.
*
* If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes.
* *
* @access public * @access public
* @see \phpseclib\Crypt\Base::setKey() * @param int $length
* @param string $key
*/ */
function setKey($key) function setKeyLength($length)
{ {
$keylength = strlen($key);
switch (true) { switch (true) {
case $keylength <= 16: case $length <= 128:
$key = str_pad($key, 16, "\0"); $this->key_size = 16;
break; break;
case $keylength <= 24: case $length <= 192:
$key = str_pad($key, 24, "\0"); $this->key_size = 24;
break; break;
case $keylength < 32: default:
$key = str_pad($key, 32, "\0"); $this->key_size = 32;
break;
case $keylength > 32:
$key = substr($key, 0, 32);
} }
parent::setKey($key);
parent::setKeyLength($length);
} }
/** /**

View File

@ -336,4 +336,39 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
$result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe'))); $result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe')));
$this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe'); $this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe');
} }
public function testGetKeyLengthDefault()
{
$aes = new AES();
$this->assertSame($aes->getKeyLength(), 128);
}
public function testGetKeyLengthWith192BitKey()
{
$aes = new AES();
$aes->setKey(str_repeat('a', 24));
$this->assertSame($aes->getKeyLength(), 192);
}
public function testSetKeyLengthWithLargerKey()
{
$aes = new AES();
$aes->setKeyLength(128);
$aes->setKey(str_repeat('a', 24));
$this->assertSame($aes->getKeyLength(), 128);
$ciphertext = bin2hex($aes->encrypt('a'));
$this->assertSame($ciphertext, '82b7b068dfc60ed2a46893b69fecd6c2');
$this->assertSame($aes->getKeyLength(), 128);
}
public function testSetKeyLengthWithSmallerKey()
{
$aes = new AES();
$aes->setKeyLength(256);
$aes->setKey(str_repeat('a', 16));
$this->assertSame($aes->getKeyLength(), 256);
$ciphertext = bin2hex($aes->encrypt('a'));
$this->assertSame($ciphertext, 'fd4250c0d234aa7e1aa592820aa8406b');
$this->assertSame($aes->getKeyLength(), 256);
}
} }