Merge branch '1.0' into sftp-put-callback-for-1.0

This commit is contained in:
andrey012 2015-05-02 15:24:31 +03:00
commit f4a93c790f
37 changed files with 2529 additions and 1032 deletions

View File

@ -7,6 +7,10 @@
* *
* PHP versions 4 and 5 * 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 Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits * {@link 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 Crypt_AES::setKey() setKey()} * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
@ -107,20 +111,6 @@ define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of AES. * Pure-PHP implementation of AES.
* *
@ -201,7 +191,7 @@ class Crypt_AES extends Crypt_Rijndael
default: default:
$this->key_size = 32; $this->key_size = 32;
} }
$this->_setupEngine(); $this->_setEngine();
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -101,20 +101,6 @@ define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_BLOWFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of Blowfish. * Pure-PHP implementation of Blowfish.
* *
@ -174,7 +160,7 @@ class Crypt_Blowfish extends Crypt_Base
/** /**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
* *
* S-Box 1 * S-Box 0
* *
* @access private * @access private
* @var array * @var array
@ -340,7 +326,7 @@ class Crypt_Blowfish extends Crypt_Base
/** /**
* P-Array consists of 18 32-bit subkeys * P-Array consists of 18 32-bit subkeys
* *
* @var array $parray * @var array
* @access private * @access private
*/ */
var $parray = array( var $parray = array(
@ -354,7 +340,7 @@ class Crypt_Blowfish extends Crypt_Base
* *
* Holds the expanded key [p] and the key-depended s-boxes [sb] * Holds the expanded key [p] and the key-depended s-boxes [sb]
* *
* @var array $bctx * @var array
* @access private * @access private
*/ */
var $bctx; var $bctx;
@ -395,6 +381,29 @@ class Crypt_Blowfish extends Crypt_Base
parent::setKey($key); parent::setKey($key);
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_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) * Setup the key (expansion)
* *
@ -472,17 +481,17 @@ class Crypt_Blowfish extends Crypt_Base
$r = $in[2]; $r = $in[2];
for ($i = 0; $i < 16; $i+= 2) { for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i]; $l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] + $r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^ $sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) + $sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff]; $sb_3[$l & 0xff];
$r^= $p[$i + 1]; $r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] + $l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^ $sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) + $sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]; $sb_3[$r & 0xff];
} }
return pack("N*", $r ^ $p[17], $l ^ $p[16]); return pack("N*", $r ^ $p[17], $l ^ $p[16]);
} }
@ -519,7 +528,6 @@ class Crypt_Blowfish extends Crypt_Base
$sb_2[$r >> 8 & 0xff]) + $sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff]; $sb_3[$r & 0xff];
} }
return pack("N*", $r ^ $p[0], $l ^ $p[1]); return pack("N*", $r ^ $p[0], $l ^ $p[1]);
} }
@ -534,15 +542,14 @@ class Crypt_Blowfish extends Crypt_Base
$lambda_functions =& Crypt_Blowfish::_getLambdaFunctions(); $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // 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. // 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) { // Generation of a unique hash for our generated code
case $gen_hi_opt_code: $code_hash = "Crypt_Blowfish, {$this->mode}";
$code_hash = md5(str_pad("Crypt_Blowfish, {$this->mode}, ", 32, "\0") . $this->key); if ($gen_hi_opt_code) {
break; $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
default:
$code_hash = "Crypt_Blowfish, {$this->mode}";
} }
if (!isset($lambda_functions[$code_hash])) { if (!isset($lambda_functions[$code_hash])) {

View File

@ -121,20 +121,6 @@ define('CRYPT_DES_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_DES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_DES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of DES. * Pure-PHP implementation of DES.
* *
@ -191,6 +177,21 @@ class Crypt_DES extends Crypt_Base
*/ */
var $cipher_name_mcrypt = 'des'; var $cipher_name_mcrypt = 'des';
/**
* The OpenSSL names of the cipher / modes
*
* @see Crypt_Base::openssl_mode_names
* @var Array
* @access private
*/
var $openssl_mode_names = array(
CRYPT_MODE_ECB => 'des-ecb',
CRYPT_MODE_CBC => 'des-cbc',
CRYPT_MODE_CFB => 'des-cfb',
CRYPT_MODE_OFB => 'des-ofb'
// CRYPT_MODE_CTR is undefined for DES
);
/** /**
* Optimizing value while CFB-encrypting * Optimizing value while CFB-encrypting
* *
@ -661,6 +662,28 @@ class Crypt_DES extends Crypt_Base
0x00000820, 0x00020020, 0x08000000, 0x08020800 0x00000820, 0x00020020, 0x08000000, 0x08020800
); );
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::isValidEngine()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($this->key_size_max == 8) {
if ($engine == CRYPT_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. * Sets the key.
* *
@ -1358,21 +1381,20 @@ class Crypt_DES extends Crypt_Base
$des_rounds = $this->des_rounds; $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. // 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 // 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 );
// Generation of a uniqe hash for our generated code // Generation of a uniqe hash for our generated code
switch (true) { $code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
case $gen_hi_opt_code: if ($gen_hi_opt_code) {
// For hi-optimized code, we create for each combination of // For hi-optimized code, we create for each combination of
// $mode, $des_rounds and $this->key its own encrypt/decrypt function. // $mode, $des_rounds and $this->key its own encrypt/decrypt function.
$code_hash = md5(str_pad("Crypt_DES, $des_rounds, {$this->mode}, ", 32, "\0") . $this->key); // After max 10 hi-optimized functions, we create generic
break; // (still very fast.. but not ultra) functions for each $mode/$des_rounds
default: // Currently 2 * 5 generic functions will be then max. possible.
// After max 10 hi-optimized functions, we create generic $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
// Currently 2 * 5 generic functions will be then max. possible.
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
} }
// Is there a re-usable $lambda_functions in there? If not, we have to create it. // Is there a re-usable $lambda_functions in there? If not, we have to create it.

View File

@ -99,20 +99,6 @@ define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_RC2::Crypt_RC2()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC2_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of RC2. * Pure-PHP implementation of RC2.
* *
@ -138,7 +124,19 @@ class Crypt_RC2 extends Crypt_Base
* @var String * @var String
* @access private * @access private
*/ */
var $key = "\0"; var $key;
/**
* The Original (unpadded) Key
*
* @see Crypt_Base::key
* @see setKey()
* @see encrypt()
* @see decrypt()
* @var String
* @access private
*/
var $orig_key;
/** /**
* The default password key_size used by setPassword() * The default password key_size used by setPassword()
@ -189,6 +187,17 @@ class Crypt_RC2 extends Crypt_Base
*/ */
var $default_key_length = 1024; var $default_key_length = 1024;
/**
* The key length in bits.
*
* @see Crypt_RC2::isValidEnine()
* @see Crypt_RC2::setKey()
* @var Integer
* @access private
* @internal Should be in range [1..1024].
*/
var $current_key_length;
/** /**
* The Key Schedule * The Key Schedule
* *
@ -341,7 +350,30 @@ class Crypt_RC2 extends Crypt_Base
function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC) function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC)
{ {
parent::Crypt_Base($mode); parent::Crypt_Base($mode);
$this->setKey(''); }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_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);
} }
/** /**
@ -375,15 +407,18 @@ class Crypt_RC2 extends Crypt_Base
* @see Crypt_Base::setKey() * @see Crypt_Base::setKey()
* @access public * @access public
* @param String $key * @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) function setKey($key, $t1 = 0)
{ {
$this->orig_key = $key;
if ($t1 <= 0) { if ($t1 <= 0) {
$t1 = $this->default_key_length; $t1 = $this->default_key_length;
} else if ($t1 > 1024) { } else if ($t1 > 1024) {
$t1 = 1024; $t1 = 1024;
} }
$this->current_key_length = $t1;
// Key byte count should be 1..128. // Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128) : "\x00"; $key = strlen($key) ? substr($key, 0, 128) : "\x00";
$t = strlen($key); $t = strlen($key);
@ -416,6 +451,52 @@ class Crypt_RC2 extends Crypt_Base
parent::setKey(call_user_func_array('pack', $l)); 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 == CRYPT_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 == CRYPT_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 * Encrypts a block
* *
@ -506,6 +587,21 @@ class Crypt_RC2 extends Crypt_Base
return pack('vvvv', $r0, $r1, $r2, $r3); return pack('vvvv', $r0, $r1, $r2, $r3);
} }
/**
* Setup the CRYPT_ENGINE_MCRYPT $engine
*
* @see Crypt_Base::_setupMcrypt()
* @access private
*/
function _setupMcrypt()
{
if (!isset($this->key)) {
$this->setKey('');
}
parent::_setupMcrypt();
}
/** /**
* Creates the key schedule * Creates the key schedule
* *
@ -514,6 +610,10 @@ class Crypt_RC2 extends Crypt_Base
*/ */
function _setupKey() function _setupKey()
{ {
if (!isset($this->key)) {
$this->setKey('');
}
// Key has already been expanded in Crypt_RC2::setKey(): // Key has already been expanded in Crypt_RC2::setKey():
// Only the first value must be altered. // Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key); $l = unpack('Ca/Cb/v*', $this->key);
@ -536,14 +636,14 @@ class Crypt_RC2 extends Crypt_Base
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers // The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster]. // 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. // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
$keys = $this->keys; // (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
if (count($lambda_functions) >= 10) { $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
$code_hash = md5(str_pad("Crypt_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? // Is there a re-usable $lambda_functions in there?
// If not, we have to create it. // If not, we have to create it.
@ -551,6 +651,16 @@ class Crypt_RC2 extends Crypt_Base
// Init code for both, encrypt and decrypt. // Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;'; $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 // $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = ' $encrypt_block = $decrypt_block = '
$in = unpack("v4", $in); $in = unpack("v4", $in);

View File

@ -69,20 +69,6 @@ if (!class_exists('Crypt_Base')) {
include_once 'Base.php'; include_once 'Base.php';
} }
/**#@+
* @access private
* @see Crypt_RC4::Crypt_RC4()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**#@+ /**#@+
* @access private * @access private
* @see Crypt_RC4::_crypt() * @see Crypt_RC4::_crypt()
@ -181,6 +167,38 @@ class Crypt_RC4 extends Crypt_Base
parent::Crypt_Base(CRYPT_MODE_STREAM); parent::Crypt_Base(CRYPT_MODE_STREAM);
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
switch ($engine) {
case CRYPT_ENGINE_OPENSSL:
switch (strlen($this->key)) {
case 5:
$this->cipher_name_openssl = 'rc4-40';
break;
case 8:
$this->cipher_name_openssl = 'rc4-64';
break;
case 16:
$this->cipher_name_openssl = 'rc4';
break;
default:
return false;
}
}
return parent::isValidEngine($engine);
}
/** /**
* Dummy function. * Dummy function.
* *
@ -230,7 +248,7 @@ class Crypt_RC4 extends Crypt_Base
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) { if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::encrypt($plaintext); return parent::encrypt($plaintext);
} }
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT); return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
@ -250,7 +268,7 @@ class Crypt_RC4 extends Crypt_Base
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) { if ($this->engine != CRYPT_ENGINE_INTERNAL) {
return parent::decrypt($ciphertext); return parent::decrypt($ciphertext);
} }
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT); return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);

File diff suppressed because it is too large Load Diff

View File

@ -59,19 +59,31 @@ if (!class_exists('Crypt_DES')) {
include_once 'DES.php'; include_once 'DES.php';
} }
/**#@+
* @access public
* @see Crypt_TripleDES::Crypt_TripleDES()
*/
/** /**
* Encrypt / decrypt using inner chaining * Encrypt / decrypt using inner chaining
* *
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3). * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
*/ */
define('CRYPT_MODE_3CBC', -2);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_3CBC', -2); define('CRYPT_DES_MODE_3CBC', -2);
/** /**
* Encrypt / decrypt using outer chaining * Encrypt / decrypt using outer chaining
* *
* Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC. * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
*/ */
define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC); define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC);
/**
* BC version of the above.
*/
define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3);
/**#@-*/
/** /**
* Pure-PHP implementation of Triple DES. * Pure-PHP implementation of Triple DES.
@ -186,20 +198,20 @@ class Crypt_TripleDES extends Crypt_DES
* @param optional Integer $mode * @param optional Integer $mode
* @access public * @access public
*/ */
function Crypt_TripleDES($mode = CRYPT_DES_MODE_CBC) function Crypt_TripleDES($mode = CRYPT_MODE_CBC)
{ {
switch ($mode) { switch ($mode) {
// In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC // In case of CRYPT_DES_MODE_3CBC, we init as CRYPT_DES_MODE_CBC
// and additional flag us internally as 3CBC // and additional flag us internally as 3CBC
case CRYPT_DES_MODE_3CBC: case CRYPT_DES_MODE_3CBC:
parent::Crypt_Base(CRYPT_DES_MODE_CBC); parent::Crypt_Base(CRYPT_MODE_CBC);
$this->mode_3cbc = true; $this->mode_3cbc = true;
// This three $des'es will do the 3CBC work (if $key > 64bits) // This three $des'es will do the 3CBC work (if $key > 64bits)
$this->des = array( $this->des = array(
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
new Crypt_DES(CRYPT_DES_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC),
); );
// we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects // we're going to be doing the padding, ourselves, so disable it in the Crypt_DES objects
@ -213,6 +225,27 @@ class Crypt_TripleDES extends Crypt_DES
} }
} }
/**
* Test for engine validity
*
* This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine()
*
* @see Crypt_Base::Crypt_Base()
* @param Integer $engine
* @access public
* @return Boolean
*/
function isValidEngine($engine)
{
if ($engine == CRYPT_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) * Sets the initialization vector. (optional)
* *
@ -255,7 +288,7 @@ class Crypt_TripleDES extends Crypt_DES
$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:
// http://php.net/function.mcrypt-encrypt#47973 // 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 { } else {
$key = str_pad($key, 8, chr(0)); $key = str_pad($key, 8, chr(0));
} }
@ -283,7 +316,7 @@ class Crypt_TripleDES extends Crypt_DES
function encrypt($plaintext) function encrypt($plaintext)
{ {
// parent::en/decrypt() is able to do all the work for all modes and keylengths, // parent::en/decrypt() is able to do all the work for all modes and keylengths,
// except for: CRYPT_DES_MODE_3CBC (inner chaining CBC) with a key > 64bits // except for: CRYPT_MODE_3CBC (inner chaining CBC) with a key > 64bits
// if the key is smaller then 8, do what we'd normally do // if the key is smaller then 8, do what we'd normally do
if ($this->mode_3cbc && strlen($this->key) > 8) { if ($this->mode_3cbc && strlen($this->key) > 8) {
@ -425,4 +458,24 @@ class Crypt_TripleDES extends Crypt_DES
// setup our key // setup our key
parent::_setupKey(); parent::_setupKey();
} }
/**
* Sets the internal crypt engine
*
* @see Crypt_Base::Crypt_Base()
* @see 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

@ -101,20 +101,6 @@ define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB); define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+
* @access private
* @see Crypt_Base::Crypt_Base()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_TWOFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/** /**
* Pure-PHP implementation of Twofish. * Pure-PHP implementation of Twofish.
* *
@ -754,21 +740,19 @@ class Crypt_Twofish extends Crypt_Base
$lambda_functions =& Crypt_Twofish::_getLambdaFunctions(); $lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one. // 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 ); $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) { // Generation of a uniqe hash for our generated code
case $gen_hi_opt_code: $code_hash = "Crypt_Twofish, {$this->mode}";
$code_hash = md5(str_pad("Crypt_Twofish, {$this->mode}, ", 32, "\0") . $this->key); if ($gen_hi_opt_code) {
break; $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
default:
$code_hash = "Crypt_Twofish, {$this->mode}";
} }
if (!isset($lambda_functions[$code_hash])) { if (!isset($lambda_functions[$code_hash])) {
switch (true) { switch (true) {
case $gen_hi_opt_code: case $gen_hi_opt_code:
$K = $this->K; $K = $this->K;
$init_crypt = ' $init_crypt = '
static $S0, $S1, $S2, $S3; static $S0, $S1, $S2, $S3;
if (!$S0) { if (!$S0) {
@ -786,7 +770,6 @@ class Crypt_Twofish extends Crypt_Base
for ($i = 0; $i < 40; ++$i) { for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i; $K[] = '$K_' . $i;
} }
$init_crypt = ' $init_crypt = '
$S0 = $self->S0; $S0 = $self->S0;
$S1 = $self->S1; $S1 = $self->S1;

View File

@ -17,7 +17,7 @@
* if (!$ssh->login('username', 'password')) { * if (!$ssh->login('username', 'password')) {
* exit('bad login'); * exit('bad login');
* } * }
*
* $scp = new Net_SCP($ssh); * $scp = new Net_SCP($ssh);
* $scp->put('abcd', str_repeat('x', 1024*1024)); * $scp->put('abcd', str_repeat('x', 1024*1024));
* ?> * ?>

View File

@ -1793,11 +1793,12 @@ class Net_SFTP extends Net_SSH2
* @param optional Integer $mode * @param optional Integer $mode
* @param optional Integer $start * @param optional Integer $start
* @param optional Integer $local_start * @param optional Integer $local_start
* @param optional callable|null $callback
* @return Boolean * @return Boolean
* @access public * @access public
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode(). * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode().
*/ */
function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1, $local_start = -1) function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1, $local_start = -1, $callback = null)
{ {
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
return false; return false;
@ -1911,6 +1912,9 @@ class Net_SFTP extends Net_SSH2
return false; return false;
} }
$sent+= strlen($temp); $sent+= strlen($temp);
if (is_callable($callback)) {
call_user_func($callback, $sent);
}
$i++; $i++;

View File

@ -826,6 +826,16 @@ class Net_SSH2
*/ */
var $windowRows = 24; var $windowRows = 24;
/**
* Crypto Engine
*
* @see Net_SSH2::setCryptoEngine()
* @see Net_SSH2::_key_exchange()
* @var Integer
* @access private
*/
var $crypto_engine = false;
/** /**
* A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
* *
@ -860,6 +870,11 @@ class Net_SSH2
include_once 'Crypt/Hash.php'; include_once 'Crypt/Hash.php';
} }
// include Crypt_Base so constants can be defined for setCryptoEngine()
if (!class_exists('Crypt_Base')) {
include_once 'Crypt/Base.php';
}
$this->message_numbers = array( $this->message_numbers = array(
1 => 'NET_SSH2_MSG_DISCONNECT', 1 => 'NET_SSH2_MSG_DISCONNECT',
2 => 'NET_SSH2_MSG_IGNORE', 2 => 'NET_SSH2_MSG_IGNORE',
@ -935,6 +950,20 @@ class Net_SSH2
$this->timeout = $timeout; $this->timeout = $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 * Connect to an SSHv2 server
* *
@ -1065,7 +1094,9 @@ class Net_SSH2
$identifier = 'SSH-2.0-phpseclib_0.3'; $identifier = 'SSH-2.0-phpseclib_0.3';
$ext = array(); $ext = array();
if (extension_loaded('mcrypt')) { if (extension_loaded('openssl')) {
$ext[] = 'openssl';
} elseif (extension_loaded('mcrypt')) {
$ext[] = 'mcrypt'; $ext[] = 'mcrypt';
} }
@ -1107,7 +1138,7 @@ class Net_SSH2
'arcfour256', 'arcfour256',
'arcfour128', '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>: // CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key
@ -1135,9 +1166,18 @@ class Net_SSH2
'3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode
'3des-cbc', // REQUIRED three-key 3DES in CBC 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 (phpseclib_resolve_include_path('Crypt/RC4.php') === false) { if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) {
$encryption_algorithms = array_diff( $encryption_algorithms = array_diff(
$encryption_algorithms, $encryption_algorithms,
@ -1649,6 +1689,9 @@ class Net_SSH2
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
if ($this->encrypt) { if ($this->encrypt) {
if ($this->crypto_engine) {
$this->encrypt->setEngine($this->crypto_engine);
}
$this->encrypt->enableContinuousBuffer(); $this->encrypt->enableContinuousBuffer();
$this->encrypt->disablePadding(); $this->encrypt->disablePadding();
@ -1666,6 +1709,9 @@ class Net_SSH2
} }
if ($this->decrypt) { if ($this->decrypt) {
if ($this->crypto_engine) {
$this->decrypt->setEngine($this->crypto_engine);
}
$this->decrypt->enableContinuousBuffer(); $this->decrypt->enableContinuousBuffer();
$this->decrypt->disablePadding(); $this->decrypt->disablePadding();

View File

@ -15,17 +15,10 @@ class Functional_Net_SFTPLargeFileTest extends PhpseclibFunctionalTestCase
static public function setUpBeforeClass() static public function setUpBeforeClass()
{ {
if (!extension_loaded('mcrypt')) { if (!extension_loaded('mcrypt') && !extension_loaded('openssl')) {
self::markTestSkipped('This test depends on mcrypt for performance.'); self::markTestSkipped('This test depends on mcrypt or openssl for performance.');
} }
parent::setUpBeforeClass(); parent::setUpBeforeClass();
self::ensureConstant('CRYPT_AES_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_BLOWFISH_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_DES_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_RC2_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_RC4_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', CRYPT_MODE_MCRYPT);
self::ensureConstant('CRYPT_TWOFISH_MODE', CRYPT_MODE_MCRYPT);
} }
public function setUp() public function setUp()
@ -51,10 +44,10 @@ class Functional_Net_SFTPLargeFileTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @group github298 * @group github298
* @group github455 * @group github455
* @group github457 * @group github457
*/ */
public function testPutSizeLocalFile() public function testPutSizeLocalFile()
{ {
$tmp_filename = $this->createTempFile(128, 1024 * 1024); $tmp_filename = $this->createTempFile(128, 1024 * 1024);

View File

@ -36,8 +36,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testConstructor * @depends testConstructor
*/ */
public function testPasswordLogin($sftp) public function testPasswordLogin($sftp)
{ {
$username = $this->getEnv('SSH_USERNAME'); $username = $this->getEnv('SSH_USERNAME');
@ -51,8 +51,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testPasswordLogin * @depends testPasswordLogin
*/ */
public function testPwdHome($sftp) public function testPwdHome($sftp)
{ {
$this->assertEquals( $this->assertEquals(
@ -65,8 +65,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testPwdHome * @depends testPwdHome
*/ */
public function testMkDirScratch($sftp) public function testMkDirScratch($sftp)
{ {
$dirname = self::$scratchDir; $dirname = self::$scratchDir;
@ -87,8 +87,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testMkDirScratch * @depends testMkDirScratch
*/ */
public function testChDirScratch($sftp) public function testChDirScratch($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -120,8 +120,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testChDirScratch * @depends testChDirScratch
*/ */
public function testStatOnDir($sftp) public function testStatOnDir($sftp)
{ {
$this->assertNotSame( $this->assertNotSame(
@ -169,8 +169,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
/** /**
* @depends testStatOnDir * @depends testStatOnDir
*/ */
public function testPutSizeGetFile($sftp) public function testPutSizeGetFile($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -194,8 +194,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testPutSizeGetFile * @depends testPutSizeGetFile
*/ */
public function testTouch($sftp) public function testTouch($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -212,8 +212,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testTouch * @depends testTouch
*/ */
public function testTruncate($sftp) public function testTruncate($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -236,8 +236,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testTruncate * @depends testTruncate
*/ */
public function testChDirOnFile($sftp) public function testChDirOnFile($sftp)
{ {
$this->assertFalse( $this->assertFalse(
@ -249,8 +249,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testChDirOnFile * @depends testChDirOnFile
*/ */
public function testFileExistsIsFileIsDirFile($sftp) public function testFileExistsIsFileIsDirFile($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -272,8 +272,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testFileExistsIsFileIsDirFile * @depends testFileExistsIsFileIsDirFile
*/ */
public function testFileExistsIsFileIsDirFileNonexistent($sftp) public function testFileExistsIsFileIsDirFileNonexistent($sftp)
{ {
$this->assertFalse( $this->assertFalse(
@ -295,8 +295,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testFileExistsIsFileIsDirFileNonexistent * @depends testFileExistsIsFileIsDirFileNonexistent
*/ */
public function testSortOrder($sftp) public function testSortOrder($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -347,8 +347,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testSortOrder * @depends testSortOrder
*/ */
public function testResourceXfer($sftp) public function testResourceXfer($sftp)
{ {
$fp = fopen('res.txt', 'w+'); $fp = fopen('res.txt', 'w+');
@ -367,8 +367,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testResourceXfer * @depends testResourceXfer
*/ */
public function testSymlink($sftp) public function testSymlink($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -380,8 +380,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testSymlink * @depends testSymlink
*/ */
public function testReadlink($sftp) public function testReadlink($sftp)
{ {
$this->assertInternalType('string', $sftp->readlink('symlink'), $this->assertInternalType('string', $sftp->readlink('symlink'),
@ -392,10 +392,10 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* on older versions this would result in a fatal error * on older versions this would result in a fatal error
* @depends testReadlink * @depends testReadlink
* @group github402 * @group github402
*/ */
public function testStatcacheFix($sftp) public function testStatcacheFix($sftp)
{ {
// Name used for both directory and file. // Name used for both directory and file.
@ -417,8 +417,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testStatcacheFix * @depends testStatcacheFix
*/ */
public function testChDirUpHome($sftp) public function testChDirUpHome($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -436,8 +436,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testChDirUpHome * @depends testChDirUpHome
*/ */
public function testFileExistsIsFileIsDirDir($sftp) public function testFileExistsIsFileIsDirDir($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -459,8 +459,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testFileExistsIsFileIsDirDir * @depends testFileExistsIsFileIsDirDir
*/ */
public function testTruncateLargeFile($sftp) public function testTruncateLargeFile($sftp)
{ {
$filesize = (4 * 1024 + 16) * 1024 * 1024; $filesize = (4 * 1024 + 16) * 1024 * 1024;
@ -473,8 +473,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testTruncateLargeFile * @depends testTruncateLargeFile
*/ */
public function testRmDirScratch($sftp) public function testRmDirScratch($sftp)
{ {
$this->assertFalse( $this->assertFalse(
@ -487,8 +487,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testRmDirScratch * @depends testRmDirScratch
*/ */
public function testDeleteRecursiveScratch($sftp) public function testDeleteRecursiveScratch($sftp)
{ {
$this->assertTrue( $this->assertTrue(
@ -501,8 +501,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testDeleteRecursiveScratch * @depends testDeleteRecursiveScratch
*/ */
public function testRmDirScratchNonexistent($sftp) public function testRmDirScratchNonexistent($sftp)
{ {
$this->assertFalse( $this->assertFalse(

View File

@ -21,10 +21,10 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testConstructor * @depends testConstructor
* @group github408 * @group github408
* @group github412 * @group github412
*/ */
public function testPreLogin($ssh) public function testPreLogin($ssh)
{ {
$this->assertFalse( $this->assertFalse(
@ -51,8 +51,8 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testPreLogin * @depends testPreLogin
*/ */
public function testPasswordLogin($ssh) public function testPasswordLogin($ssh)
{ {
$username = $this->getEnv('SSH_USERNAME'); $username = $this->getEnv('SSH_USERNAME');
@ -66,9 +66,9 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase
} }
/** /**
* @depends testPasswordLogin * @depends testPasswordLogin
* @group github280 * @group github280
*/ */
public function testExecWithMethodCallback($ssh) public function testExecWithMethodCallback($ssh)
{ {
$callbackObject = $this->getMock('stdClass', array('callbackMethod')); $callbackObject = $this->getMock('stdClass', array('callbackMethod'));

View File

@ -33,11 +33,11 @@ abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase
} }
/** /**
* @param string $variable * @param string $variable
* @param string|null $message * @param string|null $message
* *
* @return null * @return null
*/ */
protected function requireEnv($variable, $message = null) protected function requireEnv($variable, $message = null)
{ {
if ($this->_getEnv($variable) === false) { if ($this->_getEnv($variable) === false) {
@ -50,10 +50,10 @@ abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase
} }
/** /**
* @param string $variable * @param string $variable
* *
* @return string * @return string
*/ */
protected function getEnv($variable) protected function getEnv($variable)
{ {
$this->requireEnv($variable); $this->requireEnv($variable);

View File

@ -20,17 +20,17 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase
} }
/** /**
* Creates a temporary file on the local filesystem and returns its path. * Creates a temporary file on the local filesystem and returns its path.
* The $number_of_writes and $bytes_per_write parameters can be used to * The $number_of_writes and $bytes_per_write parameters can be used to
* write $number_of_writes * $bytes_per_write times the character 'a' to the * write $number_of_writes * $bytes_per_write times the character 'a' to the
* temporary file. All files created using this method will be deleted from * temporary file. All files created using this method will be deleted from
* the filesystem on tearDown(), i.e. after each test method was run. * the filesystem on tearDown(), i.e. after each test method was run.
* *
* @param int $number_of_writes * @param int $number_of_writes
* @param int $bytes_per_write * @param int $bytes_per_write
* *
* @return string * @return string
*/ */
protected function createTempFile($number_of_writes = 0, $bytes_per_write = 0) protected function createTempFile($number_of_writes = 0, $bytes_per_write = 0)
{ {
$filename = tempnam(sys_get_temp_dir(), 'phpseclib-test-'); $filename = tempnam(sys_get_temp_dir(), 'phpseclib-test-');
@ -48,11 +48,11 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase
} }
/** /**
* @param string $constant * @param string $constant
* @param mixed $expected * @param mixed $expected
* *
* @return null * @return null
*/ */
static protected function ensureConstant($constant, $expected) static protected function ensureConstant($constant, $expected)
{ {
if (defined($constant)) { if (defined($constant)) {
@ -82,10 +82,10 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase
} }
/** /**
* @param string $filename * @param string $filename
* *
* @return null * @return null
*/ */
static protected function reRequireFile($filename) static protected function reRequireFile($filename)
{ {
if (function_exists('runkit_import')) { if (function_exists('runkit_import')) {

View File

@ -7,11 +7,8 @@
class Unit_Crypt_AES_InternalTest extends Unit_Crypt_AES_TestCase class Unit_Crypt_AES_InternalTest extends Unit_Crypt_AES_TestCase
{ {
static public function setUpBeforeClass() protected function setUp()
{ {
parent::setUpBeforeClass(); $this->engine = CRYPT_ENGINE_INTERNAL;
self::ensureConstant('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', CRYPT_RIJNDAEL_MODE_INTERNAL);
} }
} }

View File

@ -7,15 +7,8 @@
class Unit_Crypt_AES_McryptTest extends Unit_Crypt_AES_TestCase class Unit_Crypt_AES_McryptTest extends Unit_Crypt_AES_TestCase
{ {
static public function setUpBeforeClass() protected function setUp()
{ {
if (!extension_loaded('mcrypt')) { $this->engine = CRYPT_ENGINE_MCRYPT;
self::markTestSkipped('mcrypt extension is not available.');
}
parent::setUpBeforeClass();
self::ensureConstant('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
self::ensureConstant('CRYPT_RIJNDAEL_MODE', CRYPT_RIJNDAEL_MODE_MCRYPT);
} }
} }

View File

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

View File

@ -9,25 +9,34 @@ require_once 'Crypt/AES.php';
abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
{ {
static public function setUpBeforeClass() protected $engine;
{
parent::setUpBeforeClass();
self::reRequireFile('Crypt/Rijndael.php'); private function _checkEngine($aes)
self::reRequireFile('Crypt/AES.php'); {
if ($aes->getEngine() != $this->engine) {
$engine = 'internal';
switch ($this->engine) {
case CRYPT_ENGINE_OPENSSL:
$engine = 'OpenSSL';
break;
case CRYPT_ENGINE_MCRYPT:
$engine = 'mcrypt';
}
self::markTestSkipped('Unable to initialize ' . $engine . ' engine');
}
} }
/** /**
* Produces all combinations of test values. * Produces all combinations of test values.
* *
* @return array * @return array
*/ */
public function continuousBufferCombos() public function continuousBufferCombos()
{ {
$modes = array( $modes = array(
'CRYPT_AES_MODE_CTR', 'CRYPT_MODE_CTR',
'CRYPT_AES_MODE_OFB', 'CRYPT_MODE_OFB',
'CRYPT_AES_MODE_CFB', 'CRYPT_MODE_CFB',
); );
$plaintexts = array( $plaintexts = array(
'', '',
@ -59,15 +68,18 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
} }
/** /**
* @dataProvider continuousBufferCombos * @dataProvider continuousBufferCombos
*/ */
public function testEncryptDecryptWithContinuousBuffer($mode, $plaintext, $iv, $key) public function testEncryptDecryptWithContinuousBuffer($mode, $plaintext, $iv, $key)
{ {
$aes = new Crypt_AES(constant($mode)); $aes = new Crypt_AES(constant($mode));
$aes->setPreferredEngine($this->engine);
$aes->enableContinuousBuffer(); $aes->enableContinuousBuffer();
$aes->setIV($iv); $aes->setIV($iv);
$aes->setKey($key); $aes->setKey($key);
$this->_checkEngine($aes);
$actual = ''; $actual = '';
for ($i = 0, $strlen = strlen($plaintext); $i < $strlen; ++$i) { for ($i = 0, $strlen = strlen($plaintext); $i < $strlen; ++$i) {
$actual .= $aes->decrypt($aes->encrypt($plaintext[$i])); $actual .= $aes->decrypt($aes->encrypt($plaintext[$i]));
@ -77,31 +89,245 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase
} }
/** /**
* @group github451 * @group github451
*/ */
public function testKeyPaddingRijndael() public function testKeyPaddingRijndael()
{ {
// this test case is from the following URL: // this test case is from the following URL:
// https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip // https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip
$aes = new Crypt_Rijndael(); $aes = new Crypt_Rijndael();
$aes->setPreferredEngine($this->engine);
$aes->disablePadding(); $aes->disablePadding();
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. Valid in Rijndael. $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')); $ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
$this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880')); $this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880'));
} }
/** /**
* @group github451 * @group github451
*/ */
public function testKeyPaddingAES() public function testKeyPaddingAES()
{ {
// same as the above - just with a different ciphertext // same as the above - just with a different ciphertext
$aes = new Crypt_AES(); $aes = new Crypt_AES();
$aes->setPreferredEngine($this->engine);
$aes->disablePadding(); $aes->disablePadding();
$aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits $aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits
$this->_checkEngine($aes);
$ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734')); $ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734'));
$this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0')); $this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0'));
} }
/**
* Produces all combinations of test values.
*
* @return array
*/
public function continuousBufferBatteryCombos()
{
$modes = array(
'CRYPT_MODE_CTR',
'CRYPT_MODE_OFB',
'CRYPT_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 Crypt_AES(constant($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 Crypt_AES(constant($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 Crypt_AES(constant($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 Crypt_AES(constant($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 Crypt_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 Crypt_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 Crypt_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,83 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/Blowfish.php';
class Unit_Crypt_BlowfishTest extends PhpseclibTestCase
{
public function engineVectors()
{
$engines = array(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_ENGINE_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 Crypt_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,77 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/DES.php';
// 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 Crypt_DES(CRYPT_MODE_CBC);
$des->setKey('d');
$des->setIV('d');
$des->setPreferredEngine(CRYPT_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(CRYPT_ENGINE_MCRYPT);
if ($des->getEngine() == CRYPT_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(CRYPT_ENGINE_OPENSSL);
if ($des->getEngine() == CRYPT_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 Crypt_DES(CRYPT_MODE_CBC);
$des->disablePadding();
// when the key and iv are not specified they should be null padded
//$des->setKey();
//$des->setIV();
$des->setPreferredEngine(CRYPT_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(CRYPT_ENGINE_MCRYPT);
if ($des->getEngine() == CRYPT_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(CRYPT_ENGINE_OPENSSL);
if ($des->getEngine() == CRYPT_ENGINE_OPENSSL) {
$openssl = $des->decrypt('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

@ -13,8 +13,8 @@ class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hashData() * @dataProvider hashData()
*/ */
public function testHash($message, $result) public function testHash($message, $result)
{ {
$this->assertHashesTo($this->getInstance(), $message, $result); $this->assertHashesTo($this->getInstance(), $message, $result);
@ -30,8 +30,8 @@ class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hmacData() * @dataProvider hmacData()
*/ */
public function testHMAC($key, $message, $result) public function testHMAC($key, $message, $result)
{ {
$this->assertHMACsTo($this->getInstance(), $key, $message, $result); $this->assertHMACsTo($this->getInstance(), $key, $message, $result);

View File

@ -13,8 +13,8 @@ class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hashData() * @dataProvider hashData()
*/ */
public function testHash($message, $result) public function testHash($message, $result)
{ {
$this->assertHashesTo($this->getInstance(), $message, $result); $this->assertHashesTo($this->getInstance(), $message, $result);
@ -39,8 +39,8 @@ class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hmacData() * @dataProvider hmacData()
*/ */
public function testHMAC($key, $message, $result) public function testHMAC($key, $message, $result)
{ {
$this->assertHMACsTo($this->getInstance(), $key, $message, $result); $this->assertHMACsTo($this->getInstance(), $key, $message, $result);

View File

@ -13,16 +13,16 @@ class Unit_Crypt_Hash_SHA256_96Test extends Unit_Crypt_Hash_SHA256Test
} }
/** /**
* @dataProvider hashData() * @dataProvider hashData()
*/ */
public function testHash($message, $longResult) public function testHash($message, $longResult)
{ {
parent::testHash($message, substr($longResult, 0, 24)); parent::testHash($message, substr($longResult, 0, 24));
} }
/** /**
* @dataProvider hmacData() * @dataProvider hmacData()
*/ */
public function testHMAC($key, $message, $longResult) public function testHMAC($key, $message, $longResult)
{ {
parent::testHMAC($key, $message, substr($longResult, 0, 24)); parent::testHMAC($key, $message, substr($longResult, 0, 24));

View File

@ -13,8 +13,8 @@ class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hashData() * @dataProvider hashData()
*/ */
public function testHash($message, $result) public function testHash($message, $result)
{ {
$this->assertHashesTo($this->getInstance(), $message, $result); $this->assertHashesTo($this->getInstance(), $message, $result);
@ -39,8 +39,8 @@ class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase
} }
/** /**
* @dataProvider hmacData() * @dataProvider hmacData()
*/ */
public function testHMAC($key, $message, $result) public function testHMAC($key, $message, $result)
{ {
$this->assertHMACsTo($this->getInstance(), $key, $message, $result); $this->assertHMACsTo($this->getInstance(), $key, $message, $result);

View File

@ -13,16 +13,16 @@ class Unit_Crypt_Hash_SHA512_96Test extends Unit_Crypt_Hash_SHA512Test
} }
/** /**
* @dataProvider hashData() * @dataProvider hashData()
*/ */
public function testHash($message, $longResult) public function testHash($message, $longResult)
{ {
parent::testHash($message, substr($longResult, 0, 24)); parent::testHash($message, substr($longResult, 0, 24));
} }
/** /**
* @dataProvider hmacData() * @dataProvider hmacData()
*/ */
public function testHMAC($key, $message, $longResult) public function testHMAC($key, $message, $longResult)
{ {
parent::testHMAC($key, $message, substr($longResult, 0, 24)); parent::testHMAC($key, $message, substr($longResult, 0, 24));

View File

@ -0,0 +1,121 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/RC2.php';
class Unit_Crypt_RC2Test extends PhpseclibTestCase
{
var $engines = array(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_ENGINE_OPENSSL => '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 Crypt_RC2(CRYPT_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(CRYPT_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(CRYPT_ENGINE_MCRYPT);
if ($rc2->getEngine() == CRYPT_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(CRYPT_ENGINE_OPENSSL);
if ($rc2->getEngine() == CRYPT_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 Crypt_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,207 @@
<?php
/**
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/RC4.php';
class Unit_Crypt_RC4Test extends PhpseclibTestCase
{
public function engineVectors()
{
$engines = array(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_ENGINE_OPENSSL => '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 Crypt_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

@ -261,10 +261,10 @@ Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
} }
/** /**
* make phpseclib generated XML keys be unsigned. this may need to be reverted * make phpseclib generated XML keys be unsigned. this may need to be reverted
* if it is later learned that XML keys are, in fact, supposed to be signed * if it is later learned that XML keys are, in fact, supposed to be signed
* @group github468 * @group github468
*/ */
public function testUnsignedXML() public function testUnsignedXML()
{ {
$rsa = new Crypt_RSA(); $rsa = new Crypt_RSA();
@ -282,8 +282,8 @@ Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
} }
/** /**
* @group github468 * @group github468
*/ */
public function testSignedPKCS1() public function testSignedPKCS1()
{ {
$rsa = new Crypt_RSA(); $rsa = new Crypt_RSA();

View File

@ -27,9 +27,9 @@ class Unit_Crypt_RandomTest extends PhpseclibTestCase
} }
/** /**
* Takes a set of random values of length 128 bits and asserts all taken * Takes a set of random values of length 128 bits and asserts all taken
* values are unique. * values are unique.
*/ */
public function testStringUniqueness() public function testStringUniqueness()
{ {
$values = array(); $values = array();

View File

@ -0,0 +1,182 @@
<?php
/**
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2014 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/TripleDES.php';
class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
{
var $engines = array(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_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 Crypt_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(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_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 Crypt_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 Crypt_TripleDES(CRYPT_DES_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,73 @@
<?php
/**
* @author Andreas Fischer <bantu@phpbb.com>
* @copyright MMXIII Andreas Fischer
* @license http://www.opensource.org/licenses/mit-license.html MIT License
*/
require_once 'Crypt/Twofish.php';
class Unit_Crypt_TwofishTest extends PhpseclibTestCase
{
public function testVectors()
{
$engines = array(
CRYPT_ENGINE_INTERNAL => 'internal',
CRYPT_ENGINE_MCRYPT => 'mcrypt',
CRYPT_ENGINE_OPENSSL => 'OpenSSL',
);
foreach ($engines as $engine=>$name) {
$tf = new Crypt_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

@ -10,9 +10,9 @@ require_once 'File/ASN1.php';
class Unit_File_ASN1Test extends PhpseclibTestCase class Unit_File_ASN1Test extends PhpseclibTestCase
{ {
/** /**
* on older versions of File_ASN1 this would yield a PHP Warning * on older versions of File_ASN1 this would yield a PHP Warning
* @group github275 * @group github275
*/ */
public function testAnyString() public function testAnyString()
{ {
$KDC_REP = array( $KDC_REP = array(
@ -83,9 +83,9 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
} }
/** /**
* on older versions of File_ASN1 this would produce a null instead of an array * on older versions of File_ASN1 this would produce a null instead of an array
* @group github275 * @group github275
*/ */
public function testIncorrectString() public function testIncorrectString()
{ {
$PA_DATA = array( $PA_DATA = array(
@ -235,8 +235,8 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
} }
/** /**
* older versions of File_ASN1 didn't handle indefinite length tags very well * older versions of File_ASN1 didn't handle indefinite length tags very well
*/ */
public function testIndefiniteLength() public function testIndefiniteLength()
{ {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
@ -270,8 +270,8 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
} }
/** /**
* @group github477 * @group github477
*/ */
public function testContextSpecificNonConstructed() public function testContextSpecificNonConstructed()
{ {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
@ -280,8 +280,8 @@ class Unit_File_ASN1Test extends PhpseclibTestCase
} }
/** /**
* @group github602 * @group github602
*/ */
public function testEmptyContextTag() public function testEmptyContextTag()
{ {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();

View File

@ -295,8 +295,8 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase
} }
/** /**
* @group github279 * @group github279
*/ */
public function testDiffieHellmanKeyAgreement() public function testDiffieHellmanKeyAgreement()
{ {
if (getenv('TRAVIS') && PHP_VERSION === '5.3.3' if (getenv('TRAVIS') && PHP_VERSION === '5.3.3'

View File

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