/** * Setup the performance-optimized function for de/encrypt() * * @see Crypt_Base::_setupInlineCrypt() * @access private */ 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 =& Crypt_Rijndael::_getLambdaFunctions(); // The first 10 generated $lambda_functions will use the key-words hardcoded for better performance. // For memory reason we limit those ultra-optimized functions. // After that, we use pure (extracted) integer vars for the key-words which is faster than accessing them via array. if (count($lambda_functions) < 10) { $w = $this->w; $dw = $this->dw; $init_encrypt = ''; $init_decrypt = ''; } else { for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) { $w[] = '$w[' . $i . ']'; $dw[] = '$dw[' . $i . ']'; } $init_encrypt = '$w = $self->w;'; $init_decrypt = '$dw = $self->dw;'; } $code_hash = md5(str_pad("Crypt_Rijndael, {$this->mode}, {$this->block_size}, ", 32, "") . implode(',', $w)); if (!isset($lambda_functions[$code_hash])) { $Nr = $this->Nr; $Nb = $this->Nb; $c = $this->c; // Generating encrypt code: $init_encrypt .= ' static $t0, $t1, $t2, $t3, $sbox; if (!$t0) { for ($i = 0; $i < 256; ++$i) { $t0[$i] = (int)$self->t0[$i]; $t1[$i] = (int)$self->t1[$i]; $t2[$i] = (int)$self->t2[$i]; $t3[$i] = (int)$self->t3[$i]; $sbox[$i] = (int)$self->sbox[$i]; } } '; $s = 'e'; $e = 's'; $wc = $Nb - 1; // Preround: addRoundKey $encrypt_block = '$in = unpack("N*", $in);' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $w[++$wc] . ";\n"; } // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$' . $e . $i . ' = $t0[($' . $s . $i . ' >> 24) & 0xff] ^ $t1[($' . $s . ($i + $c[1]) % $Nb . ' >> 16) & 0xff] ^ $t2[($' . $s . ($i + $c[2]) % $Nb . ' >> 8) & 0xff] ^ $t3[ $' . $s . ($i + $c[3]) % $Nb . ' & 0xff] ^ ' . $w[++$wc] . ";\n"; } } // Finalround: subWord + shiftRows + addRoundKey for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$' . $e . $i . ' = $sbox[ $' . $e . $i . ' & 0xff] | ($sbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | ($sbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | ($sbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; } $encrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= ', ($' . $e . $i . ' & 0xFF000000) ^ ($' . $e . ($i + $c[1]) % $Nb . ' & 0x00FF0000) ^ ($' . $e . ($i + $c[2]) % $Nb . ' & 0x0000FF00) ^ ($' . $e . ($i + $c[3]) % $Nb . ' & 0x000000FF) ^ ' . $w[$i] . "\n"; } $encrypt_block .= ');'; // Generating decrypt code: $init_decrypt .= ' static $dt0, $dt1, $dt2, $dt3, $isbox; if (!$dt0) { for ($i = 0; $i < 256; ++$i) { $dt0[$i] = (int)$self->dt0[$i]; $dt1[$i] = (int)$self->dt1[$i]; $dt2[$i] = (int)$self->dt2[$i]; $dt3[$i] = (int)$self->dt3[$i]; $isbox[$i] = (int)$self->isbox[$i]; } } '; $s = 'e'; $e = 's'; $wc = $Nb - 1; // Preround: addRoundKey $decrypt_block = '$in = unpack("N*", $in);' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $dw[++$wc] . ';' . "\n"; } // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$' . $e . $i . ' = $dt0[($' . $s . $i . ' >> 24) & 0xff] ^ $dt1[($' . $s . ($Nb + $i - $c[1]) % $Nb . ' >> 16) & 0xff] ^ $dt2[($' . $s . ($Nb + $i - $c[2]) % $Nb . ' >> 8) & 0xff] ^ $dt3[ $' . $s . ($Nb + $i - $c[3]) % $Nb . ' & 0xff] ^ ' . $dw[++$wc] . ";\n"; } } // Finalround: subWord + shiftRows + addRoundKey for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$' . $e . $i . ' = $isbox[ $' . $e . $i . ' & 0xff] | ($isbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | ($isbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | ($isbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; } $decrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= ', ($' . $e . $i . ' & 0xFF000000) ^ ($' . $e . ($Nb + $i - $c[1]) % $Nb . ' & 0x00FF0000) ^ ($' . $e . ($Nb + $i - $c[2]) % $Nb . ' & 0x0000FF00) ^ ($' . $e . ($Nb + $i - $c[3]) % $Nb . ' & 0x000000FF) ^ ' . $dw[$i] . "\n"; } $decrypt_block .= ');'; $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(array('init_crypt' => '', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block)); } $this->inline_crypt = $lambda_functions[$code_hash]; }
/** * Setup the performance-optimized function for de/encrypt() * * @see Crypt_Base::_setupInlineCrypt() * @access private */ 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 =& Crypt_Rijndael::_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; $dw = $this->dw; $init_encrypt = ''; $init_decrypt = ''; break; default: for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) { $w[] = '$w[' . $i . ']'; $dw[] = '$dw[' . $i . ']'; } $init_encrypt = '$w = $self->w;'; $init_decrypt = '$dw = $self->dw;'; } $Nr = $this->Nr; $Nb = $this->Nb; $c = $this->c; // Generating encrypt code: $init_encrypt .= ' static $tables; if (empty($tables)) { $tables = &$self->_getTables(); } $t0 = $tables[0]; $t1 = $tables[1]; $t2 = $tables[2]; $t3 = $tables[3]; $sbox = $tables[4]; '; $s = 'e'; $e = 's'; $wc = $Nb - 1; // Preround: addRoundKey $encrypt_block = '$in = unpack("N*", $in);' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $w[++$wc] . ";\n"; } // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$' . $e . $i . ' = $t0[($' . $s . $i . ' >> 24) & 0xff] ^ $t1[($' . $s . ($i + $c[1]) % $Nb . ' >> 16) & 0xff] ^ $t2[($' . $s . ($i + $c[2]) % $Nb . ' >> 8) & 0xff] ^ $t3[ $' . $s . ($i + $c[3]) % $Nb . ' & 0xff] ^ ' . $w[++$wc] . ";\n"; } } // Finalround: subWord + shiftRows + addRoundKey for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$' . $e . $i . ' = $sbox[ $' . $e . $i . ' & 0xff] | ($sbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | ($sbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | ($sbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; } $encrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= ', ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^ ($' . $e . ($i + $c[1]) % $Nb . ' & 0x00FF0000 ) ^ ($' . $e . ($i + $c[2]) % $Nb . ' & 0x0000FF00 ) ^ ($' . $e . ($i + $c[3]) % $Nb . ' & 0x000000FF ) ^ ' . $w[$i] . "\n"; } $encrypt_block .= ');'; // Generating decrypt code: $init_decrypt .= ' static $invtables; if (empty($invtables)) { $invtables = &$self->_getInvTables(); } $dt0 = $invtables[0]; $dt1 = $invtables[1]; $dt2 = $invtables[2]; $dt3 = $invtables[3]; $isbox = $invtables[4]; '; $s = 'e'; $e = 's'; $wc = $Nb - 1; // Preround: addRoundKey $decrypt_block = '$in = unpack("N*", $in);' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $dw[++$wc] . ';' . "\n"; } // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$' . $e . $i . ' = $dt0[($' . $s . $i . ' >> 24) & 0xff] ^ $dt1[($' . $s . ($Nb + $i - $c[1]) % $Nb . ' >> 16) & 0xff] ^ $dt2[($' . $s . ($Nb + $i - $c[2]) % $Nb . ' >> 8) & 0xff] ^ $dt3[ $' . $s . ($Nb + $i - $c[3]) % $Nb . ' & 0xff] ^ ' . $dw[++$wc] . ";\n"; } } // Finalround: subWord + shiftRows + addRoundKey for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$' . $e . $i . ' = $isbox[ $' . $e . $i . ' & 0xff] | ($isbox[($' . $e . $i . ' >> 8) & 0xff] << 8) | ($isbox[($' . $e . $i . ' >> 16) & 0xff] << 16) | ($isbox[($' . $e . $i . ' >> 24) & 0xff] << 24);' . "\n"; } $decrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= ', ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^ ($' . $e . ($Nb + $i - $c[1]) % $Nb . ' & 0x00FF0000 ) ^ ($' . $e . ($Nb + $i - $c[2]) % $Nb . ' & 0x0000FF00 ) ^ ($' . $e . ($Nb + $i - $c[3]) % $Nb . ' & 0x000000FF ) ^ ' . $dw[$i] . "\n"; } $decrypt_block .= ');'; $lambda_functions[$code_hash] = $this->_createInlineCryptFunction(array('init_crypt' => '', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block)); } $this->inline_crypt = $lambda_functions[$code_hash]; }