Merge branch 'openssl-support' into 2.0

Conflicts:
	phpseclib/Crypt/AES.php
	phpseclib/Crypt/Base.php
	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
	phpseclib/Net/SSH2.php
	tests/Functional/Net/SFTPLargeFileTest.php
	tests/Unit/Crypt/AES/InternalTest.php
	tests/Unit/Crypt/AES/McryptTest.php
	tests/Unit/Crypt/AES/TestCase.php
This commit is contained in:
terrafrost 2015-04-02 05:32:31 -05:00
commit ebcb3130b7
22 changed files with 2314 additions and 882 deletions

View File

@ -7,6 +7,10 @@
*
* PHP versions 4 and 5
*
* NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
* just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
* to save one include_once().
*
* If {@link \phpseclib\Crypt\AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link \phpseclib\Crypt\AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 192-bits and 192 bits will be the key length until {@link \phpseclib\Crypt\AES::setKey() setKey()}
@ -56,15 +60,6 @@ use phpseclib\Crypt\Rijndael;
*/
class AES extends Rijndael
{
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'AES';
/**
* Dummy function
*
@ -127,7 +122,7 @@ class AES extends Rijndael
default:
$this->key_size = 32;
}
$this->_setupEngine();
$this->_setEngine();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -68,15 +68,6 @@ class Blowfish extends Base
*/
var $password_key_size = 56;
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'BLOWFISH';
/**
* The mcrypt specific name of the cipher
*
@ -98,7 +89,7 @@ class Blowfish extends Base
/**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
*
* S-Box 1
* S-Box 0
*
* @access private
* @var array
@ -319,6 +310,29 @@ class Blowfish extends Base
parent::setKey($key);
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == self::ENGINE_OPENSSL) {
if (strlen($this->key) != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'bf-ecb';
$this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
* Setup the key (expansion)
*
@ -396,17 +410,17 @@ class Blowfish extends Base
$r = $in[2];
for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
}
@ -443,7 +457,6 @@ class Blowfish extends Base
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
}
@ -458,15 +471,14 @@ class Blowfish extends Base
$lambda_functions =& self::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10);
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Blowfish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Blowfish, {$this->mode}";
// Generation of a unique hash for our generated code
$code_hash = "Crypt_Blowfish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {

View File

@ -97,15 +97,6 @@ class DES extends Base
*/
var $password_key_size = 8;
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'DES';
/**
* The mcrypt specific name of the cipher
*
@ -115,6 +106,21 @@ class DES extends Base
*/
var $cipher_name_mcrypt = 'des';
/**
* The OpenSSL names of the cipher / modes
*
* @see \phpseclib\Crypt\Base::openssl_mode_names
* @var Array
* @access private
*/
var $openssl_mode_names = array(
self::MODE_ECB => 'des-ecb',
self::MODE_CBC => 'des-cbc',
self::MODE_CFB => 'des-cfb',
self::MODE_OFB => 'des-ofb'
// self::MODE_CTR is undefined for DES
);
/**
* Optimizing value while CFB-encrypting
*
@ -585,6 +591,28 @@ class DES extends Base
0x00000820, 0x00020020, 0x08000000, 0x08020800
);
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($this->key_size_max == 8) {
if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ecb';
$this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
}
}
return parent::isValidEngine($engine);
}
/**
* Sets the key.
*
@ -1282,21 +1310,20 @@ class DES extends Base
$des_rounds = $this->des_rounds;
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// (Currently, for Crypt_DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
// (Currently, for Crypt_TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
// Generation of a uniqe hash for our generated code
switch (true) {
case $gen_hi_opt_code:
// For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
$code_hash = md5(str_pad("DES, $des_rounds, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
// After max 10 hi-optimized functions, we create generic
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = "DES, $des_rounds, {$this->mode}";
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
if ($gen_hi_opt_code) {
// For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
// After max 10 hi-optimized functions, we create generic
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there? If not, we have to create it.
@ -1343,8 +1370,8 @@ class DES extends Base
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
}
$init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
$init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
$init_encrypt = '$ke = $self->keys[self::ENCRYPT];';
$init_decrypt = '$kd = $self->keys[self::DECRYPT];';
break;
}

View File

@ -62,7 +62,19 @@ class RC2 extends Base
* @var String
* @access private
*/
var $key = "\0";
var $key;
/**
* The Original (unpadded) Key
*
* @see \phpseclib\Crypt\Base::key
* @see setKey()
* @see encrypt()
* @see decrypt()
* @var String
* @access private
*/
var $orig_key;
/**
* The default password key_size used by setPassword()
@ -74,15 +86,6 @@ class RC2 extends Base
*/
var $password_key_size = 16; // = 128 bits
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RC2';
/**
* The mcrypt specific name of the cipher
*
@ -113,6 +116,17 @@ class RC2 extends Base
*/
var $default_key_length = 1024;
/**
* The key length in bits.
*
* @see \phpseclib\Crypt\RC2::isValidEnine()
* @see \phpseclib\Crypt\RC2::setKey()
* @var Integer
* @access private
* @internal Should be in range [1..1024].
*/
var $current_key_length;
/**
* The Key Schedule
*
@ -240,32 +254,27 @@ class RC2 extends Base
);
/**
* Default Constructor.
* Test for engine validity
*
* Determines whether or not the mcrypt extension should be used.
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* $mode could be:
*
* - \phpseclib\Crypt\Base::MODE_ECB
*
* - \phpseclib\Crypt\Base::MODE_CBC
*
* - \phpseclib\Crypt\Base::MODE_CTR
*
* - \phpseclib\Crypt\Base::MODE_CFB
*
* - \phpseclib\Crypt\Base::MODE_OFB
*
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
*
* @see \phpseclib\Crypt\Base::__construct()
* @param optional Integer $mode
* @see \phpseclib\Crypt\Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function __construct($mode = Base::MODE_CBC)
function isValidEngine($engine)
{
parent::__construct($mode);
$this->setKey('');
switch ($engine) {
case self::ENGINE_OPENSSL:
if ($this->current_key_length != 128 || strlen($this->orig_key) != 16) {
return false;
}
$this->cipher_name_openssl_ecb = 'rc2-ecb';
$this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
}
return parent::isValidEngine($engine);
}
/**
@ -299,15 +308,19 @@ class RC2 extends Base
* @see \phpseclib\Crypt\Base::setKey()
* @access public
* @param String $key
* @param Integer $t1 optional Effective key length in bits.
* @param Integer $t1 optional Effective key length in bits.
*/
function setKey($key, $t1 = 0)
{
$this->orig_key = $key;
if ($t1 <= 0) {
$t1 = $this->default_key_length;
} else if ($t1 > 1024) {
$t1 = 1024;
}
$this->current_key_length = $t1;
// Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
$t = strlen($key);
@ -340,6 +353,52 @@ class RC2 extends Base
parent::setKey(call_user_func_array('pack', $l));
}
/**
* Encrypts a message.
*
* Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code
*
* @see decrypt()
* @access public
* @param String $plaintext
* @return String $ciphertext
*/
function encrypt($plaintext)
{
if ($this->engine == self::ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::encrypt($plaintext);
$this->key = $temp;
return $result;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code
*
* @see encrypt()
* @access public
* @param String $ciphertext
* @return String $plaintext
*/
function decrypt($ciphertext)
{
if ($this->engine == self::ENGINE_OPENSSL) {
$temp = $this->key;
$this->key = $this->orig_key;
$result = parent::decrypt($ciphertext);
$this->key = $temp;
return $result;
}
return parent::encrypt($ciphertext);
}
/**
* Encrypts a block
*
@ -430,6 +489,21 @@ class RC2 extends Base
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
*
* @see \phpseclib\Crypt\Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
if (!isset($this->key)) {
$this->setKey('');
}
parent::_setupMcrypt();
}
/**
* Creates the key schedule
*
@ -438,6 +512,10 @@ class RC2 extends Base
*/
function _setupKey()
{
if (!isset($this->key)) {
$this->setKey('');
}
// Key has already been expanded in \phpseclib\Crypt\RC2::setKey():
// Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key);
@ -460,14 +538,14 @@ class RC2 extends Base
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
$keys = $this->keys;
if (count($lambda_functions) >= 10) {
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
$code_hash = md5(str_pad("RC2, {$this->mode}, ", 32, "\0") . implode(',', $keys));
// Generation of a uniqe hash for our generated code
$code_hash = "Crypt_RC2, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
// Is there a re-usable $lambda_functions in there?
// If not, we have to create it.
@ -475,6 +553,16 @@ class RC2 extends Base
// Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;';
switch (true) {
case $gen_hi_opt_code:
$keys = $this->keys;
default:
$keys = array();
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
// $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = '
$in = unpack("v4", $in);

View File

@ -85,15 +85,6 @@ class RC4 extends Base
*/
var $password_key_size = 128; // = 1024 bits
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RC4';
/**
* The mcrypt specific name of the cipher
*
@ -193,7 +184,7 @@ class RC4 extends Base
*/
function encrypt($plaintext)
{
if ($this->engine == Base::ENGINE_MCRYPT) {
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, self::ENCRYPT);
@ -213,7 +204,7 @@ class RC4 extends Base
*/
function decrypt($ciphertext)
{
if ($this->engine == Base::ENGINE_MCRYPT) {
if ($this->engine != Base::ENGINE_INTERNAL) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, self::DECRYPT);

File diff suppressed because it is too large Load Diff

View File

@ -84,16 +84,6 @@ class TripleDES extends DES
*/
var $password_default_salt = 'phpseclib';
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\DES::const_namespace
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'DES';
/**
* The mcrypt specific name of the cipher
*
@ -194,6 +184,27 @@ class TripleDES extends DES
}
}
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
*
* @see \phpseclib\Crypt\Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == self::ENGINE_OPENSSL) {
$this->cipher_name_openssl_ecb = 'des-ede3';
$mode = $this->_openssl_translate_mode();
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
}
return parent::isValidEngine($engine);
}
/**
* Sets the initialization vector. (optional)
*
@ -236,7 +247,7 @@ class TripleDES extends DES
$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:
// http://php.net/function.mcrypt-encrypt#47973
//$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
} else {
$key = str_pad($key, 8, chr(0));
}
@ -406,4 +417,24 @@ class TripleDES extends DES
// setup our key
parent::_setupKey();
}
/**
* Sets the internal crypt engine
*
* @see \phpseclib\Crypt\Base::Crypt_Base()
* @see \phpseclib\Crypt\Base::setPreferredEngine()
* @param Integer $engine
* @access public
* @return Integer
*/
function setPreferredEngine($engine)
{
if ($this->mode_3cbc) {
$this->des[0]->setPreferredEngine($engine);
$this->des[1]->setPreferredEngine($engine);
$this->des[2]->setPreferredEngine($engine);
}
return parent::setPreferredEngine($engine);
}
}

View File

@ -49,15 +49,6 @@ use phpseclib\Crypt\Base;
*/
class Twofish extends Base
{
/**
* The namespace used by the cipher for its constants.
*
* @see \phpseclib\Crypt\Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'TWOFISH';
/**
* The mcrypt specific name of the cipher
*
@ -678,21 +669,19 @@ class Twofish extends Base
$lambda_functions =& self::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Twofish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Twofish, {$this->mode}";
// Generation of a uniqe hash for our generated code
$code_hash = "Crypt_Twofish, {$this->mode}";
if ($gen_hi_opt_code) {
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$K = $this->K;
$init_crypt = '
static $S0, $S1, $S2, $S3;
if (!$S0) {
@ -710,7 +699,6 @@ class Twofish extends Base
for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i;
}
$init_crypt = '
$S0 = $self->S0;
$S1 = $self->S1;

View File

@ -835,6 +835,16 @@ class SSH2
*/
var $windowRows = 24;
/**
* Crypto Engine
*
* @see Net_SSH2::setCryptoEngine()
* @see Net_SSH2::_key_exchange()
* @var Integer
* @access private
*/
var $crypto_engine = false;
/**
* Default Constructor.
*
@ -922,6 +932,20 @@ class SSH2
$this->connectionTimeout = $timeout;
}
/**
* Set Crypto Engine Mode
*
* Possible $engine values:
* CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
*
* @param Integer $engine
* @access private
*/
function setCryptoEngine($engine)
{
$this->crypto_engine = $engine;
}
/**
* Connect to an SSHv2 server
*
@ -1043,7 +1067,9 @@ class SSH2
$identifier = 'SSH-2.0-phpseclib_0.3';
$ext = array();
if (extension_loaded('mcrypt')) {
if (extension_loaded('openssl')) {
$ext[] = 'openssl';
} elseif (extension_loaded('mcrypt')) {
$ext[] = 'mcrypt';
}
@ -1085,7 +1111,7 @@ class SSH2
'arcfour256',
'arcfour128',
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
//'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
// CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
@ -1113,9 +1139,18 @@ class SSH2
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-cbc', // REQUIRED three-key 3DES in CBC mode
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
//'none' // OPTIONAL no encryption; NOT RECOMMENDED
);
if (extension_loaded('openssl') && !extension_loaded('mcrypt')) {
// OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to
// instances that do not use continuous buffers
$encryption_algorithms = array_diff(
$encryption_algorithms,
array('arcfour256', 'arcfour128', 'arcfour')
);
}
if (class_exists('\phpseclib\Crypt\RC4') === false) {
$encryption_algorithms = array_diff(
$encryption_algorithms,
@ -1573,6 +1608,9 @@ class SSH2
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
if ($this->encrypt) {
if ($this->crypto_engine) {
$this->encrypt->setEngine($this->crypto_engine);
}
$this->encrypt->enableContinuousBuffer();
$this->encrypt->disablePadding();
@ -1590,6 +1628,9 @@ class SSH2
}
if ($this->decrypt) {
if ($this->crypto_engine) {
$this->decrypt->setEngine($this->crypto_engine);
}
$this->decrypt->enableContinuousBuffer();
$this->decrypt->disablePadding();

View File

@ -16,17 +16,10 @@ class Functional_Net_SFTPLargeFileTest extends PhpseclibFunctionalTestCase
static public function setUpBeforeClass()
{
if (!extension_loaded('mcrypt')) {
self::markTestSkipped('This test depends on mcrypt for performance.');
if (!extension_loaded('mcrypt') && !extension_loaded('openssl')) {
self::markTestSkipped('This test depends on mcrypt or openssl for performance.');
}
parent::setUpBeforeClass();
self::ensureConstant('CRYPT_AES_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_BLOWFISH_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_DES_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_RC2_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_RC4_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_TWOFISH_MODE', Base::ENGINE_MCRYPT);
}
public function setUp()

View File

@ -9,11 +9,8 @@ use phpseclib\Crypt\Base;
class Unit_Crypt_AES_InternalTest extends Unit_Crypt_AES_TestCase
{
static public function setUpBeforeClass()
protected function setUp()
{
parent::setUpBeforeClass();
self::ensureConstant('CRYPT_AES_MODE', Base::ENGINE_INTERNAL);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', Base::ENGINE_INTERNAL);
$this->engine = Base::ENGINE_INTERNAL;
}
}

View File

@ -9,15 +9,8 @@ use phpseclib\Crypt\Base;
class Unit_Crypt_AES_McryptTest extends Unit_Crypt_AES_TestCase
{
static public function setUpBeforeClass()
protected function setUp()
{
if (!extension_loaded('mcrypt')) {
self::markTestSkipped('mcrypt extension is not available.');
}
parent::setUpBeforeClass();
self::ensureConstant('CRYPT_AES_MODE', Base::ENGINE_MCRYPT);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', Base::ENGINE_MCRYPT);
$this->engine = Base::ENGINE_MCRYPT;
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright 2013 Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
class Unit_Crypt_AES_OpenSSLTest extends Unit_Crypt_AES_TestCase
{
protected function setUp()
{
$this->engine = Base::ENGINE_OPENSSL;
}
}

View File

@ -11,14 +11,21 @@ use phpseclib\Crypt\Rijndael;
abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
{
static public function setUpBeforeClass()
protected $engine;
private function _checkEngine($aes)
{
include_once 'Crypt/AES.php';
parent::setUpBeforeClass();
self::reRequireFile('Crypt/Rijndael.php');
self::reRequireFile('Crypt/AES.php');
if ($aes->getEngine() != $this->engine) {
$engine = 'internal';
switch ($this->engine) {
case Base::ENGINE_OPENSSL:
$engine = 'OpenSSL';
break;
case Base::ENGINE_MCRYPT:
$engine = 'mcrypt';
}
self::markTestSkipped('Unable to initialize ' . $engine . ' engine');
}
}
/**
@ -68,10 +75,13 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
public function testEncryptDecryptWithContinuousBuffer($mode, $plaintext, $iv, $key)
{
$aes = new AES($mode);
$aes->setPreferredEngine($this->engine);
$aes->enableContinuousBuffer();
$aes->setIV($iv);
$aes->setKey($key);
$this->_checkEngine($aes);
$actual = '';
for ($i = 0, $strlen = strlen($plaintext); $i < $strlen; ++$i) {
$actual .= $aes->decrypt($aes->encrypt($plaintext[$i]));
@ -89,8 +99,10 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
// https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip
$aes = new Rijndael();
$aes->setPreferredEngine($this->engine);
$aes->disablePadding();
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. Valid in Rijndael.
//$this->_checkEngine($aes); // should only work in internal mode
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
$this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880'));
}
@ -103,9 +115,221 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
// same as the above - just with a different ciphertext
$aes = new AES();
$aes->setPreferredEngine($this->engine);
$aes->disablePadding();
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits
$this->_checkEngine($aes);
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
$this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0'));
}
/**
* Produces all combinations of test values.
*
* @return array
*/
public function continuousBufferBatteryCombos()
{
$modes = array(
Base::MODE_CTR,
Base::MODE_OFB,
Base::MODE_CFB,
);
$combos = array(
array(16),
array(17),
array(1, 16),
array(3, 6, 7), // (3 to test the openssl_encrypt call and the buffer creation, 6 to test the exclusive use of the buffer and 7 to test the buffer's exhaustion and recreation)
array(15, 4), // (15 to test openssl_encrypt call and buffer creation and 4 to test something that spans multpile bloc
array(3, 6, 10, 16), // this is why the strlen check in the buffer-only code was needed
array(16, 16), // two full size blocks
array(3, 6, 7, 16), // partial block + full size block
array(16, 3, 6, 7),
// a few others just for fun
array(32,32),
array(31,31),
array(17,17),
array(99, 99)
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($modes as $mode)
foreach ($combos as $combo)
foreach (array('encrypt', 'decrypt') as $op)
$result[] = array($op, $mode, $combo);
// @codingStandardsIgnoreEnd
return $result;
}
/**
* @dataProvider continuousBufferBatteryCombos
*/
public function testContinuousBufferBattery($op, $mode, $test)
{
$iv = str_repeat('x', 16);
$key = str_repeat('a', 16);
$aes = new AES($mode);
$aes->setPreferredEngine($this->engine);
$aes->setKey($key);
$aes->setIV($iv);
$this->_checkEngine($aes);
$str = '';
$result = '';
foreach ($test as $len) {
$temp = str_repeat('d', $len);
$str.= $temp;
}
$c1 = $aes->$op($str);
$aes = new AES($mode);
$aes->setPreferredEngine($this->engine);
$aes->enableContinuousBuffer();
$aes->setKey($key);
$aes->setIV($iv);
if (!$this->_checkEngine($aes)) {
return;
}
foreach ($test as $len) {
$temp = str_repeat('d', $len);
$output = $aes->$op($temp);
$result.= $output;
}
$c2 = $result;
$this->assertSame(bin2hex($c1), bin2hex($c2));
}
/**
* @dataProvider continuousBufferBatteryCombos
*/
// pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled
public function testNonContinuousBufferBattery($op, $mode, $test)
{
if (count($test) == 1) {
return;
}
$iv = str_repeat('x', 16);
$key = str_repeat('a', 16);
$aes = new AES($mode);
$aes->setPreferredEngine($this->engine);
$aes->setKey($key);
$aes->setIV($iv);
$this->_checkEngine($aes);
$str = '';
$result = '';
foreach ($test as $len) {
$temp = str_repeat('d', $len);
$str.= $temp;
}
$c1 = $aes->$op($str);
$aes = new AES($mode);
$aes->setPreferredEngine($this->engine);
$aes->setKey($key);
$aes->setIV($iv);
$this->_checkEngine($aes);
foreach ($test as $len) {
$temp = str_repeat('d', $len);
$output = $aes->$op($temp);
$result.= $output;
}
$c2 = $result;
$this->assertNotSame(bin2hex($c1), bin2hex($c2));
}
// from http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf#page=16
public function testGFSBox128()
{
$aes = new AES();
$aes->setKey(pack('H*', '00000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
$aes->disablePadding();
$aes->setPreferredEngine($this->engine);
$this->_checkEngine($aes);
$result = bin2hex($aes->encrypt(pack('H*', 'f34481ec3cc627bacd5dc3fb08f273e6')));
$this->assertSame($result, '0336763e966d92595a567cc9ce537f5e');
$result = bin2hex($aes->encrypt(pack('H*', '9798c4640bad75c7c3227db910174e72')));
$this->assertSame($result, 'a9a1631bf4996954ebc093957b234589');
$result = bin2hex($aes->encrypt(pack('H*', '96ab5c2ff612d9dfaae8c31f30c42168')));
$this->assertSame($result, 'ff4f8391a6a40ca5b25d23bedd44a597');
$result = bin2hex($aes->encrypt(pack('H*', '6a118a874519e64e9963798a503f1d35')));
$this->assertSame($result, 'dc43be40be0e53712f7e2bf5ca707209');
$result = bin2hex($aes->encrypt(pack('H*', 'cb9fceec81286ca3e989bd979b0cb284')));
$this->assertSame($result, '92beedab1895a94faa69b632e5cc47ce');
$result = bin2hex($aes->encrypt(pack('H*', 'b26aeb1874e47ca8358ff22378f09144')));
$this->assertSame($result, '459264f4798f6a78bacb89c15ed3d601');
$result = bin2hex($aes->encrypt(pack('H*', '58c8e00b2631686d54eab84b91f0aca1')));
$this->assertSame($result, '08a4e2efec8a8e3312ca7460b9040bbf');
}
public function testGFSBox192()
{
$aes = new AES();
$aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
$aes->disablePadding();
$aes->setPreferredEngine($this->engine);
$this->_checkEngine($aes);
$result = bin2hex($aes->encrypt(pack('H*', '1b077a6af4b7f98229de786d7516b639')));
$this->assertSame($result, '275cfc0413d8ccb70513c3859b1d0f72');
$result = bin2hex($aes->encrypt(pack('H*', '9c2d8842e5f48f57648205d39a239af1')));
$this->assertSame($result, 'c9b8135ff1b5adc413dfd053b21bd96d');
$result = bin2hex($aes->encrypt(pack('H*', 'bff52510095f518ecca60af4205444bb')));
$this->assertSame($result, '4a3650c3371ce2eb35e389a171427440');
$result = bin2hex($aes->encrypt(pack('H*', '51719783d3185a535bd75adc65071ce1')));
$this->assertSame($result, '4f354592ff7c8847d2d0870ca9481b7c');
$result = bin2hex($aes->encrypt(pack('H*', '26aa49dcfe7629a8901a69a9914e6dfd')));
$this->assertSame($result, 'd5e08bf9a182e857cf40b3a36ee248cc');
$result = bin2hex($aes->encrypt(pack('H*', '941a4773058224e1ef66d10e0a6ee782')));
$this->assertSame($result, '067cd9d3749207791841562507fa9626');
}
public function testGFSBox256()
{
$aes = new AES();
$aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000'));
$aes->setIV(pack('H*', '00000000000000000000000000000000'));
$aes->disablePadding();
$aes->setPreferredEngine($this->engine);
$this->_checkEngine($aes);
$result = bin2hex($aes->encrypt(pack('H*', '014730f80ac625fe84f026c60bfd547d')));
$this->assertSame($result, '5c9d844ed46f9885085e5d6a4f94c7d7');
$result = bin2hex($aes->encrypt(pack('H*', '0b24af36193ce4665f2825d7b4749c98')));
$this->assertSame($result, 'a9ff75bd7cf6613d3731c77c3b6d0c04');
$result = bin2hex($aes->encrypt(pack('H*', '761c1fe41a18acf20d241650611d90f1')));
$this->assertSame($result, '623a52fcea5d443e48d9181ab32c7421');
$result = bin2hex($aes->encrypt(pack('H*', '8a560769d605868ad80d819bdba03771')));
$this->assertSame($result, '38f2c7ae10612415d27ca190d27da8b4');
$result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe')));
$this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe');
}
}

View File

@ -0,0 +1,84 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\Blowfish;
class Unit_Crypt_BlowfishTest extends PhpseclibTestCase
{
public function engineVectors()
{
$engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENINE_OPENSSL => 'OpenSSL',
);
// tests from https://www.schneier.com/code/vectors.txt
$tests = array(
// key, plaintext, ciphertext
array(pack('H*', '0000000000000000'), pack('H*', '0000000000000000'), pack('H*', '4EF997456198DD78')),
array(pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '51866FD5B85ECB8A')),
array(pack('H*', '3000000000000000'), pack('H*', '1000000000000001'), pack('H*', '7D856F9A613063F2')),
array(pack('H*', '1111111111111111'), pack('H*', '1111111111111111'), pack('H*', '2466DD878B963C9D')),
array(pack('H*', '0123456789ABCDEF'), pack('H*', '1111111111111111'), pack('H*', '61F9C3802281B096')),
array(pack('H*', '1111111111111111'), pack('H*', '0123456789ABCDEF'), pack('H*', '7D0CC630AFDA1EC7')),
array(pack('H*', '0000000000000000'), pack('H*', '0000000000000000'), pack('H*', '4EF997456198DD78')),
array(pack('H*', 'FEDCBA9876543210'), pack('H*', '0123456789ABCDEF'), pack('H*', '0ACEAB0FC6A0A28D')),
array(pack('H*', '7CA110454A1A6E57'), pack('H*', '01A1D6D039776742'), pack('H*', '59C68245EB05282B')),
array(pack('H*', '0131D9619DC1376E'), pack('H*', '5CD54CA83DEF57DA'), pack('H*', 'B1B8CC0B250F09A0')),
array(pack('H*', '07A1133E4A0B2686'), pack('H*', '0248D43806F67172'), pack('H*', '1730E5778BEA1DA4')),
array(pack('H*', '3849674C2602319E'), pack('H*', '51454B582DDF440A'), pack('H*', 'A25E7856CF2651EB')),
array(pack('H*', '04B915BA43FEB5B6'), pack('H*', '42FD443059577FA2'), pack('H*', '353882B109CE8F1A')),
array(pack('H*', '0113B970FD34F2CE'), pack('H*', '059B5E0851CF143A'), pack('H*', '48F4D0884C379918')),
array(pack('H*', '0170F175468FB5E6'), pack('H*', '0756D8E0774761D2'), pack('H*', '432193B78951FC98')),
array(pack('H*', '43297FAD38E373FE'), pack('H*', '762514B829BF486A'), pack('H*', '13F04154D69D1AE5')),
array(pack('H*', '07A7137045DA2A16'), pack('H*', '3BDD119049372802'), pack('H*', '2EEDDA93FFD39C79')),
array(pack('H*', '04689104C2FD3B2F'), pack('H*', '26955F6835AF609A'), pack('H*', 'D887E0393C2DA6E3')),
array(pack('H*', '37D06BB516CB7546'), pack('H*', '164D5E404F275232'), pack('H*', '5F99D04F5B163969')),
array(pack('H*', '1F08260D1AC2465E'), pack('H*', '6B056E18759F5CCA'), pack('H*', '4A057A3B24D3977B')),
array(pack('H*', '584023641ABA6176'), pack('H*', '004BD6EF09176062'), pack('H*', '452031C1E4FADA8E')),
array(pack('H*', '025816164629B007'), pack('H*', '480D39006EE762F2'), pack('H*', '7555AE39F59B87BD')),
array(pack('H*', '49793EBC79B3258F'), pack('H*', '437540C8698F3CFA'), pack('H*', '53C55F9CB49FC019')),
array(pack('H*', '4FB05E1515AB73A7'), pack('H*', '072D43A077075292'), pack('H*', '7A8E7BFA937E89A3')),
array(pack('H*', '49E95D6D4CA229BF'), pack('H*', '02FE55778117F12A'), pack('H*', 'CF9C5D7A4986ADB5')),
array(pack('H*', '018310DC409B26D6'), pack('H*', '1D9D5C5018F728C2'), pack('H*', 'D1ABB290658BC778')),
array(pack('H*', '1C587F1C13924FEF'), pack('H*', '305532286D6F295A'), pack('H*', '55CB3774D13EF201')),
array(pack('H*', '0101010101010101'), pack('H*', '0123456789ABCDEF'), pack('H*', 'FA34EC4847B268B2')),
array(pack('H*', '1F1F1F1F0E0E0E0E'), pack('H*', '0123456789ABCDEF'), pack('H*', 'A790795108EA3CAE')),
array(pack('H*', 'E0FEE0FEF1FEF1FE'), pack('H*', '0123456789ABCDEF'), pack('H*', 'C39E072D9FAC631D')),
array(pack('H*', '0000000000000000'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '014933E0CDAFF6E4')),
array(pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '0000000000000000'), pack('H*', 'F21E9A77B71C49BC')),
array(pack('H*', '0123456789ABCDEF'), pack('H*', '0000000000000000'), pack('H*', '245946885754369A')),
array(pack('H*', 'FEDCBA9876543210'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '6B5C5A9C5D9E0A5A'))
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName)
foreach ($tests as $test)
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2]);
// @codingStandardsIgnoreEnd
return $result;
}
/**
* @dataProvider engineVectors
*/
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
{
$bf = new Blowfish();
$bf->setKey($key);
if (!$bf->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
}
$bf->setPreferredEngine($engine);
$bf->disablePadding();
$result = $bf->encrypt($plaintext);
$plaintext = bin2hex($plaintext);
$this->assertEquals($result, $expected, "Failed asserting that $plaintext yielded expected output in $engineName engine");
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\DES;
// the AES tests establish the correctness of the modes of operation. this test is inteded to establish the consistency of
// key and iv padding between the multiple engines
class Unit_Crypt_DESTest extends PhpseclibTestCase
{
public function testEncryptPadding()
{
$des = new DES(Base::MODE_CBC);
$des->setKey('d');
$des->setIV('d');
$des->setPreferredEngine(Base::ENGINE_INTERNAL);
$result = pack('H*', '3e7613642049af1e');
$internal = $des->encrypt('d');
$this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result');
$des->setPreferredEngine(Base::ENGINE_MCRYPT);
if ($des->getEngine() == Base::ENGINE_MCRYPT) {
$mcrypt = $des->encrypt('d');
$this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize mcrypt engine');
}
$des->setPreferredEngine(Base::ENGINE_OPENSSL);
if ($des->getEngine() == Base::ENGINE_OPENSSL) {
$openssl = $des->encrypt('d');
$this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize OpenSSL engine');
}
}
// phpseclib null pads ciphertext's if they're not long enough and you're in ecb / cbc mode. this silent failure mode is consistent
// with mcrypt's behavior. maybe throwing an exception would be better but whatever. this test is more intended to establish consistent
// behavior between the various engine's
public function testDecryptPadding()
{
$des = new DES(Base::MODE_CBC);
$des->disablePadding();
// when the key and iv are not specified they should be null padded
//$des->setKey();
//$des->setIV();
$des->setPreferredEngine(Base::ENGINE_INTERNAL);
$internal = $des->decrypt('d');
$result = pack('H*', '79b305d1ce555221');
$this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result');
$des->setPreferredEngine(Base::ENGINE_MCRYPT);
if ($des->getEngine() == Base::ENGINE_MCRYPT) {
$mcrypt = $des->decrypt('d');
$this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize mcrypt engine');
}
$des->setPreferredEngine(Base::ENGINE_OPENSSL);
if ($des->getEngine() == Base::ENGINE_OPENSSL) {
$openssl = $des->encrypt('d');
$this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize OpenSSL engine');
}
}
}

View File

@ -0,0 +1,122 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\RC2;
class Unit_Crypt_RC2Test extends PhpseclibTestCase
{
var $engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENGINE_OPENSL => 'OpenSSL',
);
public function engineVectors()
{
// tests from https://tools.ietf.org/html/rfc2268#page-8
$tests = array(
// key, effective key length, plaintext, ciphertext
array('0000000000000000', 63, '0000000000000000', 'ebb773f993278eff'),
array('ffffffffffffffff', 64, 'ffffffffffffffff', '278b27e42e2f0d49'),
array('3000000000000000', 64, '1000000000000001', '30649edf9be7d2c2'),
array('88', 64, '0000000000000000', '61a8a244adacccf0'),
array('88bca90e90875a', 64, '0000000000000000', '6ccf4308974c267f'),
array('88bca90e90875a7f0f79c384627bafb2', 64, '0000000000000000', '1a807d272bbe5db1'),
array('88bca90e90875a7f0f79c384627bafb2', 128, '0000000000000000', '2269552ab0f85ca6'),
array('88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', 129, '0000000000000000', '5b78d3a43dfff1f1')
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($this->engines as $engine => $engineName)
foreach ($tests as $test)
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]);
// @codingStandardsIgnoreEnd
return $result;
}
// this test is just confirming RC2's key expansion
public function testEncryptPadding()
{
$rc2 = new RC2(Base::MODE_ECB);
// unlike Crypt_AES / Crypt_Rijndael, when you tell Crypt_RC2 that the key length is 128-bits the key isn't null padded to that length.
// instead, RC2 key expansion is used to extend it out to that length. this isn't done for AES / Rijndael since that doesn't define any
// sort of key expansion algorithm.
// admittedly, phpseclib is inconsistent in this regard. RC4 and Blowfish support arbitrary key lengths between a certain range, as well,
// and they don't have any way to set the key length. but then again, neither do those algorithms have their own key expansion algorithm,
// whereas RC2 does. and technically, AES / Rijndael (and even Twofish) don't support arbitrary key lengths - they support variable key
// lengths. so in some ways, i suppose this inconsistency somewhat makes sense, although the fact that Crypt_Twofish doesn't have a
// setKeyLength() function whereas Crypt_AES / Crypt_Rijndael do not is, itself, an inconsistency.
// but that said, Crypt_RC2 is inconsistent in other ways: if you pass a 128-bit (16-byte) key to it via setKey() the key is not treated
// as a 128-bit key but rather as a 1024-bit key and is expanded accordingly, not via null padding, but via RC2's key expansion algorithm.
// this behavior is in contrast to mcrypt, which extends keys via null padding to 1024 bits. it is also in contrast to OpenSSL, which
// extends keys, via null padding, to 128 bits. mcrypt's approach seems preferable as one can simulate 128 bit keys by using RC2's
// key expansion algorithm to extend the key to 1024 bits and then changing the first byte of the new key with an inverse pitable mapping.
// in contrast, to my knowledge, there is no technique for expanding a key less than 128 bits to 128 bits, via RC2 key expansion. the only
// scenario in that regard is null padding.
// simple truncation is insufficient, since, quoting RFC2268, "the purpose of the key-expansion algorithm [in RC2] is to modify the key buffer
// so that each bit of the expanded key depends in a complicated way on every bit of the supplied input key".
// now, to OpenSSL's credit, null padding is internally consistent with OpenSSL. OpenSSL only supports fixed length keys. For rc2, rc4 and
// bf (blowfish), all keys are 128 bits (or are null padded / truncated accordingly). to use 40-bit or 64-bit keys with RC4 with OpenSSL you
// don't use the rc4 algorithm - you use the rc4-40 or rc4-64 algorithm. and similarily, it's not aes-cbc that you use - it's either aes-128-cbc
// or aes-192-cbc or aes-256-cbc. this is in contrast to mcrypt, which (with the exception of RC2) actually supports variable and arbitrary
// length keys.
// superficially, it seens like Rijndael would be another exception to mcrypt's key length handling, but it in fact is not. the reason being that,
// with mcrypt, when you specify MCRYPT_RIJNDAEL_128 or MCRYPT_RIJNDAEL_192 or MCRYPT_RIJNDAEL_256 the numbers at the end aren't referring to the
// key length, but rather, the block length. ie. Rijndael, unlike most block ciphers, doesn't just have a variable (but not arbitrary) key length -
// it also has a variable block length. AES's block length, however, is not variable, so technically, only MCRYPT_RIJNDAEL_128 is AES.
$rc2->setKey(str_repeat('d', 16), 128);
$rc2->setPreferredEngine(Base::ENGINE_INTERNAL);
$internal = $rc2->encrypt('d');
$result = pack('H*', 'e3b36057f4821346');
$this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result');
$rc2->setPreferredEngine(Base::ENGINE_MCRYPT);
if ($rc2->getEngine() == Base::ENGINE_MCRYPT) {
$mcrypt = $rc2->encrypt('d');
$this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize mcrypt engine');
}
$rc2->setPreferredEngine(self::ENGINE_OPENSSL);
if ($rc2->getEngine() == self::ENGINE_OPENSSL) {
$openssl = $rc2->encrypt('d');
$this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result');
} else {
self::markTestSkipped('Unable to initialize OpenSSL engine');
}
}
/**
* @dataProvider engineVectors
*/
public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext)
{
$rc2 = new RC2();
$rc2->disablePadding();
$rc2->setKeyLength($keyLen);
$rc2->setKey(pack('H*', $key)); // could also do $rc2->setKey(pack('H*', $key), $keyLen)
if (!$rc2->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
}
$rc2->setPreferredEngine($engine);
$result = bin2hex($rc2->encrypt(pack('H*', $plaintext)));
$this->assertEquals($result, $ciphertext, "Failed asserting that $plaintext yielded expected output in $engineName engine");
}
}

View File

@ -0,0 +1,208 @@
<?php
/**
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\RC4;
class Unit_Crypt_RC4Test extends PhpseclibTestCase
{
public function engineVectors()
{
$engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENGINE_MCRYPT => 'OpenSSL',
);
// tests from https://tools.ietf.org/html/rfc6229
$tests = array(
array(
'key' => pack('H*', '0102030405'), // 40-bit key
'output' => array(
array('offset' => 0, 'result' => 'b2396305f03dc027ccc3524a0a1118a8'),
array('offset' => 16, 'result' => '6982944f18fc82d589c403a47a0d0919'),
array('offset' => 240, 'result' => '28cb1132c96ce286421dcaadb8b69eae'),
array('offset' => 256, 'result' => '1cfcf62b03eddb641d77dfcf7f8d8c93'),
array('offset' => 496, 'result' => '42b7d0cdd918a8a33dd51781c81f4041'),
array('offset' => 512, 'result' => '6459844432a7da923cfb3eb4980661f6'),
array('offset' => 752, 'result' => 'ec10327bde2beefd18f9277680457e22'),
array('offset' => 768, 'result' => 'eb62638d4f0ba1fe9fca20e05bf8ff2b'),
array('offset' => 1008, 'result' => '45129048e6a0ed0b56b490338f078da5'),
array('offset' => 1024, 'result' => '30abbcc7c20b01609f23ee2d5f6bb7df'),
array('offset' => 1520, 'result' => '3294f744d8f9790507e70f62e5bbceea'),
array('offset' => 1536, 'result' => 'd8729db41882259bee4f825325f5a130'),
array('offset' => 2032, 'result' => '1eb14a0c13b3bf47fa2a0ba93ad45b8b'),
array('offset' => 2048, 'result' => 'cc582f8ba9f265e2b1be9112e975d2d7'),
array('offset' => 3056, 'result' => 'f2e30f9bd102ecbf75aaade9bc35c43c'),
array('offset' => 3072, 'result' => 'ec0e11c479dc329dc8da7968fe965681'),
array('offset' => 4080, 'result' => '068326a2118416d21f9d04b2cd1ca050'),
array('offset' => 4096, 'result' => 'ff25b58995996707e51fbdf08b34d875')
)
),
array(
'key' => pack('H*', '01020304050607'), // 56-bit key
'output' => array(
array('offset' => 0, 'result' => '293f02d47f37c9b633f2af5285feb46b'),
array('offset' => 16, 'result' => 'e620f1390d19bd84e2e0fd752031afc1'),
array('offset' => 240, 'result' => '914f02531c9218810df60f67e338154c'),
array('offset' => 256, 'result' => 'd0fdb583073ce85ab83917740ec011d5'),
array('offset' => 496, 'result' => '75f81411e871cffa70b90c74c592e454'),
array('offset' => 512, 'result' => '0bb87202938dad609e87a5a1b079e5e4'),
array('offset' => 752, 'result' => 'c2911246b612e7e7b903dfeda1dad866'),
array('offset' => 768, 'result' => '32828f91502b6291368de8081de36fc2'),
array('offset' => 1008, 'result' => 'f3b9a7e3b297bf9ad804512f9063eff1'),
array('offset' => 1024, 'result' => '8ecb67a9ba1f55a5a067e2b026a3676f'),
array('offset' => 1520, 'result' => 'd2aa902bd42d0d7cfd340cd45810529f'),
array('offset' => 1536, 'result' => '78b272c96e42eab4c60bd914e39d06e3'),
array('offset' => 2032, 'result' => 'f4332fd31a079396ee3cee3f2a4ff049'),
array('offset' => 2048, 'result' => '05459781d41fda7f30c1be7e1246c623'),
array('offset' => 3056, 'result' => 'adfd3868b8e51485d5e610017e3dd609'),
array('offset' => 3072, 'result' => 'ad26581c0c5be45f4cea01db2f3805d5'),
array('offset' => 4080, 'result' => 'f3172ceffc3b3d997c85ccd5af1a950c'),
array('offset' => 4096, 'result' => 'e74b0b9731227fd37c0ec08a47ddd8b8')
)
),
array(
'key' => pack('H*', '0102030405060708'), // 64-bit key
'output' => array(
array('offset' => 0, 'result' => '97ab8a1bf0afb96132f2f67258da15a8'),
array('offset' => 16, 'result' => '8263efdb45c4a18684ef87e6b19e5b09'),
array('offset' => 240, 'result' => '9636ebc9841926f4f7d1f362bddf6e18'),
array('offset' => 256, 'result' => 'd0a990ff2c05fef5b90373c9ff4b870a'),
array('offset' => 496, 'result' => '73239f1db7f41d80b643c0c52518ec63'),
array('offset' => 512, 'result' => '163b319923a6bdb4527c626126703c0f'),
array('offset' => 752, 'result' => '49d6c8af0f97144a87df21d91472f966'),
array('offset' => 768, 'result' => '44173a103b6616c5d5ad1cee40c863d0'),
array('offset' => 1008, 'result' => '273c9c4b27f322e4e716ef53a47de7a4'),
array('offset' => 1024, 'result' => 'c6d0e7b226259fa9023490b26167ad1d'),
array('offset' => 1520, 'result' => '1fe8986713f07c3d9ae1c163ff8cf9d3'),
array('offset' => 1536, 'result' => '8369e1a965610be887fbd0c79162aafb'),
array('offset' => 2032, 'result' => '0a0127abb44484b9fbef5abcae1b579f'),
array('offset' => 2048, 'result' => 'c2cdadc6402e8ee866e1f37bdb47e42c'),
array('offset' => 3056, 'result' => '26b51ea37df8e1d6f76fc3b66a7429b3'),
array('offset' => 3072, 'result' => 'bc7683205d4f443dc1f29dda3315c87b'),
array('offset' => 4080, 'result' => 'd5fa5a3469d29aaaf83d23589db8c85b'),
array('offset' => 4096, 'result' => '3fb46e2c8f0f068edce8cdcd7dfc5862')
)
),
array(
'key' => pack('H*', '0102030405060708090a'), // 80-bit key
'output' => array(
array('offset' => 0, 'result' => 'ede3b04643e586cc907dc21851709902'),
array('offset' => 16, 'result' => '03516ba78f413beb223aa5d4d2df6711'),
array('offset' => 240, 'result' => '3cfd6cb58ee0fdde640176ad0000044d'),
array('offset' => 256, 'result' => '48532b21fb6079c9114c0ffd9c04a1ad'),
array('offset' => 496, 'result' => '3e8cea98017109979084b1ef92f99d86'),
array('offset' => 512, 'result' => 'e20fb49bdb337ee48b8d8dc0f4afeffe'),
array('offset' => 752, 'result' => '5c2521eacd7966f15e056544bea0d315'),
array('offset' => 768, 'result' => 'e067a7031931a246a6c3875d2f678acb'),
array('offset' => 1008, 'result' => 'a64f70af88ae56b6f87581c0e23e6b08'),
array('offset' => 1024, 'result' => 'f449031de312814ec6f319291f4a0516'),
array('offset' => 1520, 'result' => 'bdae85924b3cb1d0a2e33a30c6d79599'),
array('offset' => 1536, 'result' => '8a0feddbac865a09bcd127fb562ed60a'),
array('offset' => 2032, 'result' => 'b55a0a5b51a12a8be34899c3e047511a'),
array('offset' => 2048, 'result' => 'd9a09cea3ce75fe39698070317a71339'),
array('offset' => 3056, 'result' => '552225ed1177f44584ac8cfa6c4eb5fc'),
array('offset' => 3072, 'result' => '7e82cbabfc95381b080998442129c2f8'),
array('offset' => 4080, 'result' => '1f135ed14ce60a91369d2322bef25e3c'),
array('offset' => 4096, 'result' => '08b6be45124a43e2eb77953f84dc8553')
)
),
array(
'key' => pack('H*', '0102030405060708090a0b0c0d0e0f10'), // 128-bit key
'output' => array(
array('offset' => 0, 'result' => '9ac7cc9a609d1ef7b2932899cde41b97'),
array('offset' => 16, 'result' => '5248c4959014126a6e8a84f11d1a9e1c'),
array('offset' => 240, 'result' => '065902e4b620f6cc36c8589f66432f2b'),
array('offset' => 256, 'result' => 'd39d566bc6bce3010768151549f3873f'),
array('offset' => 496, 'result' => 'b6d1e6c4a5e4771cad79538df295fb11'),
array('offset' => 512, 'result' => 'c68c1d5c559a974123df1dbc52a43b89'),
array('offset' => 752, 'result' => 'c5ecf88de897fd57fed301701b82a259'),
array('offset' => 768, 'result' => 'eccbe13de1fcc91c11a0b26c0bc8fa4d'),
array('offset' => 1008, 'result' => 'e7a72574f8782ae26aabcf9ebcd66065'),
array('offset' => 1024, 'result' => 'bdf0324e6083dcc6d3cedd3ca8c53c16'),
array('offset' => 1520, 'result' => 'b40110c4190b5622a96116b0017ed297'),
array('offset' => 1536, 'result' => 'ffa0b514647ec04f6306b892ae661181'),
array('offset' => 2032, 'result' => 'd03d1bc03cd33d70dff9fa5d71963ebd'),
array('offset' => 2048, 'result' => '8a44126411eaa78bd51e8d87a8879bf5'),
array('offset' => 3056, 'result' => 'fabeb76028ade2d0e48722e46c4615a3'),
array('offset' => 3072, 'result' => 'c05d88abd50357f935a63c59ee537623'),
array('offset' => 4080, 'result' => 'ff38265c1642c1abe8d3c2fe5e572bf8'),
array('offset' => 4096, 'result' => 'a36a4c301ae8ac13610ccbc12256cacc')
)
),
array(
'key' => pack('H*', '0102030405060708090a0b0c0d0e0f101112131415161718'), // 192-bit key
'output' => array(
array('offset' => 0, 'result' => '0595e57fe5f0bb3c706edac8a4b2db11'),
array('offset' => 16, 'result' => 'dfde31344a1af769c74f070aee9e2326'),
array('offset' => 240, 'result' => 'b06b9b1e195d13d8f4a7995c4553ac05'),
array('offset' => 256, 'result' => '6bd2378ec341c9a42f37ba79f88a32ff'),
array('offset' => 496, 'result' => 'e70bce1df7645adb5d2c4130215c3522'),
array('offset' => 512, 'result' => '9a5730c7fcb4c9af51ffda89c7f1ad22'),
array('offset' => 752, 'result' => '0485055fd4f6f0d963ef5ab9a5476982'),
array('offset' => 768, 'result' => '591fc66bcda10e452b03d4551f6b62ac'),
array('offset' => 1008, 'result' => '2753cc83988afa3e1688a1d3b42c9a02'),
array('offset' => 1024, 'result' => '93610d523d1d3f0062b3c2a3bbc7c7f0'),
array('offset' => 1520, 'result' => '96c248610aadedfeaf8978c03de8205a'),
array('offset' => 1536, 'result' => '0e317b3d1c73b9e9a4688f296d133a19'),
array('offset' => 2032, 'result' => 'bdf0e6c3cca5b5b9d533b69c56ada120'),
array('offset' => 2048, 'result' => '88a218b6e2ece1e6246d44c759d19b10'),
array('offset' => 3056, 'result' => '6866397e95c140534f94263421006e40'),
array('offset' => 3072, 'result' => '32cb0a1e9542c6b3b8b398abc3b0f1d5'),
array('offset' => 4080, 'result' => '29a0b8aed54a132324c62e423f54b4c8'),
array('offset' => 4096, 'result' => '3cb0f3b5020a98b82af9fe154484a168')
)
),
array(
'key' => pack('H*', '0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'), // 256-bit key
'output' => array(
array('offset' => 0, 'result' => 'eaa6bd25880bf93d3f5d1e4ca2611d91'),
array('offset' => 16, 'result' => 'cfa45c9f7e714b54bdfa80027cb14380'),
array('offset' => 240, 'result' => '114ae344ded71b35f2e60febad727fd8'),
array('offset' => 256, 'result' => '02e1e7056b0f623900496422943e97b6'),
array('offset' => 496, 'result' => '91cb93c787964e10d9527d999c6f936b'),
array('offset' => 512, 'result' => '49b18b42f8e8367cbeb5ef104ba1c7cd'),
array('offset' => 752, 'result' => '87084b3ba700bade955610672745b374'),
array('offset' => 768, 'result' => 'e7a7b9e9ec540d5ff43bdb12792d1b35'),
array('offset' => 1008, 'result' => 'c799b596738f6b018c76c74b1759bd90'),
array('offset' => 1024, 'result' => '7fec5bfd9f9b89ce6548309092d7e958'),
array('offset' => 1520, 'result' => '40f250b26d1f096a4afd4c340a588815'),
array('offset' => 1536, 'result' => '3e34135c79db010200767651cf263073'),
array('offset' => 2032, 'result' => 'f656abccf88dd827027b2ce917d464ec'),
array('offset' => 2048, 'result' => '18b62503bfbc077fbabb98f20d98ab34'),
array('offset' => 3056, 'result' => '8aed95ee5b0dcbfbef4eb21d3a3f52f9'),
array('offset' => 3072, 'result' => '625a1ab00ee39a5327346bddb01a9c18'),
array('offset' => 4080, 'result' => 'a13a7c79c7e119b5ab0296ab28c300b9'),
array('offset' => 4096, 'result' => 'f3e4c0a2e02d1d01f7f0a74618af2b48')
)
)
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName)
foreach ($tests as $test)
foreach ($test['output'] as $output)
$result[] = array($engine, $engineName, $test['key'], $output['offset'], $output['result']);
// @codingStandardsIgnoreEnd
return $result;
}
/**
* @dataProvider engineVectors
*/
public function testVectors($engine, $engineName, $key, $offset, $expected)
{
$rc4 = new RC4();
$rc4->setPreferredEngine($engine);
$rc4->setKey($key);
if ($rc4->getEngine() != $engine) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine for ' . (strlen($key) * 8) . '-bit key');
}
$result = $rc4->encrypt(str_repeat("\0", $offset + 16));
$this->assertEquals(bin2hex(substr($result, -16)), $expected, "Failed asserting that key $key yielded expected output at offset $offset in $engineName engine");
}
}

View File

@ -0,0 +1,183 @@
<?php
/**
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\TripleDES;
class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
{
var $engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENGINE_OPENSSL => 'OpenSSL',
);
public function engineVectors()
{
// tests from http://csrc.nist.gov/publications/nistpubs/800-20/800-20.pdf#page=273
$tests = array(
// Table A.1
// key, plaintext, ciphertext
array(str_repeat("\x01", 24), pack('H*', '8000000000000000'), pack('H*', '95F8A5E5DD31D900')),
array(str_repeat("\x01", 24), pack('H*', '4000000000000000'), pack('H*', 'DD7F121CA5015619')),
array(str_repeat("\x01", 24), pack('H*', '2000000000000000'), pack('H*', '2E8653104F3834EA')),
array(str_repeat("\x01", 24), pack('H*', '1000000000000000'), pack('H*', '4BD388FF6CD81D4F')),
array(str_repeat("\x01", 24), pack('H*', '0800000000000000'), pack('H*', '20B9E767B2FB1456')),
array(str_repeat("\x01", 24), pack('H*', '0400000000000000'), pack('H*', '55579380D77138EF')),
array(str_repeat("\x01", 24), pack('H*', '0200000000000000'), pack('H*', '6CC5DEFAAF04512F')),
array(str_repeat("\x01", 24), pack('H*', '0100000000000000'), pack('H*', '0D9F279BA5D87260')),
array(str_repeat("\x01", 24), pack('H*', '0080000000000000'), pack('H*', 'D9031B0271BD5A0A')),
array(str_repeat("\x01", 24), pack('H*', '0040000000000000'), pack('H*', '424250B37C3DD951')),
array(str_repeat("\x01", 24), pack('H*', '0020000000000000'), pack('H*', 'B8061B7ECD9A21E5')),
array(str_repeat("\x01", 24), pack('H*', '0010000000000000'), pack('H*', 'F15D0F286B65BD28')),
array(str_repeat("\x01", 24), pack('H*', '0008000000000000'), pack('H*', 'ADD0CC8D6E5DEBA1')),
array(str_repeat("\x01", 24), pack('H*', '0004000000000000'), pack('H*', 'E6D5F82752AD63D1')),
array(str_repeat("\x01", 24), pack('H*', '0002000000000000'), pack('H*', 'ECBFE3BD3F591A5E')),
array(str_repeat("\x01", 24), pack('H*', '0001000000000000'), pack('H*', 'F356834379D165CD')),
array(str_repeat("\x01", 24), pack('H*', '0000800000000000'), pack('H*', '2B9F982F20037FA9')),
array(str_repeat("\x01", 24), pack('H*', '0000400000000000'), pack('H*', '889DE068A16F0BE6')),
array(str_repeat("\x01", 24), pack('H*', '0000200000000000'), pack('H*', 'E19E275D846A1298')),
array(str_repeat("\x01", 24), pack('H*', '0000100000000000'), pack('H*', '329A8ED523D71AEC')),
array(str_repeat("\x01", 24), pack('H*', '0000080000000000'), pack('H*', 'E7FCE22557D23C97')),
array(str_repeat("\x01", 24), pack('H*', '0000040000000000'), pack('H*', '12A9F5817FF2D65D')),
array(str_repeat("\x01", 24), pack('H*', '0000020000000000'), pack('H*', 'A484C3AD38DC9C19')),
array(str_repeat("\x01", 24), pack('H*', '0000010000000000'), pack('H*', 'FBE00A8A1EF8AD72')),
array(str_repeat("\x01", 24), pack('H*', '0000008000000000'), pack('H*', '750D079407521363')),
array(str_repeat("\x01", 24), pack('H*', '0000004000000000'), pack('H*', '64FEED9C724C2FAF')),
array(str_repeat("\x01", 24), pack('H*', '0000002000000000'), pack('H*', 'F02B263B328E2B60')),
array(str_repeat("\x01", 24), pack('H*', '0000001000000000'), pack('H*', '9D64555A9A10B852')),
array(str_repeat("\x01", 24), pack('H*', '0000000800000000'), pack('H*', 'D106FF0BED5255D7')),
array(str_repeat("\x01", 24), pack('H*', '0000000400000000'), pack('H*', 'E1652C6B138C64A5')),
array(str_repeat("\x01", 24), pack('H*', '0000000200000000'), pack('H*', 'E428581186EC8F46')),
array(str_repeat("\x01", 24), pack('H*', '0000000100000000'), pack('H*', 'AEB5F5EDE22D1A36')),
array(str_repeat("\x01", 24), pack('H*', '0000000080000000'), pack('H*', 'E943D7568AEC0C5C')),
array(str_repeat("\x01", 24), pack('H*', '0000000040000000'), pack('H*', 'DF98C8276F54B04B')),
array(str_repeat("\x01", 24), pack('H*', '0000000020000000'), pack('H*', 'B160E4680F6C696F')),
array(str_repeat("\x01", 24), pack('H*', '0000000010000000'), pack('H*', 'FA0752B07D9C4AB8')),
array(str_repeat("\x01", 24), pack('H*', '0000000008000000'), pack('H*', 'CA3A2B036DBC8502')),
array(str_repeat("\x01", 24), pack('H*', '0000000004000000'), pack('H*', '5E0905517BB59BCF')),
array(str_repeat("\x01", 24), pack('H*', '0000000002000000'), pack('H*', '814EEB3B91D90726')),
array(str_repeat("\x01", 24), pack('H*', '0000000001000000'), pack('H*', '4D49DB1532919C9F')),
array(str_repeat("\x01", 24), pack('H*', '0000000000800000'), pack('H*', '25EB5FC3F8CF0621')),
array(str_repeat("\x01", 24), pack('H*', '0000000000400000'), pack('H*', 'AB6A20C0620D1C6F')),
array(str_repeat("\x01", 24), pack('H*', '0000000000200000'), pack('H*', '79E90DBC98F92CCA')),
array(str_repeat("\x01", 24), pack('H*', '0000000000100000'), pack('H*', '866ECEDD8072BB0E')),
array(str_repeat("\x01", 24), pack('H*', '0000000000080000'), pack('H*', '8B54536F2F3E64A8')),
array(str_repeat("\x01", 24), pack('H*', '0000000000040000'), pack('H*', 'EA51D3975595B86B')),
array(str_repeat("\x01", 24), pack('H*', '0000000000020000'), pack('H*', 'CAFFC6AC4542DE31')),
array(str_repeat("\x01", 24), pack('H*', '0000000000010000'), pack('H*', '8DD45A2DDF90796C')),
array(str_repeat("\x01", 24), pack('H*', '0000000000008000'), pack('H*', '1029D55E880EC2D0')),
array(str_repeat("\x01", 24), pack('H*', '0000000000004000'), pack('H*', '5D86CB23639DBEA9')),
array(str_repeat("\x01", 24), pack('H*', '0000000000002000'), pack('H*', '1D1CA853AE7C0C5F')),
array(str_repeat("\x01", 24), pack('H*', '0000000000001000'), pack('H*', 'CE332329248F3228')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000800'), pack('H*', '8405D1ABE24FB942')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000400'), pack('H*', 'E643D78090CA4207')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000200'), pack('H*', '48221B9937748A23')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000100'), pack('H*', 'DD7C0BBD61FAFD54')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000080'), pack('H*', '2FBC291A570DB5C4')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000040'), pack('H*', 'E07C30D7E4E26E12')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000020'), pack('H*', '0953E2258E8E90A1')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000010'), pack('H*', '5B711BC4CEEBF2EE')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000008'), pack('H*', 'CC083F1E6D9E85F6')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000004'), pack('H*', 'D2FD8867D50D2DFE')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000002'), pack('H*', '06E7EA22CE92708F')),
array(str_repeat("\x01", 24), pack('H*', '0000000000000001'), pack('H*', '166B40B44ABA4BD6'))
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($this->engines as $engine => $engineName)
foreach ($tests as $test)
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2]);
// @codingStandardsIgnoreEnd
return $result;
}
/**
* @dataProvider engineVectors
*/
public function testVectors($engine, $engineName, $key, $plaintext, $expected)
{
$des = new TripleDES();
if (!$des->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
}
$des->setPreferredEngine($engine);
$des->setKey($key);
$des->disablePadding();
$result = $des->encrypt($plaintext);
$plaintext = bin2hex($plaintext);
$this->assertEquals($result, $expected, "Failed asserting that $plaintext yielded expected output in $engineName engine");
}
public function engineIVVectors()
{
$engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENGINE_OPENSSL => 'OpenSSL',
);
// tests from http://csrc.nist.gov/groups/STM/cavp/documents/des/DESMMT.pdf
$tests = array(
// key, iv, plaintext, ciphertext
array(
pack('H*', '627f460e08104a10' . '43cd265d5840eaf1' . '313edf97df2a8a8c'),
pack('H*', '8e29f75ea77e5475'),
pack('H*', '326a494cd33fe756'),
pack('H*', 'b22b8d66de970692')),
array(
pack('H*', '37ae5ebf46dff2dc' . '0754b94f31cbb385' . '5e7fd36dc870bfae'),
pack('H*', '3d1de3cc132e3b65'),
pack('H*', '84401f78fe6c10876d8ea23094ea5309'),
pack('H*', '7b1f7c7e3b1c948ebd04a75ffba7d2f5'))
);
$result = array();
// @codingStandardsIgnoreStart
foreach ($engines as $engine => $engineName)
foreach ($tests as $test)
$result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]);
// @codingStandardsIgnoreEnd
return $result;
}
/**
* @dataProvider engineIVVectors
*/
public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected)
{
$des = new TripleDES();
if (!$des->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
}
$des->setPreferredEngine($engine);
$des->setKey($key);
$des->setIV($iv);
$des->disablePadding();
$result = $des->encrypt($plaintext);
$plaintext = bin2hex($plaintext);
$this->assertEquals($result, $expected, "Failed asserting that $plaintext yielded expected output in $engineName engine");
}
public function testInnerChaining()
{
// regular CBC returns
// e089b6d84708c6bc80be6c2da82bd19a79ffe11f02933ac1
$expected = 'e089b6d84708c6bc6f04c8971121603d7be2861efae0f3f5';
$des = new TripleDES(TripleDES::MODE_3CBC);
$des->setKey('abcdefghijklmnopqrstuvwx');
foreach ($this->engines as $engine => $engineName) {
$des->setPreferredEngine($engine);
if (!$des->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $engineName . ' engine');
}
$result = bin2hex($des->encrypt(str_repeat('a', 16)));
$this->assertEquals($result, $expected, "Failed asserting inner chainin worked correctly in $engineName engine");
}
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use phpseclib\Crypt\Base;
use phpseclib\Crypt\Twofish;
class Unit_Crypt_TwofishTest extends PhpseclibTestCase
{
public function testVectors()
{
$engines = array(
Base::ENGINE_INTERNAL => 'internal',
Base::ENGINE_MCRYPT => 'mcrypt',
Base::ENGINE_OPENSSL => 'OpenSSL',
);
foreach ($engines as $engine=>$name) {
$tf = new Twofish();
$tf->disablePadding();
// tests from https://www.schneier.com/code/ecb_ival.txt
// key size = 128
$key = pack('H*', '00000000000000000000000000000000');
$tf->setKey($key);
if (!$tf->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $name . ' engine');
}
$plaintext = pack('H*', '00000000000000000000000000000000');
$ciphertext = $tf->encrypt($plaintext);
$expected = strtolower('9F589F5CF6122C32B6BFEC2F2AE8C35A');
$this->assertEquals(bin2hex($ciphertext), $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
$expected = bin2hex($plaintext);
$plaintext = bin2hex($tf->decrypt($ciphertext));
$this->assertEquals($plaintext, $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
// key size = 192
$key = pack('H*', '0123456789ABCDEFFEDCBA98765432100011223344556677');
$tf->setKey($key);
if (!$tf->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $name . ' engine');
}
$plaintext = pack('H*', '00000000000000000000000000000000');
$ciphertext = $tf->encrypt($plaintext);
$expected = strtolower('CFD1D2E5A9BE9CDF501F13B892BD2248');
$this->assertEquals(bin2hex($ciphertext), $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
$expected = bin2hex($plaintext);
$plaintext = bin2hex($tf->decrypt($ciphertext));
$this->assertEquals($plaintext, $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
// key size = 256
$key = pack('H*', '0123456789ABCDEFFEDCBA987654321000112233445566778899AABBCCDDEEFF');
$tf->setKey($key);
if (!$tf->isValidEngine($engine)) {
self::markTestSkipped('Unable to initialize ' . $name . ' engine');
}
$plaintext = pack('H*', '00000000000000000000000000000000');
$ciphertext = $tf->encrypt($plaintext);
$expected = strtolower('37527BE0052334B89F0CFCCAE87CFA20');
$this->assertEquals(bin2hex($ciphertext), $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
$expected = bin2hex($plaintext);
$plaintext = bin2hex($tf->decrypt($ciphertext));
$this->assertEquals($plaintext, $expected, "Failed asserting that $plaintext yielded expected output in $name engine");
}
}
}

View File

@ -41,9 +41,14 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase
$identifier = $this->createSSHMock()->_generate_identifier();
$this->assertStringStartsWith('SSH-2.0-phpseclib_0.3', $identifier);
if (extension_loaded('mcrypt')) {
if (extension_loaded('openssl')) {
$this->assertContains('openssl', $identifier);
$this->assertNotContains('mcrypt', $identifier);
} else if (extension_loaded('mcrypt')) {
$this->assertNotContains('openssl', $identifier);
$this->assertContains('mcrypt', $identifier);
} else {
$this->assertNotContains('openssl', $identifier);
$this->assertNotContains('mcrypt', $identifier);
}