mirror of
https://github.com/phpseclib/phpseclib.git
synced 2025-01-11 17:38:53 +00:00
SymmetricCiphers: don't cache "hi-optimized code"
Also add a new engine - ENGINE_EVAL. Previously ENGINE_INTERNAL had three different modes - a "hi-optimized" version, a "lo-optimized" version and a version that didn't depend on create_function and there wasn't a way to really isolate these modes and test them individually.
This commit is contained in:
parent
2a1177b256
commit
d34a911402
@ -478,22 +478,6 @@ class Blowfish extends BlockCipher
|
|||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
$lambda_functions =& self::getLambdaFunctions();
|
|
||||||
|
|
||||||
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
|
|
||||||
// (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
|
|
||||||
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
|
|
||||||
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
|
||||||
|
|
||||||
// Generation of a unique hash for our generated code
|
|
||||||
$code_hash = "Crypt_Blowfish, {$this->mode}";
|
|
||||||
if ($gen_hi_opt_code) {
|
|
||||||
$code_hash = str_pad($code_hash, 32) . $this->hashInlineCryptFunction($this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($lambda_functions[$code_hash])) {
|
|
||||||
switch (true) {
|
|
||||||
case $gen_hi_opt_code:
|
|
||||||
$p = $this->bctx['p'];
|
$p = $this->bctx['p'];
|
||||||
$init_crypt = '
|
$init_crypt = '
|
||||||
static $sb_0, $sb_1, $sb_2, $sb_3;
|
static $sb_0, $sb_1, $sb_2, $sb_3;
|
||||||
@ -504,18 +488,6 @@ class Blowfish extends BlockCipher
|
|||||||
$sb_3 = $this->bctx["sb"][3];
|
$sb_3 = $this->bctx["sb"][3];
|
||||||
}
|
}
|
||||||
';
|
';
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$p = [];
|
|
||||||
for ($i = 0; $i < 18; ++$i) {
|
|
||||||
$p[] = '$p_' . $i;
|
|
||||||
}
|
|
||||||
$init_crypt = '
|
|
||||||
list($sb_0, $sb_1, $sb_2, $sb_3) = $this->bctx["sb"];
|
|
||||||
list(' . implode(',', $p) . ') = $this->bctx["p"];
|
|
||||||
|
|
||||||
';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generating encrypt code:
|
// Generating encrypt code:
|
||||||
$encrypt_block = '
|
$encrypt_block = '
|
||||||
@ -544,7 +516,6 @@ class Blowfish extends BlockCipher
|
|||||||
$l ^ ' . $p[16] . '
|
$l ^ ' . $p[16] . '
|
||||||
);
|
);
|
||||||
';
|
';
|
||||||
|
|
||||||
// Generating decrypt code:
|
// Generating decrypt code:
|
||||||
$decrypt_block = '
|
$decrypt_block = '
|
||||||
$in = unpack("N*", $in);
|
$in = unpack("N*", $in);
|
||||||
@ -575,7 +546,7 @@ class Blowfish extends BlockCipher
|
|||||||
);
|
);
|
||||||
';
|
';
|
||||||
|
|
||||||
$lambda_functions[$code_hash] = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => $init_crypt,
|
'init_crypt' => $init_crypt,
|
||||||
'init_encrypt' => '',
|
'init_encrypt' => '',
|
||||||
@ -585,6 +556,4 @@ class Blowfish extends BlockCipher
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->inline_crypt = \Closure::bind($lambda_functions[$code_hash], $this, $this->getClassContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -92,15 +92,6 @@ abstract class SymmetricKey
|
|||||||
const MODE_STREAM = 5;
|
const MODE_STREAM = 5;
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Whirlpool available flag
|
|
||||||
*
|
|
||||||
* @see \phpseclib\Crypt\Common\SymmetricKey::_hashInlineCryptFunction()
|
|
||||||
* @var bool
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private static $WHIRLPOOL_AVAILABLE;
|
|
||||||
|
|
||||||
/**#@+
|
/**#@+
|
||||||
* @access private
|
* @access private
|
||||||
* @see \phpseclib\Crypt\Common\SymmetricKey::__construct()
|
* @see \phpseclib\Crypt\Common\SymmetricKey::__construct()
|
||||||
@ -110,13 +101,17 @@ abstract class SymmetricKey
|
|||||||
*/
|
*/
|
||||||
const ENGINE_INTERNAL = 1;
|
const ENGINE_INTERNAL = 1;
|
||||||
/**
|
/**
|
||||||
* Base value for the mcrypt implementation $engine switch
|
* Base value for the eval() implementation $engine switch
|
||||||
*/
|
*/
|
||||||
const ENGINE_MCRYPT = 2;
|
const ENGINE_EVAL = 2;
|
||||||
/**
|
/**
|
||||||
* Base value for the mcrypt implementation $engine switch
|
* Base value for the mcrypt implementation $engine switch
|
||||||
*/
|
*/
|
||||||
const ENGINE_OPENSSL = 3;
|
const ENGINE_MCRYPT = 3;
|
||||||
|
/**
|
||||||
|
* Base value for the mcrypt implementation $engine switch
|
||||||
|
*/
|
||||||
|
const ENGINE_OPENSSL = 4;
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -480,11 +475,6 @@ abstract class SymmetricKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->mode = $mode;
|
$this->mode = $mode;
|
||||||
|
|
||||||
// Determining whether inline crypting can be used by the cipher
|
|
||||||
if ($this->use_inline_crypt !== false) {
|
|
||||||
$this->use_inline_crypt = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -982,7 +972,7 @@ abstract class SymmetricKey
|
|||||||
$this->setup();
|
$this->setup();
|
||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
if ($this->use_inline_crypt) {
|
if ($this->engine === self::ENGINE_EVAL) {
|
||||||
$inline = $this->inline_crypt;
|
$inline = $this->inline_crypt;
|
||||||
return $inline('encrypt', $plaintext);
|
return $inline('encrypt', $plaintext);
|
||||||
}
|
}
|
||||||
@ -1266,7 +1256,7 @@ abstract class SymmetricKey
|
|||||||
$this->setup();
|
$this->setup();
|
||||||
$this->changed = false;
|
$this->changed = false;
|
||||||
}
|
}
|
||||||
if ($this->use_inline_crypt) {
|
if ($this->engine === self::ENGINE_EVAL) {
|
||||||
$inline = $this->inline_crypt;
|
$inline = $this->inline_crypt;
|
||||||
return $inline('decrypt', $ciphertext);
|
return $inline('decrypt', $ciphertext);
|
||||||
}
|
}
|
||||||
@ -1696,9 +1686,7 @@ abstract class SymmetricKey
|
|||||||
}
|
}
|
||||||
$this->openssl_emulate_ctr = false;
|
$this->openssl_emulate_ctr = false;
|
||||||
$result = $this->cipher_name_openssl &&
|
$result = $this->cipher_name_openssl &&
|
||||||
extension_loaded('openssl') &&
|
extension_loaded('openssl');
|
||||||
// PHP 5.3.0 - 5.3.2 did not let you set IV's
|
|
||||||
version_compare(PHP_VERSION, '5.3.3', '>=');
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1721,6 +1709,8 @@ abstract class SymmetricKey
|
|||||||
return $this->cipher_name_mcrypt &&
|
return $this->cipher_name_mcrypt &&
|
||||||
extension_loaded('mcrypt') &&
|
extension_loaded('mcrypt') &&
|
||||||
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
|
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
|
||||||
|
case self::ENGINE_EVAL:
|
||||||
|
return method_exists($this, 'setupInlineCrypt');
|
||||||
case self::ENGINE_INTERNAL:
|
case self::ENGINE_INTERNAL:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1737,7 +1727,9 @@ abstract class SymmetricKey
|
|||||||
*
|
*
|
||||||
* - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_MCRYPT [fast]
|
* - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_MCRYPT [fast]
|
||||||
*
|
*
|
||||||
* - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_INTERNAL [slow]
|
* - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_EVAL [slow]
|
||||||
|
*
|
||||||
|
* - \phpseclib\Crypt\Common\SymmetricKey::ENGINE_INTERNAL [slowest]
|
||||||
*
|
*
|
||||||
* If the preferred crypt engine is not available the fastest available one will be used
|
* If the preferred crypt engine is not available the fastest available one will be used
|
||||||
*
|
*
|
||||||
@ -1751,6 +1743,7 @@ abstract class SymmetricKey
|
|||||||
//case self::ENGINE_OPENSSL;
|
//case self::ENGINE_OPENSSL;
|
||||||
case self::ENGINE_MCRYPT:
|
case self::ENGINE_MCRYPT:
|
||||||
case self::ENGINE_INTERNAL:
|
case self::ENGINE_INTERNAL:
|
||||||
|
case self::ENGINE_EVAL:
|
||||||
$this->preferredEngine = $engine;
|
$this->preferredEngine = $engine;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1784,7 +1777,8 @@ abstract class SymmetricKey
|
|||||||
$candidateEngines = [
|
$candidateEngines = [
|
||||||
$this->preferredEngine,
|
$this->preferredEngine,
|
||||||
self::ENGINE_OPENSSL,
|
self::ENGINE_OPENSSL,
|
||||||
self::ENGINE_MCRYPT
|
self::ENGINE_MCRYPT,
|
||||||
|
self::ENGINE_EVAL
|
||||||
];
|
];
|
||||||
foreach ($candidateEngines as $engine) {
|
foreach ($candidateEngines as $engine) {
|
||||||
if ($this->isValidEngine($engine)) {
|
if ($this->isValidEngine($engine)) {
|
||||||
@ -1876,7 +1870,7 @@ abstract class SymmetricKey
|
|||||||
$this->clearBuffers();
|
$this->clearBuffers();
|
||||||
$this->setupKey();
|
$this->setupKey();
|
||||||
|
|
||||||
if ($this->use_inline_crypt) {
|
if ($this->engine === self::ENGINE_EVAL) {
|
||||||
$this->setupInlineCrypt();
|
$this->setupInlineCrypt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2064,9 +2058,7 @@ abstract class SymmetricKey
|
|||||||
*
|
*
|
||||||
* _setupInlineCrypt() would be called only if:
|
* _setupInlineCrypt() would be called only if:
|
||||||
*
|
*
|
||||||
* - $engine == self::ENGINE_INTERNAL and
|
* - $this->engine === self::ENGINE_EVAL
|
||||||
*
|
|
||||||
* - $use_inline_crypt === true
|
|
||||||
*
|
*
|
||||||
* - each time on _setup(), after(!) _setupKey()
|
* - each time on _setup(), after(!) _setupKey()
|
||||||
*
|
*
|
||||||
@ -2114,16 +2106,7 @@ abstract class SymmetricKey
|
|||||||
* @access private
|
* @access private
|
||||||
* @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
|
* @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
//protected function setupInlineCrypt();
|
||||||
{
|
|
||||||
// If, for any reason, an extending \phpseclib\Crypt\Common\SymmetricKey() \phpseclib\Crypt\* class
|
|
||||||
// not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
|
|
||||||
// ie in the class var declaration of $use_inline_crypt in general for the \phpseclib\Crypt\* class,
|
|
||||||
// in the constructor at object instance-time
|
|
||||||
// or, if it's runtime-specific, at runtime
|
|
||||||
|
|
||||||
$this->use_inline_crypt = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the performance-optimized function for en/decrypt()
|
* Creates the performance-optimized function for en/decrypt()
|
||||||
@ -2586,63 +2569,7 @@ abstract class SymmetricKey
|
|||||||
|
|
||||||
eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};');
|
eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};');
|
||||||
|
|
||||||
return $func;
|
return \Closure::bind($func, $this, $this->getClassContext());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds the lambda_functions table (classwide)
|
|
||||||
*
|
|
||||||
* Each name of the lambda function, created from
|
|
||||||
* _setupInlineCrypt() && _createInlineCryptFunction()
|
|
||||||
* is stored, classwide (!), here for reusing.
|
|
||||||
*
|
|
||||||
* The string-based index of $function is a classwide
|
|
||||||
* unique value representing, at least, the $mode of
|
|
||||||
* operation (or more... depends of the optimizing level)
|
|
||||||
* for which $mode the lambda function was created.
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @return array &$functions
|
|
||||||
*/
|
|
||||||
protected function &getLambdaFunctions()
|
|
||||||
{
|
|
||||||
static $functions = [];
|
|
||||||
return $functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a digest from $bytes
|
|
||||||
*
|
|
||||||
* @see self::setupInlineCrypt()
|
|
||||||
* @access private
|
|
||||||
* @param $bytes
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function hashInlineCryptFunction($bytes)
|
|
||||||
{
|
|
||||||
if (!isset(self::$WHIRLPOOL_AVAILABLE)) {
|
|
||||||
self::$WHIRLPOOL_AVAILABLE = extension_loaded('hash') && in_array('whirlpool', hash_algos());
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = '';
|
|
||||||
$hash = $bytes;
|
|
||||||
|
|
||||||
switch (true) {
|
|
||||||
case self::$WHIRLPOOL_AVAILABLE:
|
|
||||||
foreach (str_split($bytes, 64) as $t) {
|
|
||||||
$hash = hash('whirlpool', $hash, true);
|
|
||||||
$result .= $t ^ $hash;
|
|
||||||
}
|
|
||||||
return $result . hash('whirlpool', $hash, true);
|
|
||||||
default:
|
|
||||||
$len = strlen($bytes);
|
|
||||||
for ($i = 0; $i < $len; $i+=20) {
|
|
||||||
$t = substr($bytes, $i, 20);
|
|
||||||
$hash = sha1($hash, true);
|
|
||||||
$result .= $t ^ $hash;
|
|
||||||
}
|
|
||||||
return $result . sha1($hash, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1301,33 +1301,11 @@ class DES extends BlockCipher
|
|||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
$lambda_functions =& self::getLambdaFunctions();
|
|
||||||
|
|
||||||
// Engine configuration for:
|
// Engine configuration for:
|
||||||
// - DES ($des_rounds == 1) or
|
// - DES ($des_rounds == 1) or
|
||||||
// - 3DES ($des_rounds == 3)
|
// - 3DES ($des_rounds == 3)
|
||||||
$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.
|
|
||||||
// (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
|
|
||||||
// (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
|
|
||||||
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
|
|
||||||
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
|
|
||||||
|
|
||||||
// Generation of a unique hash for our generated code
|
|
||||||
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
|
|
||||||
if ($gen_hi_opt_code) {
|
|
||||||
// For hi-optimized code, we create for each combination of
|
|
||||||
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
|
|
||||||
// After max 10 hi-optimized functions, we create generic
|
|
||||||
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
|
|
||||||
// Currently 2 * 5 generic functions will be then max. possible.
|
|
||||||
$code_hash = str_pad($code_hash, 32) . $this->hashInlineCryptFunction($this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is there a re-usable $lambda_functions in there? If not, we have to create it.
|
|
||||||
if (!isset($lambda_functions[$code_hash])) {
|
|
||||||
// Init code for both, encrypt and decrypt.
|
|
||||||
$init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
$init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
||||||
if (!$sbox1) {
|
if (!$sbox1) {
|
||||||
$sbox1 = array_map("intval", $this->sbox1);
|
$sbox1 = array_map("intval", $this->sbox1);
|
||||||
@ -1346,33 +1324,12 @@ class DES extends BlockCipher
|
|||||||
}
|
}
|
||||||
';
|
';
|
||||||
|
|
||||||
switch (true) {
|
|
||||||
case $gen_hi_opt_code:
|
|
||||||
// In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
|
|
||||||
// No futher initialisation of the $keys schedule is necessary.
|
|
||||||
// That is the extra performance boost.
|
|
||||||
$k = [
|
$k = [
|
||||||
self::ENCRYPT => $this->keys[self::ENCRYPT],
|
self::ENCRYPT => $this->keys[self::ENCRYPT],
|
||||||
self::DECRYPT => $this->keys[self::DECRYPT]
|
self::DECRYPT => $this->keys[self::DECRYPT]
|
||||||
];
|
];
|
||||||
$init_encrypt = '';
|
$init_encrypt = '';
|
||||||
$init_decrypt = '';
|
$init_decrypt = '';
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// In generic optimized code mode, we have to use, as the best compromise [currently],
|
|
||||||
// our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
|
|
||||||
$k = [
|
|
||||||
self::ENCRYPT => [],
|
|
||||||
self::DECRYPT => []
|
|
||||||
];
|
|
||||||
for ($i = 0, $c = count($this->keys[self::ENCRYPT]); $i < $c; ++$i) {
|
|
||||||
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
|
|
||||||
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
|
|
||||||
}
|
|
||||||
$init_encrypt = '$ke = $this->keys[self::ENCRYPT];';
|
|
||||||
$init_decrypt = '$kd = $this->keys[self::DECRYPT];';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creating code for en- and decryption.
|
// Creating code for en- and decryption.
|
||||||
$crypt_block = [];
|
$crypt_block = [];
|
||||||
@ -1438,7 +1395,7 @@ class DES extends BlockCipher
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates the inline-crypt function
|
// Creates the inline-crypt function
|
||||||
$lambda_functions[$code_hash] = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => $init_crypt,
|
'init_crypt' => $init_crypt,
|
||||||
'init_encrypt' => $init_encrypt,
|
'init_encrypt' => $init_encrypt,
|
||||||
@ -1448,8 +1405,4 @@ class DES extends BlockCipher
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the inline-crypt function as callback in: $this->inline_crypt
|
|
||||||
$this->inline_crypt = \Closure::bind($lambda_functions[$code_hash], $this, $this->getClassContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -578,35 +578,10 @@ class RC2 extends BlockCipher
|
|||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
$lambda_functions =& self::getLambdaFunctions();
|
|
||||||
|
|
||||||
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
|
|
||||||
// for the mixing rounds, for better inline crypt performance [~20% faster].
|
|
||||||
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
|
|
||||||
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
|
|
||||||
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
|
||||||
|
|
||||||
// Generation of a unique hash for our generated code
|
|
||||||
$code_hash = "Crypt_RC2, {$this->mode}";
|
|
||||||
if ($gen_hi_opt_code) {
|
|
||||||
$code_hash = str_pad($code_hash, 32) . $this->hashInlineCryptFunction($this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is there a re-usable $lambda_functions in there?
|
|
||||||
// If not, we have to create it.
|
|
||||||
if (!isset($lambda_functions[$code_hash])) {
|
|
||||||
// Init code for both, encrypt and decrypt.
|
// Init code for both, encrypt and decrypt.
|
||||||
$init_crypt = '$keys = $this->keys;';
|
$init_crypt = '$keys = $this->keys;';
|
||||||
|
|
||||||
switch (true) {
|
|
||||||
case $gen_hi_opt_code:
|
|
||||||
$keys = $this->keys;
|
$keys = $this->keys;
|
||||||
default:
|
|
||||||
$keys = [];
|
|
||||||
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 = '
|
||||||
@ -694,7 +669,7 @@ class RC2 extends BlockCipher
|
|||||||
$decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
|
$decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
|
||||||
|
|
||||||
// Creates the inline-crypt function
|
// Creates the inline-crypt function
|
||||||
$lambda_functions[$code_hash] = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => $init_crypt,
|
'init_crypt' => $init_crypt,
|
||||||
'encrypt_block' => $encrypt_block,
|
'encrypt_block' => $encrypt_block,
|
||||||
@ -702,8 +677,4 @@ class RC2 extends BlockCipher
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the inline-crypt function as callback in: $this->inline_crypt
|
|
||||||
$this->inline_crypt = \Closure::bind($lambda_functions[$code_hash], $this, $this->getClassContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -811,40 +811,10 @@ class Rijndael extends BlockCipher
|
|||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
// Note: _setupInlineCrypt() will be called only if $this->changed === true
|
|
||||||
// So here we are'nt under the same heavy timing-stress as we are in _de/encryptBlock() or de/encrypt().
|
|
||||||
// However...the here generated function- $code, stored as php callback in $this->inline_crypt, must work as fast as even possible.
|
|
||||||
|
|
||||||
$lambda_functions =& self::getLambdaFunctions();
|
|
||||||
|
|
||||||
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
|
|
||||||
// (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit)
|
|
||||||
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
|
|
||||||
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
|
||||||
|
|
||||||
// Generation of a uniqe hash for our generated code
|
|
||||||
$code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}";
|
|
||||||
if ($gen_hi_opt_code) {
|
|
||||||
$code_hash = str_pad($code_hash, 32) . $this->hashInlineCryptFunction($this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($lambda_functions[$code_hash])) {
|
|
||||||
switch (true) {
|
|
||||||
case $gen_hi_opt_code:
|
|
||||||
// The hi-optimized $lambda_functions will use the key-words hardcoded for better performance.
|
|
||||||
$w = $this->w;
|
$w = $this->w;
|
||||||
$dw = $this->dw;
|
$dw = $this->dw;
|
||||||
$init_encrypt = '';
|
$init_encrypt = '';
|
||||||
$init_decrypt = '';
|
$init_decrypt = '';
|
||||||
break;
|
|
||||||
default:
|
|
||||||
for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) {
|
|
||||||
$w[] = '$w[' . $i . ']';
|
|
||||||
$dw[] = '$dw[' . $i . ']';
|
|
||||||
}
|
|
||||||
$init_encrypt = '$w = $this->w;';
|
|
||||||
$init_decrypt = '$dw = $this->dw;';
|
|
||||||
}
|
|
||||||
|
|
||||||
$Nr = $this->Nr;
|
$Nr = $this->Nr;
|
||||||
$Nb = $this->Nb;
|
$Nb = $this->Nb;
|
||||||
@ -964,7 +934,7 @@ class Rijndael extends BlockCipher
|
|||||||
}
|
}
|
||||||
$decrypt_block .= ');';
|
$decrypt_block .= ');';
|
||||||
|
|
||||||
$lambda_functions[$code_hash] = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => '',
|
'init_crypt' => '',
|
||||||
'init_encrypt' => $init_encrypt,
|
'init_encrypt' => $init_encrypt,
|
||||||
@ -974,7 +944,4 @@ class Rijndael extends BlockCipher
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->inline_crypt = \Closure::bind($lambda_functions[$code_hash], $this, $this->getClassContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -707,21 +707,6 @@ class Twofish extends BlockCipher
|
|||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
$lambda_functions =& self::getLambdaFunctions();
|
|
||||||
|
|
||||||
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
|
|
||||||
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
|
|
||||||
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
|
||||||
|
|
||||||
// Generation of a unique hash for our generated code
|
|
||||||
$code_hash = "Crypt_Twofish, {$this->mode}";
|
|
||||||
if ($gen_hi_opt_code) {
|
|
||||||
$code_hash = str_pad($code_hash, 32) . $this->hashInlineCryptFunction($this->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($lambda_functions[$code_hash])) {
|
|
||||||
switch (true) {
|
|
||||||
case $gen_hi_opt_code:
|
|
||||||
$K = $this->K;
|
$K = $this->K;
|
||||||
$init_crypt = '
|
$init_crypt = '
|
||||||
static $S0, $S1, $S2, $S3;
|
static $S0, $S1, $S2, $S3;
|
||||||
@ -734,20 +719,6 @@ class Twofish extends BlockCipher
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
';
|
';
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$K = [];
|
|
||||||
for ($i = 0; $i < 40; ++$i) {
|
|
||||||
$K[] = '$K_' . $i;
|
|
||||||
}
|
|
||||||
$init_crypt = '
|
|
||||||
$S0 = $this->S0;
|
|
||||||
$S1 = $this->S1;
|
|
||||||
$S2 = $this->S2;
|
|
||||||
$S3 = $this->S3;
|
|
||||||
list(' . implode(',', $K) . ') = $this->K;
|
|
||||||
';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generating encrypt code:
|
// Generating encrypt code:
|
||||||
$encrypt_block = '
|
$encrypt_block = '
|
||||||
@ -833,7 +804,7 @@ class Twofish extends BlockCipher
|
|||||||
'.$K[3].' ^ $R1);
|
'.$K[3].' ^ $R1);
|
||||||
';
|
';
|
||||||
|
|
||||||
$lambda_functions[$code_hash] = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => $init_crypt,
|
'init_crypt' => $init_crypt,
|
||||||
'init_encrypt' => '',
|
'init_encrypt' => '',
|
||||||
@ -843,6 +814,4 @@ class Twofish extends BlockCipher
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$this->inline_crypt = \Closure::bind($lambda_functions[$code_hash], $this, $this->getClassContext());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
16
tests/Unit/Crypt/AES/EvalTest.php
Normal file
16
tests/Unit/Crypt/AES/EvalTest.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @author Andreas Fischer <bantu@phpbb.com>
|
||||||
|
* @copyright 2013 Andreas Fischer
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
use phpseclib\Crypt\Common\BlockCipher;
|
||||||
|
|
||||||
|
class Unit_Crypt_AES_EvalTest extends Unit_Crypt_AES_TestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->engine = BlockCipher::ENGINE_EVAL;
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ class Unit_Crypt_BlowfishTest extends PhpseclibTestCase
|
|||||||
{
|
{
|
||||||
$engines = array(
|
$engines = array(
|
||||||
BlockCipher::ENGINE_INTERNAL => 'internal',
|
BlockCipher::ENGINE_INTERNAL => 'internal',
|
||||||
|
BlockCipher::ENGINE_EVAL => 'eval',
|
||||||
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
||||||
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,7 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase
|
|||||||
{
|
{
|
||||||
var $engines = array(
|
var $engines = array(
|
||||||
BlockCipher::ENGINE_INTERNAL => 'internal',
|
BlockCipher::ENGINE_INTERNAL => 'internal',
|
||||||
|
BlockCipher::ENGINE_EVAL => 'eval',
|
||||||
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
||||||
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,7 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase
|
|||||||
{
|
{
|
||||||
var $engines = array(
|
var $engines = array(
|
||||||
BlockCipher::ENGINE_INTERNAL => 'internal',
|
BlockCipher::ENGINE_INTERNAL => 'internal',
|
||||||
|
BlockCipher::ENGINE_EVAL => 'eval',
|
||||||
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
||||||
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
||||||
);
|
);
|
||||||
|
@ -14,6 +14,7 @@ class Unit_Crypt_TwofishTest extends PhpseclibTestCase
|
|||||||
{
|
{
|
||||||
$engines = array(
|
$engines = array(
|
||||||
BlockCipher::ENGINE_INTERNAL => 'internal',
|
BlockCipher::ENGINE_INTERNAL => 'internal',
|
||||||
|
BlockCipher::ENGINE_EVAL => 'eval',
|
||||||
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
BlockCipher::ENGINE_MCRYPT => 'mcrypt',
|
||||||
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
BlockCipher::ENGINE_OPENSSL => 'OpenSSL',
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user