[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

phpmyadmin wheezy update ready for review



Hi,

I have completed a port of all pending CVEs and patches for wheezy in
the phpMyAdmin package. Here's the resulting debdiff:

diff -Nru phpmyadmin-3.4.11.1/debian/changelog phpmyadmin-3.4.11.1/debian/changelog
--- phpmyadmin-3.4.11.1/debian/changelog	2015-10-28 14:48:17.000000000 -0400
+++ phpmyadmin-3.4.11.1/debian/changelog	2016-04-22 11:54:07.000000000 -0400
@@ -1,3 +1,16 @@
+phpmyadmin (4:3.4.11.1-2+deb7u3) wheezy-security; urgency=medium
+
+  * Fix security issues:
+    - CVE-2016-1927: suggestPassword generates weak passphrases
+    - CVE-2016-2038: information disclosure via crafted requests
+    - CVE-2016-2039: weak CSRF token values
+    - CVE-2016-2040: XSS vulnerabilities in authenticated users
+    - CVE-2016-2041: information breach in CSRF token comparison
+    - CVE-2016-2045: XSS injection via crafted SQL queries
+    - CVE-2016-2560: XSS injection
+
+ -- Antoine Beaupré <anarcat@debian.org>  Fri, 22 Apr 2016 11:54:07 -0400
+
 phpmyadmin (4:3.4.11.1-2+deb7u2) wheezy-security; urgency=high
 
   * Fix security issues (closes: #774194):
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-1927.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-1927.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-1927.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-1927.patch	2016-04-22 10:54:32.000000000 -0400
@@ -0,0 +1,47 @@
+Description: port password generator from 4.0 to fix CVE-2016-1927
+Origin: vendor, 6a96e67487f2faecb4de4204fee9b96b94020720 2369daa7f5f550797f560e6b46a021e4558c2d72
+Author: Antoine Beaupré <anarcat@debian.org>
+Last-Update: 2016-04-22
+
+--- phpmyadmin-3.4.11.1.orig/js/functions.js
++++ phpmyadmin-3.4.11.1/js/functions.js
+@@ -1,5 +1,38 @@
+ var sql_box_locked=false,only_once_elements=[],ajax_message_init=false;function PMA_prepareForAjaxRequest(a){a.find("input:hidden").is("#ajax_request_hidden")||a.append('<input type="hidden" id="ajax_request_hidden" name="ajax_request" value="true" />')}
+-function suggestPassword(a){var b=a.generated_pw;b.value="";for(i=0;i<16;i++)b.value+="abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ".charAt(Math.floor(Math.random()*53));a.text_pma_pw.value=b.value;a.text_pma_pw2.value=b.value;return true}
++function suggestPassword(passwd_form)
++{
++    // restrict the password to just letters and numbers to avoid problems:
++    // "editors and viewers regard the password as multiple words and
++    // things like double click no longer work"
++    var pwchars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWYXZ";
++    var passwordlength = 16;    // do we want that to be dynamic?  no, keep it simple :)
++    var passwd = passwd_form.generated_pw;
++    var randomWords = new Int32Array(passwordlength);
++
++    passwd.value = '';
++
++    // First we're going to try to use a built-in CSPRNG
++    if (window.crypto && window.crypto.getRandomValues) {
++        window.crypto.getRandomValues(randomWords);
++    }
++    // Because of course IE calls it msCrypto instead of being standard
++    else if (window.msCrypto && window.msCrypto.getRandomValues) {
++        window.msCrypto.getRandomValues(randomWords);
++    } else {
++        // Fallback to Math.random
++        for (var i = 0; i < passwordlength; i++) {
++            randomWords[i] = Math.floor(Math.random() * pwchars.length);
++        }
++    }
++
++    for (var i = 0; i < passwordlength; i++) {
++        passwd.value += pwchars.charAt(Math.abs(randomWords[i]) % pwchars.length);
++    }
++
++    passwd_form.text_pma_pw.value = passwd.value;
++    passwd_form.text_pma_pw2.value = passwd.value;
++    return true;
++}
+ function parseVersionString(a){if(typeof a!="string")return false;var b=0,c=a.split("-");if(c.length>=2)if(c[1].substr(0,2)=="rc")b=-20-parseInt(c[1].substr(2));else if(c[1].substr(0,4)=="beta")b=-40-parseInt(c[1].substr(4));else if(c[1].substr(0,5)=="alpha")b=-60-parseInt(c[1].substr(5));else if(c[1].substr(0,3)=="dev")b=0;var d=a.split(".");a=parseInt(d[0])||0;c=parseInt(d[1])||0;var e=parseInt(d[2])||0;d=parseInt(d[3])||0;return a*1E8+c*1E6+e*1E4+d*100+b}
+ function PMA_current_version(){var a=parseVersionString(pmaversion),b=parseVersionString(PMA_latest_version);$("#li_pma_version").append(PMA_messages.strLatestAvailable+" "+PMA_latest_version);if(b>a){var c=$.sprintf(PMA_messages.strNewerVersion,PMA_latest_version,PMA_latest_date);klass=Math.floor(b/1E4)==Math.floor(a/1E4)?"error":"notice";$("#maincontainer").after('<div class="'+klass+'">'+c+"</div>")}}
+ function displayPasswordGenerateButton(){$("#tr_element_before_generate_password").parent().append("<tr><td>"+PMA_messages.strGeneratePassword+'</td><td><input type="button" id="button_generate_password" value="'+PMA_messages.strGenerate+'" onclick="suggestPassword(this.form)" /><input type="text" name="generated_pw" id="generated_pw" /></td></tr>');$("#div_element_before_generate_password").parent().append('<div class="item"><label for="button_generate_password">'+PMA_messages.strGeneratePassword+
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2038.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2038.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2038.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2038.patch	2016-04-22 10:36:25.000000000 -0400
@@ -0,0 +1,57 @@
+commit ac81596bfcf0b3cae9f6bc821efa4aa1c7f0c81d
+Author: Madhura Jayaratne <madhura.cj@gmail.com>
+Date:   Fri Jan 15 08:12:48 2016 +1100
+
+    [Security] Fix path disclosure, items 1.4.x, 1.5 and 1.6
+    
+    Signed-off-by: Madhura Jayaratne <madhura.cj@gmail.com>
+
+--- a/setup/frames/form.inc.php
++++ b/setup/frames/form.inc.php
+@@ -19,9 +19,9 @@ require_once './setup/lib/form_processin
+ 
+ require './libraries/config/setup.forms.php';
+ 
+-$formset_id = isset($_GET['formset']) ? $_GET['formset'] : null;
++$formset_id = PMA_isValid(isset($_GET['formset'])) ? $_GET['formset'] : null;
+ $mode = isset($_GET['mode']) ? $_GET['mode'] : null;
+-if (!isset($forms[$formset_id])) {
++if (!isset($forms[$formset_id]) || substr($formset_id, 0, 1) === '_') {
+     die('Incorrect formset, check $formsets array in setup/frames/form.inc.php');
+ }
+ 
+--- a/setup/index.php
++++ b/setup/index.php
+@@ -12,7 +12,7 @@
+  */
+ require './lib/common.inc.php';
+ 
+-$page = isset($_GET['page']) ? $_GET['page'] : null;
++$page = PMA_isValid($_GET['page'], 'scalar') ? $_GET['page'] : null;
+ $page = preg_replace('/[^a-z]/', '', $page);
+ if ($page === '') {
+     $page = 'index';
+--- a/setup/validate.php
++++ b/setup/validate.php
+@@ -16,9 +16,9 @@ require './libraries/config/validate.lib
+ 
+ header('Content-type: application/json');
+ 
+-$ids = isset($_POST['id']) ? $_POST['id'] : null;
++$ids = PMA_isValid($_POST['id'], 'scalar') ? $_POST['id'] : null;
+ $vids = explode(',', $ids);
+-$vals = isset($_POST['values']) ? $_POST['values'] : null;
++$vals = PMA_isValid($_POST['values'], 'scalar') ? $_POST['values'] : null;
+ $values = json_decode($vals);
+ if (!($values instanceof stdClass)) {
+     die('Wrong data');
+--- a/libraries/common.inc.php
++++ b/libraries/common.inc.php
+@@ -346,6 +346,7 @@ if ($GLOBALS['PMA_Config']->get('ForceSS
+ }
+ 
+ 
++    require './libraries/select_lang.lib.php';
+ /**
+  * include session handling after the globals, to prevent overwriting
+  */
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2039.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2039.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2039.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2039.patch	2016-04-21 12:17:23.000000000 -0400
@@ -0,0 +1,3943 @@
+Description: fix for CVE-2016-2039
+ This pulls in phpseclib 2.0.1 from PMA 4.6 since just pulling in
+ Random.php is not enough and pulling in later patched versions
+ introduce new vulnerabilities (CVE-2016-2042). Using the system
+ phpseclib is not an option since it's only available from stretch.
+Author: Antoine Beaupré <anarcat@orangeseeds.org>
+Origin: upstream, https://github.com/phpmyadmin/phpmyadmin/commit/6fe54dfa000dd6f43f237e859781fad7111ac1bd
+Reviewed-By: no
+Last-Update: 2016-04-21
+
+--- a/libraries/session.inc.php
++++ b/libraries/session.inc.php
+@@ -15,6 +15,8 @@ if (! defined('PHPMYADMIN')) {
+     exit;
+ }
+ 
++require './libraries/phpseclib/Crypt/Random.php';
++
+ // verify if PHP supports session, die if it does not
+ 
+ if (!@function_exists('session_name')) {
+@@ -97,7 +99,7 @@ if (! isset($_COOKIE[$session_name])) {
+  * (we use "space PMA_token space" to prevent overwriting)
+  */
+ if (!isset($_SESSION[' PMA_token '])) {
+-    $_SESSION[' PMA_token '] = md5(uniqid(rand(), true));
++    $_SESSION[' PMA_token '] = bin2hex(phpseclib\Crypt\Random::string(16));
+ }
+ 
+ /**
+@@ -111,6 +113,6 @@ function PMA_secureSession()
+ {
+     // prevent session fixation and XSS
+     session_regenerate_id(true);
+-    $_SESSION[' PMA_token '] = md5(uniqid(rand(), true));
++    $_SESSION[' PMA_token '] = bin2hex(phpseclib\Crypt\Random::string(16));
+ }
+ ?>
+diff -ruN libraries/phpseclib/Crypt/AES.php ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/AES.php
+--- libraries/phpseclib/Crypt/AES.php	1969-12-31 19:00:00.000000000 -0500
++++ ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/AES.php	2016-03-17 06:11:18.000000000 -0400
+@@ -0,0 +1,131 @@
++<?php
++
++/**
++ * Pure-PHP implementation of AES.
++ *
++ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
++ *
++ * PHP version 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 self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
++ * {@link self::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 self::setKey() setKey()}
++ * is called, again, at which point, it'll be recalculated.
++ *
++ * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
++ * make a whole lot of sense.  {@link self::setBlockLength() setBlockLength()}, for instance.  Calling that function,
++ * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
++ *
++ * Here's a short example of how to use this library:
++ * <code>
++ * <?php
++ *    include 'vendor/autoload.php';
++ *
++ *    $aes = new \phpseclib\Crypt\AES();
++ *
++ *    $aes->setKey('abcdefghijklmnop');
++ *
++ *    $size = 10 * 1024;
++ *    $plaintext = '';
++ *    for ($i = 0; $i < $size; $i++) {
++ *        $plaintext.= 'a';
++ *    }
++ *
++ *    echo $aes->decrypt($aes->encrypt($plaintext));
++ * ?>
++ * </code>
++ *
++ * @category  Crypt
++ * @package   AES
++ * @author    Jim Wigginton <terrafrost@php.net>
++ * @copyright 2008 Jim Wigginton
++ * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
++ * @link      http://phpseclib.sourceforge.net
++ */
++namespace phpseclib\Crypt;
++
++if (! defined('PHPMYADMIN')) {
++    exit;
++}
++
++use phpseclib\Crypt\Rijndael;
++
++/**
++ * Pure-PHP implementation of AES.
++ *
++ * @package AES
++ * @author  Jim Wigginton <terrafrost@php.net>
++ * @access  public
++ */
++class AES extends Rijndael
++{
++    /**
++     * Dummy function
++     *
++     * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
++     *
++     * @see \phpseclib\Crypt\Rijndael::setBlockLength()
++     * @access public
++     * @param int $length
++     */
++    function setBlockLength($length)
++    {
++        return;
++    }
++
++    /**
++     * Sets the key length
++     *
++     * Valid key lengths are 128, 192, and 256.  If the length is less than 128, it will be rounded up to
++     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
++     *
++     * @see \phpseclib\Crypt\Rijndael:setKeyLength()
++     * @access public
++     * @param int $length
++     */
++    function setKeyLength($length)
++    {
++        switch ($length) {
++            case 160:
++                $length = 192;
++                break;
++            case 224:
++                $length = 256;
++        }
++        parent::setKeyLength($length);
++    }
++
++    /**
++     * Sets the key.
++     *
++     * Rijndael supports five different key lengths, AES only supports three.
++     *
++     * @see \phpseclib\Crypt\Rijndael:setKey()
++     * @see setKeyLength()
++     * @access public
++     * @param string $key
++     */
++    function setKey($key)
++    {
++        parent::setKey($key);
++
++        if (!$this->explicit_key_length) {
++            $length = strlen($key);
++            switch (true) {
++                case $length <= 16:
++                    $this->key_length = 16;
++                    break;
++                case $length <= 24:
++                    $this->key_length = 24;
++                    break;
++                default:
++                    $this->key_length = 32;
++            }
++            $this->_setEngine();
++        }
++    }
++}
+diff -ruN libraries/phpseclib/Crypt/Base.php ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Base.php
+--- libraries/phpseclib/Crypt/Base.php	1969-12-31 19:00:00.000000000 -0500
++++ ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Base.php	2016-03-17 06:11:18.000000000 -0400
+@@ -0,0 +1,2549 @@
++<?php
++
++/**
++ * Base Class for all \phpseclib\Crypt\* cipher classes
++ *
++ * PHP version 5
++ *
++ * Internally for phpseclib developers:
++ *  If you plan to add a new cipher class, please note following rules:
++ *
++ *  - The new \phpseclib\Crypt\* cipher class should extend \phpseclib\Crypt\Base
++ *
++ *  - Following methods are then required to be overridden/overloaded:
++ *
++ *    - _encryptBlock()
++ *
++ *    - _decryptBlock()
++ *
++ *    - _setupKey()
++ *
++ *  - All other methods are optional to be overridden/overloaded
++ *
++ *  - Look at the source code of the current ciphers how they extend \phpseclib\Crypt\Base
++ *    and take one of them as a start up for the new cipher class.
++ *
++ *  - Please read all the other comments/notes/hints here also for each class var/method
++ *
++ * @category  Crypt
++ * @package   Base
++ * @author    Jim Wigginton <terrafrost@php.net>
++ * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
++ * @copyright 2007 Jim Wigginton
++ * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
++ * @link      http://phpseclib.sourceforge.net
++ */
++
++namespace phpseclib\Crypt;
++
++use phpseclib\Crypt\Hash;
++
++/**
++ * Base Class for all \phpseclib\Crypt\* cipher classes
++ *
++ * @package Base
++ * @author  Jim Wigginton <terrafrost@php.net>
++ * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
++ */
++abstract class Base
++{
++    /**#@+
++     * @access public
++     * @see \phpseclib\Crypt\Base::encrypt()
++     * @see \phpseclib\Crypt\Base::decrypt()
++     */
++    /**
++     * Encrypt / decrypt using the Counter mode.
++     *
++     * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
++     *
++     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
++     */
++    const MODE_CTR = -1;
++    /**
++     * Encrypt / decrypt using the Electronic Code Book mode.
++     *
++     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
++     */
++    const MODE_ECB = 1;
++    /**
++     * Encrypt / decrypt using the Code Book Chaining mode.
++     *
++     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
++     */
++    const MODE_CBC = 2;
++    /**
++     * Encrypt / decrypt using the Cipher Feedback mode.
++     *
++     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
++     */
++    const MODE_CFB = 3;
++    /**
++     * Encrypt / decrypt using the Output Feedback mode.
++     *
++     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
++     */
++    const MODE_OFB = 4;
++    /**
++     * Encrypt / decrypt using streaming mode.
++     */
++    const MODE_STREAM = 5;
++    /**#@-*/
++
++    /**
++     * Whirlpool available flag
++     *
++     * @see \phpseclib\Crypt\Base::_hashInlineCryptFunction()
++     * @var bool
++     * @access private
++     */
++    static $WHIRLPOOL_AVAILABLE;
++
++    /**#@+
++     * @access private
++     * @see \phpseclib\Crypt\Base::__construct()
++     */
++    /**
++     * Base value for the internal implementation $engine switch
++     */
++    const ENGINE_INTERNAL = 1;
++    /**
++     * Base value for the mcrypt implementation $engine switch
++     */
++    const ENGINE_MCRYPT = 2;
++    /**
++     * Base value for the mcrypt implementation $engine switch
++     */
++    const ENGINE_OPENSSL = 3;
++    /**#@-*/
++
++    /**
++     * The Encryption Mode
++     *
++     * @see self::__construct()
++     * @var int
++     * @access private
++     */
++    var $mode;
++
++    /**
++     * The Block Length of the block cipher
++     *
++     * @var int
++     * @access private
++     */
++    var $block_size = 16;
++
++    /**
++     * The Key
++     *
++     * @see self::setKey()
++     * @var string
++     * @access private
++     */
++    var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
++
++    /**
++     * The Initialization Vector
++     *
++     * @see self::setIV()
++     * @var string
++     * @access private
++     */
++    var $iv;
++
++    /**
++     * A "sliding" Initialization Vector
++     *
++     * @see self::enableContinuousBuffer()
++     * @see self::_clearBuffers()
++     * @var string
++     * @access private
++     */
++    var $encryptIV;
++
++    /**
++     * A "sliding" Initialization Vector
++     *
++     * @see self::enableContinuousBuffer()
++     * @see self::_clearBuffers()
++     * @var string
++     * @access private
++     */
++    var $decryptIV;
++
++    /**
++     * Continuous Buffer status
++     *
++     * @see self::enableContinuousBuffer()
++     * @var bool
++     * @access private
++     */
++    var $continuousBuffer = false;
++
++    /**
++     * Encryption buffer for CTR, OFB and CFB modes
++     *
++     * @see self::encrypt()
++     * @see self::_clearBuffers()
++     * @var array
++     * @access private
++     */
++    var $enbuffer;
++
++    /**
++     * Decryption buffer for CTR, OFB and CFB modes
++     *
++     * @see self::decrypt()
++     * @see self::_clearBuffers()
++     * @var array
++     * @access private
++     */
++    var $debuffer;
++
++    /**
++     * mcrypt resource for encryption
++     *
++     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
++     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
++     *
++     * @see self::encrypt()
++     * @var resource
++     * @access private
++     */
++    var $enmcrypt;
++
++    /**
++     * mcrypt resource for decryption
++     *
++     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
++     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
++     *
++     * @see self::decrypt()
++     * @var resource
++     * @access private
++     */
++    var $demcrypt;
++
++    /**
++     * Does the enmcrypt resource need to be (re)initialized?
++     *
++     * @see \phpseclib\Crypt\Twofish::setKey()
++     * @see \phpseclib\Crypt\Twofish::setIV()
++     * @var bool
++     * @access private
++     */
++    var $enchanged = true;
++
++    /**
++     * Does the demcrypt resource need to be (re)initialized?
++     *
++     * @see \phpseclib\Crypt\Twofish::setKey()
++     * @see \phpseclib\Crypt\Twofish::setIV()
++     * @var bool
++     * @access private
++     */
++    var $dechanged = true;
++
++    /**
++     * mcrypt resource for CFB mode
++     *
++     * mcrypt's CFB mode, in (and only in) buffered context,
++     * is broken, so phpseclib implements the CFB mode by it self,
++     * even when the mcrypt php extension is available.
++     *
++     * In order to do the CFB-mode work (fast) phpseclib
++     * use a separate ECB-mode mcrypt resource.
++     *
++     * @link http://phpseclib.sourceforge.net/cfb-demo.phps
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @see self::_setupMcrypt()
++     * @var resource
++     * @access private
++     */
++    var $ecb;
++
++    /**
++     * Optimizing value while CFB-encrypting
++     *
++     * Only relevant if $continuousBuffer enabled
++     * and $engine == self::ENGINE_MCRYPT
++     *
++     * It's faster to re-init $enmcrypt if
++     * $buffer bytes > $cfb_init_len than
++     * using the $ecb resource furthermore.
++     *
++     * This value depends of the chosen cipher
++     * and the time it would be needed for it's
++     * initialization [by mcrypt_generic_init()]
++     * which, typically, depends on the complexity
++     * on its internaly Key-expanding algorithm.
++     *
++     * @see self::encrypt()
++     * @var int
++     * @access private
++     */
++    var $cfb_init_len = 600;
++
++    /**
++     * Does internal cipher state need to be (re)initialized?
++     *
++     * @see self::setKey()
++     * @see self::setIV()
++     * @see self::disableContinuousBuffer()
++     * @var bool
++     * @access private
++     */
++    var $changed = true;
++
++    /**
++     * Padding status
++     *
++     * @see self::enablePadding()
++     * @var bool
++     * @access private
++     */
++    var $padding = true;
++
++    /**
++     * Is the mode one that is paddable?
++     *
++     * @see self::__construct()
++     * @var bool
++     * @access private
++     */
++    var $paddable = false;
++
++    /**
++     * Holds which crypt engine internaly should be use,
++     * which will be determined automatically on __construct()
++     *
++     * Currently available $engines are:
++     * - self::ENGINE_OPENSSL  (very fast, php-extension: openssl, extension_loaded('openssl') required)
++     * - self::ENGINE_MCRYPT   (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
++     * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
++     *
++     * @see self::_setEngine()
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @var int
++     * @access private
++     */
++    var $engine;
++
++    /**
++     * Holds the preferred crypt engine
++     *
++     * @see self::_setEngine()
++     * @see self::setPreferredEngine()
++     * @var int
++     * @access private
++     */
++    var $preferredEngine;
++
++    /**
++     * The mcrypt specific name of the cipher
++     *
++     * Only used if $engine == self::ENGINE_MCRYPT
++     *
++     * @link http://www.php.net/mcrypt_module_open
++     * @link http://www.php.net/mcrypt_list_algorithms
++     * @see self::_setupMcrypt()
++     * @var string
++     * @access private
++     */
++    var $cipher_name_mcrypt;
++
++    /**
++     * The openssl specific name of the cipher
++     *
++     * Only used if $engine == self::ENGINE_OPENSSL
++     *
++     * @link http://www.php.net/openssl-get-cipher-methods
++     * @var string
++     * @access private
++     */
++    var $cipher_name_openssl;
++
++    /**
++     * The openssl specific name of the cipher in ECB mode
++     *
++     * If OpenSSL does not support the mode we're trying to use (CTR)
++     * it can still be emulated with ECB mode.
++     *
++     * @link http://www.php.net/openssl-get-cipher-methods
++     * @var string
++     * @access private
++     */
++    var $cipher_name_openssl_ecb;
++
++    /**
++     * The default salt used by setPassword()
++     *
++     * @see self::setPassword()
++     * @var string
++     * @access private
++     */
++    var $password_default_salt = 'phpseclib/salt';
++
++    /**
++     * The name of the performance-optimized callback function
++     *
++     * Used by encrypt() / decrypt()
++     * only if $engine == self::ENGINE_INTERNAL
++     *
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @see self::_setupInlineCrypt()
++     * @see self::$use_inline_crypt
++     * @var Callback
++     * @access private
++     */
++    var $inline_crypt;
++
++    /**
++     * Holds whether performance-optimized $inline_crypt() can/should be used.
++     *
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @see self::inline_crypt
++     * @var mixed
++     * @access private
++     */
++    var $use_inline_crypt;
++
++    /**
++     * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
++     *
++     * @see self::_openssl_ctr_process()
++     * @var bool
++     * @access private
++     */
++    var $openssl_emulate_ctr = false;
++
++    /**
++     * Determines what options are passed to openssl_encrypt/decrypt
++     *
++     * @see self::isValidEngine()
++     * @var mixed
++     * @access private
++     */
++    var $openssl_options;
++
++    /**
++     * Has the key length explicitly been set or should it be derived from the key, itself?
++     *
++     * @see self::setKeyLength()
++     * @var bool
++     * @access private
++     */
++    var $explicit_key_length = false;
++
++    /**
++     * Don't truncate / null pad key
++     *
++     * @see self::_clearBuffers()
++     * @var bool
++     * @access private
++     */
++    var $skip_key_adjustment = false;
++
++    /**
++     * Default Constructor.
++     *
++     * Determines whether or not the mcrypt extension should be used.
++     *
++     * $mode could be:
++     *
++     * - self::MODE_ECB
++     *
++     * - self::MODE_CBC
++     *
++     * - self::MODE_CTR
++     *
++     * - self::MODE_CFB
++     *
++     * - self::MODE_OFB
++     *
++     * If not explicitly set, self::MODE_CBC will be used.
++     *
++     * @param int $mode
++     * @access public
++     */
++    function __construct($mode = self::MODE_CBC)
++    {
++        // $mode dependent settings
++        switch ($mode) {
++            case self::MODE_ECB:
++                $this->paddable = true;
++                $this->mode = self::MODE_ECB;
++                break;
++            case self::MODE_CTR:
++            case self::MODE_CFB:
++            case self::MODE_OFB:
++            case self::MODE_STREAM:
++                $this->mode = $mode;
++                break;
++            case self::MODE_CBC:
++            default:
++                $this->paddable = true;
++                $this->mode = self::MODE_CBC;
++        }
++
++        $this->_setEngine();
++
++        // Determining whether inline crypting can be used by the cipher
++        if ($this->use_inline_crypt !== false && function_exists('create_function')) {
++            $this->use_inline_crypt = true;
++        }
++    }
++
++    /**
++     * Sets the initialization vector. (optional)
++     *
++     * SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used.  If not explicitly set, it'll be assumed
++     * to be all zero's.
++     *
++     * @access public
++     * @param string $iv
++     * @internal Can be overwritten by a sub class, but does not have to be
++     */
++    function setIV($iv)
++    {
++        if ($this->mode == self::MODE_ECB) {
++            return;
++        }
++
++        $this->iv = $iv;
++        $this->changed = true;
++    }
++
++    /**
++     * Sets the key length.
++     *
++     * Keys with explicitly set lengths need to be treated accordingly
++     *
++     * @access public
++     * @param int $length
++     */
++    function setKeyLength($length)
++    {
++        $this->explicit_key_length = true;
++        $this->changed = true;
++        $this->_setEngine();
++    }
++
++    /**
++     * Returns the current key length in bits
++     *
++     * @access public
++     * @return int
++     */
++    function getKeyLength()
++    {
++        return $this->key_length << 3;
++    }
++
++    /**
++     * Returns the current block length in bits
++     *
++     * @access public
++     * @return int
++     */
++    function getBlockLength()
++    {
++        return $this->block_size << 3;
++    }
++
++    /**
++     * Sets the key.
++     *
++     * The min/max length(s) of the key depends on the cipher which is used.
++     * If the key not fits the length(s) of the cipher it will paded with null bytes
++     * up to the closest valid key length.  If the key is more than max length,
++     * we trim the excess bits.
++     *
++     * If the key is not explicitly set, it'll be assumed to be all null bytes.
++     *
++     * @access public
++     * @param string $key
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function setKey($key)
++    {
++        if (!$this->explicit_key_length) {
++            $this->setKeyLength(strlen($key) << 3);
++            $this->explicit_key_length = false;
++        }
++
++        $this->key = $key;
++        $this->changed = true;
++        $this->_setEngine();
++    }
++
++    /**
++     * Sets the password.
++     *
++     * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
++     *     {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
++     *         $hash, $salt, $count, $dkLen
++     *
++     *         Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
++     *
++     * @see Crypt/Hash.php
++     * @param string $password
++     * @param string $method
++     * @return bool
++     * @access public
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function setPassword($password, $method = 'pbkdf2')
++    {
++        $key = '';
++
++        switch ($method) {
++            default: // 'pbkdf2' or 'pbkdf1'
++                $func_args = func_get_args();
++
++                // Hash function
++                $hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
++
++                // WPA and WPA2 use the SSID as the salt
++                $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
++
++                // RFC2898#section-4.2 uses 1,000 iterations by default
++                // WPA and WPA2 use 4,096.
++                $count = isset($func_args[4]) ? $func_args[4] : 1000;
++
++                // Keylength
++                if (isset($func_args[5])) {
++                    $dkLen = $func_args[5];
++                } else {
++                    $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
++                }
++
++                switch (true) {
++                    case $method == 'pbkdf1':
++                        $hashObj = new Hash();
++                        $hashObj->setHash($hash);
++                        if ($dkLen > $hashObj->getLength()) {
++                            user_error('Derived key too long');
++                            return false;
++                        }
++                        $t = $password . $salt;
++                        for ($i = 0; $i < $count; ++$i) {
++                            $t = $hashObj->hash($t);
++                        }
++                        $key = substr($t, 0, $dkLen);
++
++                        $this->setKey(substr($key, 0, $dkLen >> 1));
++                        $this->setIV(substr($key, $dkLen >> 1));
++
++                        return true;
++                    // Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
++                    case !function_exists('hash_pbkdf2'):
++                    case !function_exists('hash_algos'):
++                    case !in_array($hash, hash_algos()):
++                        $i = 1;
++                        while (strlen($key) < $dkLen) {
++                            $hmac = new Hash();
++                            $hmac->setHash($hash);
++                            $hmac->setKey($password);
++                            $f = $u = $hmac->hash($salt . pack('N', $i++));
++                            for ($j = 2; $j <= $count; ++$j) {
++                                $u = $hmac->hash($u);
++                                $f^= $u;
++                            }
++                            $key.= $f;
++                        }
++                        $key = substr($key, 0, $dkLen);
++                        break;
++                    default:
++                        $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
++                }
++        }
++
++        $this->setKey($key);
++
++        return true;
++    }
++
++    /**
++     * Encrypts a message.
++     *
++     * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
++     * implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
++     * necessary are discussed in the following
++     * URL:
++     *
++     * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
++     *
++     * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
++     * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
++     * length.
++     *
++     * @see self::decrypt()
++     * @access public
++     * @param string $plaintext
++     * @return string $ciphertext
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function encrypt($plaintext)
++    {
++        if ($this->paddable) {
++            $plaintext = $this->_pad($plaintext);
++        }
++
++        if ($this->engine === self::ENGINE_OPENSSL) {
++            if ($this->changed) {
++                $this->_clearBuffers();
++                $this->changed = false;
++            }
++            switch ($this->mode) {
++                case self::MODE_STREAM:
++                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
++                case self::MODE_ECB:
++                    $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
++                    return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
++                case self::MODE_CBC:
++                    $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
++                    if ($this->continuousBuffer) {
++                        $this->encryptIV = substr($result, -$this->block_size);
++                    }
++                    return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
++                case self::MODE_CTR:
++                    return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
++                case self::MODE_CFB:
++                    // cfb loosely routines inspired by openssl's:
++                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
++                    $ciphertext = '';
++                    if ($this->continuousBuffer) {
++                        $iv = &$this->encryptIV;
++                        $pos = &$this->enbuffer['pos'];
++                    } else {
++                        $iv = $this->encryptIV;
++                        $pos = 0;
++                    }
++                    $len = strlen($plaintext);
++                    $i = 0;
++                    if ($pos) {
++                        $orig_pos = $pos;
++                        $max = $this->block_size - $pos;
++                        if ($len >= $max) {
++                            $i = $max;
++                            $len-= $max;
++                            $pos = 0;
++                        } else {
++                            $i = $len;
++                            $pos+= $len;
++                            $len = 0;
++                        }
++                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
++                        $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
++                        $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
++                        $plaintext = substr($plaintext, $i);
++                    }
++
++                    $overflow = $len % $this->block_size;
++
++                    if ($overflow) {
++                        $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
++                        $iv = $this->_string_pop($ciphertext, $this->block_size);
++
++                        $size = $len - $overflow;
++                        $block = $iv ^ substr($plaintext, -$overflow);
++                        $iv = substr_replace($iv, $block, 0, $overflow);
++                        $ciphertext.= $block;
++                        $pos = $overflow;
++                    } elseif ($len) {
++                        $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
++                        $iv = substr($ciphertext, -$this->block_size);
++                    }
++
++                    return $ciphertext;
++                case self::MODE_OFB:
++                    return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
++            }
++        }
++
++        if ($this->engine === self::ENGINE_MCRYPT) {
++            if ($this->changed) {
++                $this->_setupMcrypt();
++                $this->changed = false;
++            }
++            if ($this->enchanged) {
++                mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
++                $this->enchanged = false;
++            }
++
++            // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
++            // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
++            // rewritten CFB implementation the above outputs the same thing twice.
++            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
++                $block_size = $this->block_size;
++                $iv = &$this->encryptIV;
++                $pos = &$this->enbuffer['pos'];
++                $len = strlen($plaintext);
++                $ciphertext = '';
++                $i = 0;
++                if ($pos) {
++                    $orig_pos = $pos;
++                    $max = $block_size - $pos;
++                    if ($len >= $max) {
++                        $i = $max;
++                        $len-= $max;
++                        $pos = 0;
++                    } else {
++                        $i = $len;
++                        $pos+= $len;
++                        $len = 0;
++                    }
++                    $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
++                    $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
++                    $this->enbuffer['enmcrypt_init'] = true;
++                }
++                if ($len >= $block_size) {
++                    if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
++                        if ($this->enbuffer['enmcrypt_init'] === true) {
++                            mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
++                            $this->enbuffer['enmcrypt_init'] = false;
++                        }
++                        $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
++                        $iv = substr($ciphertext, -$block_size);
++                        $len%= $block_size;
++                    } else {
++                        while ($len >= $block_size) {
++                            $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
++                            $ciphertext.= $iv;
++                            $len-= $block_size;
++                            $i+= $block_size;
++                        }
++                    }
++                }
++
++                if ($len) {
++                    $iv = mcrypt_generic($this->ecb, $iv);
++                    $block = $iv ^ substr($plaintext, -$len);
++                    $iv = substr_replace($iv, $block, 0, $len);
++                    $ciphertext.= $block;
++                    $pos = $len;
++                }
++
++                return $ciphertext;
++            }
++
++            $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
++
++            if (!$this->continuousBuffer) {
++                mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
++            }
++
++            return $ciphertext;
++        }
++
++        if ($this->changed) {
++            $this->_setup();
++            $this->changed = false;
++        }
++        if ($this->use_inline_crypt) {
++            $inline = $this->inline_crypt;
++            return $inline('encrypt', $this, $plaintext);
++        }
++
++        $buffer = &$this->enbuffer;
++        $block_size = $this->block_size;
++        $ciphertext = '';
++        switch ($this->mode) {
++            case self::MODE_ECB:
++                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                    $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
++                }
++                break;
++            case self::MODE_CBC:
++                $xor = $this->encryptIV;
++                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                    $block = substr($plaintext, $i, $block_size);
++                    $block = $this->_encryptBlock($block ^ $xor);
++                    $xor = $block;
++                    $ciphertext.= $block;
++                }
++                if ($this->continuousBuffer) {
++                    $this->encryptIV = $xor;
++                }
++                break;
++            case self::MODE_CTR:
++                $xor = $this->encryptIV;
++                if (strlen($buffer['ciphertext'])) {
++                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                        $block = substr($plaintext, $i, $block_size);
++                        if (strlen($block) > strlen($buffer['ciphertext'])) {
++                            $buffer['ciphertext'].= $this->_encryptBlock($xor);
++                        }
++                        $this->_increment_str($xor);
++                        $key = $this->_string_shift($buffer['ciphertext'], $block_size);
++                        $ciphertext.= $block ^ $key;
++                    }
++                } else {
++                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                        $block = substr($plaintext, $i, $block_size);
++                        $key = $this->_encryptBlock($xor);
++                        $this->_increment_str($xor);
++                        $ciphertext.= $block ^ $key;
++                    }
++                }
++                if ($this->continuousBuffer) {
++                    $this->encryptIV = $xor;
++                    if ($start = strlen($plaintext) % $block_size) {
++                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
++                    }
++                }
++                break;
++            case self::MODE_CFB:
++                // cfb loosely routines inspired by openssl's:
++                // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
++                if ($this->continuousBuffer) {
++                    $iv = &$this->encryptIV;
++                    $pos = &$buffer['pos'];
++                } else {
++                    $iv = $this->encryptIV;
++                    $pos = 0;
++                }
++                $len = strlen($plaintext);
++                $i = 0;
++                if ($pos) {
++                    $orig_pos = $pos;
++                    $max = $block_size - $pos;
++                    if ($len >= $max) {
++                        $i = $max;
++                        $len-= $max;
++                        $pos = 0;
++                    } else {
++                        $i = $len;
++                        $pos+= $len;
++                        $len = 0;
++                    }
++                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
++                    $ciphertext = substr($iv, $orig_pos) ^ $plaintext;
++                    $iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
++                }
++                while ($len >= $block_size) {
++                    $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
++                    $ciphertext.= $iv;
++                    $len-= $block_size;
++                    $i+= $block_size;
++                }
++                if ($len) {
++                    $iv = $this->_encryptBlock($iv);
++                    $block = $iv ^ substr($plaintext, $i);
++                    $iv = substr_replace($iv, $block, 0, $len);
++                    $ciphertext.= $block;
++                    $pos = $len;
++                }
++                break;
++            case self::MODE_OFB:
++                $xor = $this->encryptIV;
++                if (strlen($buffer['xor'])) {
++                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                        $block = substr($plaintext, $i, $block_size);
++                        if (strlen($block) > strlen($buffer['xor'])) {
++                            $xor = $this->_encryptBlock($xor);
++                            $buffer['xor'].= $xor;
++                        }
++                        $key = $this->_string_shift($buffer['xor'], $block_size);
++                        $ciphertext.= $block ^ $key;
++                    }
++                } else {
++                    for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                        $xor = $this->_encryptBlock($xor);
++                        $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
++                    }
++                    $key = $xor;
++                }
++                if ($this->continuousBuffer) {
++                    $this->encryptIV = $xor;
++                    if ($start = strlen($plaintext) % $block_size) {
++                        $buffer['xor'] = substr($key, $start) . $buffer['xor'];
++                    }
++                }
++                break;
++            case self::MODE_STREAM:
++                $ciphertext = $this->_encryptBlock($plaintext);
++                break;
++        }
++
++        return $ciphertext;
++    }
++
++    /**
++     * Decrypts a message.
++     *
++     * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
++     * it is.
++     *
++     * @see self::encrypt()
++     * @access public
++     * @param string $ciphertext
++     * @return string $plaintext
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function decrypt($ciphertext)
++    {
++        if ($this->paddable) {
++            // we pad with chr(0) since that's what mcrypt_generic does.  to quote from {@link http://www.php.net/function.mcrypt-generic}:
++            // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
++            $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
++        }
++
++        if ($this->engine === self::ENGINE_OPENSSL) {
++            if ($this->changed) {
++                $this->_clearBuffers();
++                $this->changed = false;
++            }
++            switch ($this->mode) {
++                case self::MODE_STREAM:
++                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
++                    break;
++                case self::MODE_ECB:
++                    if (!defined('OPENSSL_RAW_DATA')) {
++                        $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
++                    }
++                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
++                    break;
++                case self::MODE_CBC:
++                    if (!defined('OPENSSL_RAW_DATA')) {
++                        $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
++                        $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
++                    }
++                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
++                    if ($this->continuousBuffer) {
++                        $this->decryptIV = substr($ciphertext, -$this->block_size);
++                    }
++                    break;
++                case self::MODE_CTR:
++                    $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
++                    break;
++                case self::MODE_CFB:
++                    // cfb loosely routines inspired by openssl's:
++                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
++                    $plaintext = '';
++                    if ($this->continuousBuffer) {
++                        $iv = &$this->decryptIV;
++                        $pos = &$this->buffer['pos'];
++                    } else {
++                        $iv = $this->decryptIV;
++                        $pos = 0;
++                    }
++                    $len = strlen($ciphertext);
++                    $i = 0;
++                    if ($pos) {
++                        $orig_pos = $pos;
++                        $max = $this->block_size - $pos;
++                        if ($len >= $max) {
++                            $i = $max;
++                            $len-= $max;
++                            $pos = 0;
++                        } else {
++                            $i = $len;
++                            $pos+= $len;
++                            $len = 0;
++                        }
++                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
++                        $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
++                        $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
++                        $ciphertext = substr($ciphertext, $i);
++                    }
++                    $overflow = $len % $this->block_size;
++                    if ($overflow) {
++                        $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
++                        if ($len - $overflow) {
++                            $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
++                        }
++                        $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
++                        $plaintext.= $iv ^ substr($ciphertext, -$overflow);
++                        $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
++                        $pos = $overflow;
++                    } elseif ($len) {
++                        $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
++                        $iv = substr($ciphertext, -$this->block_size);
++                    }
++                    break;
++                case self::MODE_OFB:
++                    $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
++            }
++
++            return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
++        }
++
++        if ($this->engine === self::ENGINE_MCRYPT) {
++            $block_size = $this->block_size;
++            if ($this->changed) {
++                $this->_setupMcrypt();
++                $this->changed = false;
++            }
++            if ($this->dechanged) {
++                mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
++                $this->dechanged = false;
++            }
++
++            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
++                $iv = &$this->decryptIV;
++                $pos = &$this->debuffer['pos'];
++                $len = strlen($ciphertext);
++                $plaintext = '';
++                $i = 0;
++                if ($pos) {
++                    $orig_pos = $pos;
++                    $max = $block_size - $pos;
++                    if ($len >= $max) {
++                        $i = $max;
++                        $len-= $max;
++                        $pos = 0;
++                    } else {
++                        $i = $len;
++                        $pos+= $len;
++                        $len = 0;
++                    }
++                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
++                    $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
++                    $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
++                }
++                if ($len >= $block_size) {
++                    $cb = substr($ciphertext, $i, $len - $len % $block_size);
++                    $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
++                    $iv = substr($cb, -$block_size);
++                    $len%= $block_size;
++                }
++                if ($len) {
++                    $iv = mcrypt_generic($this->ecb, $iv);
++                    $plaintext.= $iv ^ substr($ciphertext, -$len);
++                    $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
++                    $pos = $len;
++                }
++
++                return $plaintext;
++            }
++
++            $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
++
++            if (!$this->continuousBuffer) {
++                mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
++            }
++
++            return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
++        }
++
++        if ($this->changed) {
++            $this->_setup();
++            $this->changed = false;
++        }
++        if ($this->use_inline_crypt) {
++            $inline = $this->inline_crypt;
++            return $inline('decrypt', $this, $ciphertext);
++        }
++
++        $block_size = $this->block_size;
++
++        $buffer = &$this->debuffer;
++        $plaintext = '';
++        switch ($this->mode) {
++            case self::MODE_ECB:
++                for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                    $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
++                }
++                break;
++            case self::MODE_CBC:
++                $xor = $this->decryptIV;
++                for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                    $block = substr($ciphertext, $i, $block_size);
++                    $plaintext.= $this->_decryptBlock($block) ^ $xor;
++                    $xor = $block;
++                }
++                if ($this->continuousBuffer) {
++                    $this->decryptIV = $xor;
++                }
++                break;
++            case self::MODE_CTR:
++                $xor = $this->decryptIV;
++                if (strlen($buffer['ciphertext'])) {
++                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                        $block = substr($ciphertext, $i, $block_size);
++                        if (strlen($block) > strlen($buffer['ciphertext'])) {
++                            $buffer['ciphertext'].= $this->_encryptBlock($xor);
++                            $this->_increment_str($xor);
++                        }
++                        $key = $this->_string_shift($buffer['ciphertext'], $block_size);
++                        $plaintext.= $block ^ $key;
++                    }
++                } else {
++                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                        $block = substr($ciphertext, $i, $block_size);
++                        $key = $this->_encryptBlock($xor);
++                        $this->_increment_str($xor);
++                        $plaintext.= $block ^ $key;
++                    }
++                }
++                if ($this->continuousBuffer) {
++                    $this->decryptIV = $xor;
++                    if ($start = strlen($ciphertext) % $block_size) {
++                        $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
++                    }
++                }
++                break;
++            case self::MODE_CFB:
++                if ($this->continuousBuffer) {
++                    $iv = &$this->decryptIV;
++                    $pos = &$buffer['pos'];
++                } else {
++                    $iv = $this->decryptIV;
++                    $pos = 0;
++                }
++                $len = strlen($ciphertext);
++                $i = 0;
++                if ($pos) {
++                    $orig_pos = $pos;
++                    $max = $block_size - $pos;
++                    if ($len >= $max) {
++                        $i = $max;
++                        $len-= $max;
++                        $pos = 0;
++                    } else {
++                        $i = $len;
++                        $pos+= $len;
++                        $len = 0;
++                    }
++                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
++                    $plaintext = substr($iv, $orig_pos) ^ $ciphertext;
++                    $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
++                }
++                while ($len >= $block_size) {
++                    $iv = $this->_encryptBlock($iv);
++                    $cb = substr($ciphertext, $i, $block_size);
++                    $plaintext.= $iv ^ $cb;
++                    $iv = $cb;
++                    $len-= $block_size;
++                    $i+= $block_size;
++                }
++                if ($len) {
++                    $iv = $this->_encryptBlock($iv);
++                    $plaintext.= $iv ^ substr($ciphertext, $i);
++                    $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
++                    $pos = $len;
++                }
++                break;
++            case self::MODE_OFB:
++                $xor = $this->decryptIV;
++                if (strlen($buffer['xor'])) {
++                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                        $block = substr($ciphertext, $i, $block_size);
++                        if (strlen($block) > strlen($buffer['xor'])) {
++                            $xor = $this->_encryptBlock($xor);
++                            $buffer['xor'].= $xor;
++                        }
++                        $key = $this->_string_shift($buffer['xor'], $block_size);
++                        $plaintext.= $block ^ $key;
++                    }
++                } else {
++                    for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
++                        $xor = $this->_encryptBlock($xor);
++                        $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
++                    }
++                    $key = $xor;
++                }
++                if ($this->continuousBuffer) {
++                    $this->decryptIV = $xor;
++                    if ($start = strlen($ciphertext) % $block_size) {
++                        $buffer['xor'] = substr($key, $start) . $buffer['xor'];
++                    }
++                }
++                break;
++            case self::MODE_STREAM:
++                $plaintext = $this->_decryptBlock($ciphertext);
++                break;
++        }
++        return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
++    }
++
++    /**
++     * OpenSSL CTR Processor
++     *
++     * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
++     * for CTR is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
++     * and Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
++     * function will emulate CTR with ECB when necesary.
++     *
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @param string $plaintext
++     * @param string $encryptIV
++     * @param array $buffer
++     * @return string
++     * @access private
++     */
++    function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
++    {
++        $ciphertext = '';
++
++        $block_size = $this->block_size;
++        $key = $this->key;
++
++        if ($this->openssl_emulate_ctr) {
++            $xor = $encryptIV;
++            if (strlen($buffer['ciphertext'])) {
++                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                    $block = substr($plaintext, $i, $block_size);
++                    if (strlen($block) > strlen($buffer['ciphertext'])) {
++                        $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
++                        $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
++                        $buffer['ciphertext'].= $result;
++                    }
++                    $this->_increment_str($xor);
++                    $otp = $this->_string_shift($buffer['ciphertext'], $block_size);
++                    $ciphertext.= $block ^ $otp;
++                }
++            } else {
++                for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
++                    $block = substr($plaintext, $i, $block_size);
++                    $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
++                    $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
++                    $this->_increment_str($xor);
++                    $ciphertext.= $block ^ $otp;
++                }
++            }
++            if ($this->continuousBuffer) {
++                $encryptIV = $xor;
++                if ($start = strlen($plaintext) % $block_size) {
++                    $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
++                }
++            }
++
++            return $ciphertext;
++        }
++
++        if (strlen($buffer['ciphertext'])) {
++            $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
++            $plaintext = substr($plaintext, strlen($ciphertext));
++
++            if (!strlen($plaintext)) {
++                return $ciphertext;
++            }
++        }
++
++        $overflow = strlen($plaintext) % $block_size;
++        if ($overflow) {
++            $plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
++            $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
++            $temp = $this->_string_pop($encrypted, $block_size);
++            $ciphertext.= $encrypted . ($plaintext2 ^ $temp);
++            if ($this->continuousBuffer) {
++                $buffer['ciphertext'] = substr($temp, $overflow);
++                $encryptIV = $temp;
++            }
++        } elseif (!strlen($buffer['ciphertext'])) {
++            $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
++            $temp = $this->_string_pop($ciphertext, $block_size);
++            if ($this->continuousBuffer) {
++                $encryptIV = $temp;
++            }
++        }
++        if ($this->continuousBuffer) {
++            if (!defined('OPENSSL_RAW_DATA')) {
++                $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
++            }
++            $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
++            if ($overflow) {
++                $this->_increment_str($encryptIV);
++            }
++        }
++
++        return $ciphertext;
++    }
++
++    /**
++     * OpenSSL OFB Processor
++     *
++     * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
++     * for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
++     * and Base::decrypt().
++     *
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @param string $plaintext
++     * @param string $encryptIV
++     * @param array $buffer
++     * @return string
++     * @access private
++     */
++    function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
++    {
++        if (strlen($buffer['xor'])) {
++            $ciphertext = $plaintext ^ $buffer['xor'];
++            $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
++            $plaintext = substr($plaintext, strlen($ciphertext));
++        } else {
++            $ciphertext = '';
++        }
++
++        $block_size = $this->block_size;
++
++        $len = strlen($plaintext);
++        $key = $this->key;
++        $overflow = $len % $block_size;
++
++        if (strlen($plaintext)) {
++            if ($overflow) {
++                $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
++                $xor = $this->_string_pop($ciphertext, $block_size);
++                if ($this->continuousBuffer) {
++                    $encryptIV = $xor;
++                }
++                $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
++                if ($this->continuousBuffer) {
++                    $buffer['xor'] = $xor;
++                }
++            } else {
++                $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
++                if ($this->continuousBuffer) {
++                    $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
++                }
++            }
++        }
++
++        return $ciphertext;
++    }
++
++    /**
++     * phpseclib <-> OpenSSL Mode Mapper
++     *
++     * May need to be overwritten by classes extending this one in some cases
++     *
++     * @return int
++     * @access private
++     */
++    function _openssl_translate_mode()
++    {
++        switch ($this->mode) {
++            case self::MODE_ECB:
++                return 'ecb';
++            case self::MODE_CBC:
++                return 'cbc';
++            case self::MODE_CTR:
++                return 'ctr';
++            case self::MODE_CFB:
++                return 'cfb';
++            case self::MODE_OFB:
++                return 'ofb';
++        }
++    }
++
++    /**
++     * Pad "packets".
++     *
++     * Block ciphers working by encrypting between their specified [$this->]block_size at a time
++     * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
++     * pad the input so that it is of the proper length.
++     *
++     * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
++     * where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
++     * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
++     * transmitted separately)
++     *
++     * @see self::disablePadding()
++     * @access public
++     */
++    function enablePadding()
++    {
++        $this->padding = true;
++    }
++
++    /**
++     * Do not pad packets.
++     *
++     * @see self::enablePadding()
++     * @access public
++     */
++    function disablePadding()
++    {
++        $this->padding = false;
++    }
++
++    /**
++     * Treat consecutive "packets" as if they are a continuous buffer.
++     *
++     * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
++     * will yield different outputs:
++     *
++     * <code>
++     *    echo $rijndael->encrypt(substr($plaintext,  0, 16));
++     *    echo $rijndael->encrypt(substr($plaintext, 16, 16));
++     * </code>
++     * <code>
++     *    echo $rijndael->encrypt($plaintext);
++     * </code>
++     *
++     * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
++     * another, as demonstrated with the following:
++     *
++     * <code>
++     *    $rijndael->encrypt(substr($plaintext, 0, 16));
++     *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
++     * </code>
++     * <code>
++     *    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
++     * </code>
++     *
++     * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
++     * outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
++     * decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
++     *
++     * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each
++     * encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
++     * continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
++     * however, they are also less intuitive and more likely to cause you problems.
++     *
++     * @see self::disableContinuousBuffer()
++     * @access public
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function enableContinuousBuffer()
++    {
++        if ($this->mode == self::MODE_ECB) {
++            return;
++        }
++
++        $this->continuousBuffer = true;
++
++        $this->_setEngine();
++    }
++
++    /**
++     * Treat consecutive packets as if they are a discontinuous buffer.
++     *
++     * The default behavior.
++     *
++     * @see self::enableContinuousBuffer()
++     * @access public
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function disableContinuousBuffer()
++    {
++        if ($this->mode == self::MODE_ECB) {
++            return;
++        }
++        if (!$this->continuousBuffer) {
++            return;
++        }
++
++        $this->continuousBuffer = false;
++        $this->changed = true;
++
++        $this->_setEngine();
++    }
++
++    /**
++     * Test for engine validity
++     *
++     * @see self::__construct()
++     * @param int $engine
++     * @access public
++     * @return bool
++     */
++    function isValidEngine($engine)
++    {
++        switch ($engine) {
++            case self::ENGINE_OPENSSL:
++                if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) {
++                    return false;
++                }
++                $this->openssl_emulate_ctr = false;
++                $result = $this->cipher_name_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) {
++                    return false;
++                }
++
++                // prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
++                // $options openssl_encrypt expected a boolean $raw_data.
++                if (!defined('OPENSSL_RAW_DATA')) {
++                    $this->openssl_options = true;
++                } else {
++                    $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
++                }
++
++                $methods = openssl_get_cipher_methods();
++                if (in_array($this->cipher_name_openssl, $methods)) {
++                    return true;
++                }
++                // not all of openssl's symmetric cipher's support ctr. for those
++                // that don't we'll emulate it
++                switch ($this->mode) {
++                    case self::MODE_CTR:
++                        if (in_array($this->cipher_name_openssl_ecb, $methods)) {
++                            $this->openssl_emulate_ctr = true;
++                            return true;
++                        }
++                }
++                return false;
++            case self::ENGINE_MCRYPT:
++                return $this->cipher_name_mcrypt &&
++                       extension_loaded('mcrypt') &&
++                       in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
++            case self::ENGINE_INTERNAL:
++                return true;
++        }
++
++        return false;
++    }
++
++    /**
++     * Sets the preferred crypt engine
++     *
++     * Currently, $engine could be:
++     *
++     * - \phpseclib\Crypt\Base::ENGINE_OPENSSL  [very fast]
++     *
++     * - \phpseclib\Crypt\Base::ENGINE_MCRYPT   [fast]
++     *
++     * - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
++     *
++     * If the preferred crypt engine is not available the fastest available one will be used
++     *
++     * @see self::__construct()
++     * @param int $engine
++     * @access public
++     */
++    function setPreferredEngine($engine)
++    {
++        switch ($engine) {
++            //case self::ENGINE_OPENSSL;
++            case self::ENGINE_MCRYPT:
++            case self::ENGINE_INTERNAL:
++                $this->preferredEngine = $engine;
++                break;
++            default:
++                $this->preferredEngine = self::ENGINE_OPENSSL;
++        }
++
++        $this->_setEngine();
++    }
++
++    /**
++     * Returns the engine currently being utilized
++     *
++     * @see self::_setEngine()
++     * @access public
++     */
++    function getEngine()
++    {
++        return $this->engine;
++    }
++
++    /**
++     * Sets the engine as appropriate
++     *
++     * @see self::__construct()
++     * @access private
++     */
++    function _setEngine()
++    {
++        $this->engine = null;
++
++        $candidateEngines = array(
++            $this->preferredEngine,
++            self::ENGINE_OPENSSL,
++            self::ENGINE_MCRYPT
++        );
++        foreach ($candidateEngines as $engine) {
++            if ($this->isValidEngine($engine)) {
++                $this->engine = $engine;
++                break;
++            }
++        }
++        if (!$this->engine) {
++            $this->engine = self::ENGINE_INTERNAL;
++        }
++
++        if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
++            // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
++            // (re)open them with the module named in $this->cipher_name_mcrypt
++            mcrypt_module_close($this->enmcrypt);
++            mcrypt_module_close($this->demcrypt);
++            $this->enmcrypt = null;
++            $this->demcrypt = null;
++
++            if ($this->ecb) {
++                mcrypt_module_close($this->ecb);
++                $this->ecb = null;
++            }
++        }
++
++        $this->changed = true;
++    }
++
++    /**
++     * Encrypts a block
++     *
++     * Note: Must be extended by the child \phpseclib\Crypt\* class
++     *
++     * @access private
++     * @param string $in
++     * @return string
++     */
++    abstract function _encryptBlock($in);
++
++    /**
++     * Decrypts a block
++     *
++     * Note: Must be extended by the child \phpseclib\Crypt\* class
++     *
++     * @access private
++     * @param string $in
++     * @return string
++     */
++    abstract function _decryptBlock($in);
++
++    /**
++     * Setup the key (expansion)
++     *
++     * Only used if $engine == self::ENGINE_INTERNAL
++     *
++     * Note: Must extend by the child \phpseclib\Crypt\* class
++     *
++     * @see self::_setup()
++     * @access private
++     */
++    abstract function _setupKey();
++
++    /**
++     * Setup the self::ENGINE_INTERNAL $engine
++     *
++     * (re)init, if necessary, the internal cipher $engine and flush all $buffers
++     * Used (only) if $engine == self::ENGINE_INTERNAL
++     *
++     * _setup() will be called each time if $changed === true
++     * typically this happens when using one or more of following public methods:
++     *
++     * - setKey()
++     *
++     * - setIV()
++     *
++     * - disableContinuousBuffer()
++     *
++     * - First run of encrypt() / decrypt() with no init-settings
++     *
++     * @see self::setKey()
++     * @see self::setIV()
++     * @see self::disableContinuousBuffer()
++     * @access private
++     * @internal _setup() is always called before en/decryption.
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function _setup()
++    {
++        $this->_clearBuffers();
++        $this->_setupKey();
++
++        if ($this->use_inline_crypt) {
++            $this->_setupInlineCrypt();
++        }
++    }
++
++    /**
++     * Setup the self::ENGINE_MCRYPT $engine
++     *
++     * (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
++     * Used (only) if $engine = self::ENGINE_MCRYPT
++     *
++     * _setupMcrypt() will be called each time if $changed === true
++     * typically this happens when using one or more of following public methods:
++     *
++     * - setKey()
++     *
++     * - setIV()
++     *
++     * - disableContinuousBuffer()
++     *
++     * - First run of encrypt() / decrypt()
++     *
++     * @see self::setKey()
++     * @see self::setIV()
++     * @see self::disableContinuousBuffer()
++     * @access private
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function _setupMcrypt()
++    {
++        $this->_clearBuffers();
++        $this->enchanged = $this->dechanged = true;
++
++        if (!isset($this->enmcrypt)) {
++            static $mcrypt_modes = array(
++                self::MODE_CTR    => 'ctr',
++                self::MODE_ECB    => MCRYPT_MODE_ECB,
++                self::MODE_CBC    => MCRYPT_MODE_CBC,
++                self::MODE_CFB    => 'ncfb',
++                self::MODE_OFB    => MCRYPT_MODE_NOFB,
++                self::MODE_STREAM => MCRYPT_MODE_STREAM,
++            );
++
++            $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
++            $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
++
++            // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
++            // to workaround mcrypt's broken ncfb implementation in buffered mode
++            // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
++            if ($this->mode == self::MODE_CFB) {
++                $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
++            }
++        } // else should mcrypt_generic_deinit be called?
++
++        if ($this->mode == self::MODE_CFB) {
++            mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
++        }
++    }
++
++    /**
++     * Pads a string
++     *
++     * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
++     * $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
++     * chr($this->block_size - (strlen($text) % $this->block_size)
++     *
++     * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
++     * and padding will, hence forth, be enabled.
++     *
++     * @see self::_unpad()
++     * @param string $text
++     * @access private
++     * @return string
++     */
++    function _pad($text)
++    {
++        $length = strlen($text);
++
++        if (!$this->padding) {
++            if ($length % $this->block_size == 0) {
++                return $text;
++            } else {
++                user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
++                $this->padding = true;
++            }
++        }
++
++        $pad = $this->block_size - ($length % $this->block_size);
++
++        return str_pad($text, $length + $pad, chr($pad));
++    }
++
++    /**
++     * Unpads a string.
++     *
++     * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
++     * and false will be returned.
++     *
++     * @see self::_pad()
++     * @param string $text
++     * @access private
++     * @return string
++     */
++    function _unpad($text)
++    {
++        if (!$this->padding) {
++            return $text;
++        }
++
++        $length = ord($text[strlen($text) - 1]);
++
++        if (!$length || $length > $this->block_size) {
++            return false;
++        }
++
++        return substr($text, 0, -$length);
++    }
++
++    /**
++     * Clears internal buffers
++     *
++     * Clearing/resetting the internal buffers is done everytime
++     * after disableContinuousBuffer() or on cipher $engine (re)init
++     * ie after setKey() or setIV()
++     *
++     * @access public
++     * @internal Could, but not must, extend by the child Crypt_* class
++     */
++    function _clearBuffers()
++    {
++        $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
++
++        // mcrypt's handling of invalid's $iv:
++        // $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
++        $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
++
++        if (!$this->skip_key_adjustment) {
++            $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
++        }
++    }
++
++    /**
++     * String Shift
++     *
++     * Inspired by array_shift
++     *
++     * @param string $string
++     * @param int $index
++     * @access private
++     * @return string
++     */
++    function _string_shift(&$string, $index = 1)
++    {
++        $substr = substr($string, 0, $index);
++        $string = substr($string, $index);
++        return $substr;
++    }
++
++    /**
++     * String Pop
++     *
++     * Inspired by array_pop
++     *
++     * @param string $string
++     * @param int $index
++     * @access private
++     * @return string
++     */
++    function _string_pop(&$string, $index = 1)
++    {
++        $substr = substr($string, -$index);
++        $string = substr($string, 0, -$index);
++        return $substr;
++    }
++
++    /**
++     * Increment the current string
++     *
++     * @see self::decrypt()
++     * @see self::encrypt()
++     * @param string $var
++     * @access private
++     */
++    function _increment_str(&$var)
++    {
++        for ($i = 4; $i <= strlen($var); $i+= 4) {
++            $temp = substr($var, -$i, 4);
++            switch ($temp) {
++                case "\xFF\xFF\xFF\xFF":
++                    $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
++                    break;
++                case "\x7F\xFF\xFF\xFF":
++                    $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
++                    return;
++                default:
++                    $temp = unpack('Nnum', $temp);
++                    $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
++                    return;
++            }
++        }
++
++        $remainder = strlen($var) % 4;
++
++        if ($remainder == 0) {
++            return;
++        }
++
++        $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
++        $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
++        $var = substr_replace($var, $temp, 0, $remainder);
++    }
++
++    /**
++     * Setup the performance-optimized function for de/encrypt()
++     *
++     * Stores the created (or existing) callback function-name
++     * in $this->inline_crypt
++     *
++     * Internally for phpseclib developers:
++     *
++     *     _setupInlineCrypt() would be called only if:
++     *
++     *     - $engine == self::ENGINE_INTERNAL and
++     *
++     *     - $use_inline_crypt === true
++     *
++     *     - each time on _setup(), after(!) _setupKey()
++     *
++     *
++     *     This ensures that _setupInlineCrypt() has always a
++     *     full ready2go initializated internal cipher $engine state
++     *     where, for example, the keys allready expanded,
++     *     keys/block_size calculated and such.
++     *
++     *     It is, each time if called, the responsibility of _setupInlineCrypt():
++     *
++     *     - to set $this->inline_crypt to a valid and fully working callback function
++     *       as a (faster) replacement for encrypt() / decrypt()
++     *
++     *     - NOT to create unlimited callback functions (for memory reasons!)
++     *       no matter how often _setupInlineCrypt() would be called. At some
++     *       point of amount they must be generic re-useable.
++     *
++     *     - the code of _setupInlineCrypt() it self,
++     *       and the generated callback code,
++     *       must be, in following order:
++     *       - 100% safe
++     *       - 100% compatible to encrypt()/decrypt()
++     *       - using only php5+ features/lang-constructs/php-extensions if
++     *         compatibility (down to php4) or fallback is provided
++     *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
++     *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
++     *         the reason for the existence of _setupInlineCrypt() :-)]
++     *       - memory-nice
++     *       - short (as good as possible)
++     *
++     * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
++     *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class.
++     *       - The following variable names are reserved:
++     *         - $_*  (all variable names prefixed with an underscore)
++     *         - $self (object reference to it self. Do not use $this, but $self instead)
++     *         - $in (the content of $in has to en/decrypt by the generated code)
++     *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
++     *
++     *
++     * @see self::_setup()
++     * @see self::_createInlineCryptFunction()
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @access private
++     * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
++     */
++    function _setupInlineCrypt()
++    {
++        // If, for any reason, an extending \phpseclib\Crypt\Base() \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()
++     *
++     * Internally for phpseclib developers:
++     *
++     *    _createInlineCryptFunction():
++     *
++     *    - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
++     *      with the current [$this->]mode of operation code
++     *
++     *    - create the $inline function, which called by encrypt() / decrypt()
++     *      as its replacement to speed up the en/decryption operations.
++     *
++     *    - return the name of the created $inline callback function
++     *
++     *    - used to speed up en/decryption
++     *
++     *
++     *
++     *    The main reason why can speed up things [up to 50%] this way are:
++     *
++     *    - using variables more effective then regular.
++     *      (ie no use of expensive arrays but integers $k_0, $k_1 ...
++     *      or even, for example, the pure $key[] values hardcoded)
++     *
++     *    - avoiding 1000's of function calls of ie _encryptBlock()
++     *      but inlining the crypt operations.
++     *      in the mode of operation for() loop.
++     *
++     *    - full loop unroll the (sometimes key-dependent) rounds
++     *      avoiding this way ++$i counters and runtime-if's etc...
++     *
++     *    The basic code architectur of the generated $inline en/decrypt()
++     *    lambda function, in pseudo php, is:
++     *
++     *    <code>
++     *    +----------------------------------------------------------------------------------------------+
++     *    | callback $inline = create_function:                                                          |
++     *    | lambda_function_0001_crypt_ECB($action, $text)                                               |
++     *    | {                                                                                            |
++     *    |     INSERT PHP CODE OF:                                                                      |
++     *    |     $cipher_code['init_crypt'];                  // general init code.                       |
++     *    |                                                  // ie: $sbox'es declarations used for       |
++     *    |                                                  //     encrypt and decrypt'ing.             |
++     *    |                                                                                              |
++     *    |     switch ($action) {                                                                       |
++     *    |         case 'encrypt':                                                                      |
++     *    |             INSERT PHP CODE OF:                                                              |
++     *    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
++     *    |                                                    ie: specified $key or $box                |
++     *    |                                                        declarations for encrypt'ing.         |
++     *    |                                                                                              |
++     *    |             foreach ($ciphertext) {                                                          |
++     *    |                 $in = $block_size of $ciphertext;                                            |
++     *    |                                                                                              |
++     *    |                 INSERT PHP CODE OF:                                                          |
++     *    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
++     *    |                                                 // strlen($in) == $this->block_size          |
++     *    |                                                 // here comes the cipher algorithm in action |
++     *    |                                                 // for encryption.                           |
++     *    |                                                 // $cipher_code['encrypt_block'] has to      |
++     *    |                                                 // encrypt the content of the $in variable   |
++     *    |                                                                                              |
++     *    |                 $plaintext .= $in;                                                           |
++     *    |             }                                                                                |
++     *    |             return $plaintext;                                                               |
++     *    |                                                                                              |
++     *    |         case 'decrypt':                                                                      |
++     *    |             INSERT PHP CODE OF:                                                              |
++     *    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
++     *    |                                                    ie: specified $key or $box                |
++     *    |                                                        declarations for decrypt'ing.         |
++     *    |             foreach ($plaintext) {                                                           |
++     *    |                 $in = $block_size of $plaintext;                                             |
++     *    |                                                                                              |
++     *    |                 INSERT PHP CODE OF:                                                          |
++     *    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
++     *    |                                                 // strlen($in) == $this->block_size          |
++     *    |                                                 // here comes the cipher algorithm in action |
++     *    |                                                 // for decryption.                           |
++     *    |                                                 // $cipher_code['decrypt_block'] has to      |
++     *    |                                                 // decrypt the content of the $in variable   |
++     *    |                 $ciphertext .= $in;                                                          |
++     *    |             }                                                                                |
++     *    |             return $ciphertext;                                                              |
++     *    |     }                                                                                        |
++     *    | }                                                                                            |
++     *    +----------------------------------------------------------------------------------------------+
++     *    </code>
++     *
++     *    See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for
++     *    productive inline $cipher_code's how they works.
++     *
++     *    Structure of:
++     *    <code>
++     *    $cipher_code = array(
++     *        'init_crypt'    => (string) '', // optional
++     *        'init_encrypt'  => (string) '', // optional
++     *        'init_decrypt'  => (string) '', // optional
++     *        'encrypt_block' => (string) '', // required
++     *        'decrypt_block' => (string) ''  // required
++     *    );
++     *    </code>
++     *
++     * @see self::_setupInlineCrypt()
++     * @see self::encrypt()
++     * @see self::decrypt()
++     * @param array $cipher_code
++     * @access private
++     * @return string (the name of the created callback function)
++     */
++    function _createInlineCryptFunction($cipher_code)
++    {
++        $block_size = $this->block_size;
++
++        // optional
++        $init_crypt    = isset($cipher_code['init_crypt'])    ? $cipher_code['init_crypt']    : '';
++        $init_encrypt  = isset($cipher_code['init_encrypt'])  ? $cipher_code['init_encrypt']  : '';
++        $init_decrypt  = isset($cipher_code['init_decrypt'])  ? $cipher_code['init_decrypt']  : '';
++        // required
++        $encrypt_block = $cipher_code['encrypt_block'];
++        $decrypt_block = $cipher_code['decrypt_block'];
++
++        // Generating mode of operation inline code,
++        // merged with the $cipher_code algorithm
++        // for encrypt- and decryption.
++        switch ($this->mode) {
++            case self::MODE_ECB:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    $_plaintext_len = strlen($_text);
++
++                    for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                        $in = substr($_text, $_i, '.$block_size.');
++                        '.$encrypt_block.'
++                        $_ciphertext.= $in;
++                    }
++
++                    return $_ciphertext;
++                    ';
++
++                $decrypt = $init_decrypt . '
++                    $_plaintext = "";
++                    $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
++                    $_ciphertext_len = strlen($_text);
++
++                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                        $in = substr($_text, $_i, '.$block_size.');
++                        '.$decrypt_block.'
++                        $_plaintext.= $in;
++                    }
++
++                    return $self->_unpad($_plaintext);
++                    ';
++                break;
++            case self::MODE_CTR:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    $_plaintext_len = strlen($_text);
++                    $_xor = $self->encryptIV;
++                    $_buffer = &$self->enbuffer;
++                    if (strlen($_buffer["ciphertext"])) {
++                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
++                                $in = $_xor;
++                                '.$encrypt_block.'
++                                $self->_increment_str($_xor);
++                                $_buffer["ciphertext"].= $in;
++                            }
++                            $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
++                            $_ciphertext.= $_block ^ $_key;
++                        }
++                    } else {
++                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            $in = $_xor;
++                            '.$encrypt_block.'
++                            $self->_increment_str($_xor);
++                            $_key = $in;
++                            $_ciphertext.= $_block ^ $_key;
++                        }
++                    }
++                    if ($self->continuousBuffer) {
++                        $self->encryptIV = $_xor;
++                        if ($_start = $_plaintext_len % '.$block_size.') {
++                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
++                        }
++                    }
++
++                    return $_ciphertext;
++                ';
++
++                $decrypt = $init_encrypt . '
++                    $_plaintext = "";
++                    $_ciphertext_len = strlen($_text);
++                    $_xor = $self->decryptIV;
++                    $_buffer = &$self->debuffer;
++
++                    if (strlen($_buffer["ciphertext"])) {
++                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
++                                $in = $_xor;
++                                '.$encrypt_block.'
++                                $self->_increment_str($_xor);
++                                $_buffer["ciphertext"].= $in;
++                            }
++                            $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
++                            $_plaintext.= $_block ^ $_key;
++                        }
++                    } else {
++                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            $in = $_xor;
++                            '.$encrypt_block.'
++                            $self->_increment_str($_xor);
++                            $_key = $in;
++                            $_plaintext.= $_block ^ $_key;
++                        }
++                    }
++                    if ($self->continuousBuffer) {
++                        $self->decryptIV = $_xor;
++                        if ($_start = $_ciphertext_len % '.$block_size.') {
++                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
++                        }
++                    }
++
++                    return $_plaintext;
++                    ';
++                break;
++            case self::MODE_CFB:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    $_buffer = &$self->enbuffer;
++
++                    if ($self->continuousBuffer) {
++                        $_iv = &$self->encryptIV;
++                        $_pos = &$_buffer["pos"];
++                    } else {
++                        $_iv = $self->encryptIV;
++                        $_pos = 0;
++                    }
++                    $_len = strlen($_text);
++                    $_i = 0;
++                    if ($_pos) {
++                        $_orig_pos = $_pos;
++                        $_max = '.$block_size.' - $_pos;
++                        if ($_len >= $_max) {
++                            $_i = $_max;
++                            $_len-= $_max;
++                            $_pos = 0;
++                        } else {
++                            $_i = $_len;
++                            $_pos+= $_len;
++                            $_len = 0;
++                        }
++                        $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
++                        $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
++                    }
++                    while ($_len >= '.$block_size.') {
++                        $in = $_iv;
++                        '.$encrypt_block.';
++                        $_iv = $in ^ substr($_text, $_i, '.$block_size.');
++                        $_ciphertext.= $_iv;
++                        $_len-= '.$block_size.';
++                        $_i+= '.$block_size.';
++                    }
++                    if ($_len) {
++                        $in = $_iv;
++                        '.$encrypt_block.'
++                        $_iv = $in;
++                        $_block = $_iv ^ substr($_text, $_i);
++                        $_iv = substr_replace($_iv, $_block, 0, $_len);
++                        $_ciphertext.= $_block;
++                        $_pos = $_len;
++                    }
++                    return $_ciphertext;
++                ';
++
++                $decrypt = $init_encrypt . '
++                    $_plaintext = "";
++                    $_buffer = &$self->debuffer;
++
++                    if ($self->continuousBuffer) {
++                        $_iv = &$self->decryptIV;
++                        $_pos = &$_buffer["pos"];
++                    } else {
++                        $_iv = $self->decryptIV;
++                        $_pos = 0;
++                    }
++                    $_len = strlen($_text);
++                    $_i = 0;
++                    if ($_pos) {
++                        $_orig_pos = $_pos;
++                        $_max = '.$block_size.' - $_pos;
++                        if ($_len >= $_max) {
++                            $_i = $_max;
++                            $_len-= $_max;
++                            $_pos = 0;
++                        } else {
++                            $_i = $_len;
++                            $_pos+= $_len;
++                            $_len = 0;
++                        }
++                        $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
++                        $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
++                    }
++                    while ($_len >= '.$block_size.') {
++                        $in = $_iv;
++                        '.$encrypt_block.'
++                        $_iv = $in;
++                        $cb = substr($_text, $_i, '.$block_size.');
++                        $_plaintext.= $_iv ^ $cb;
++                        $_iv = $cb;
++                        $_len-= '.$block_size.';
++                        $_i+= '.$block_size.';
++                    }
++                    if ($_len) {
++                        $in = $_iv;
++                        '.$encrypt_block.'
++                        $_iv = $in;
++                        $_plaintext.= $_iv ^ substr($_text, $_i);
++                        $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
++                        $_pos = $_len;
++                    }
++
++                    return $_plaintext;
++                    ';
++                break;
++            case self::MODE_OFB:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    $_plaintext_len = strlen($_text);
++                    $_xor = $self->encryptIV;
++                    $_buffer = &$self->enbuffer;
++
++                    if (strlen($_buffer["xor"])) {
++                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            if (strlen($_block) > strlen($_buffer["xor"])) {
++                                $in = $_xor;
++                                '.$encrypt_block.'
++                                $_xor = $in;
++                                $_buffer["xor"].= $_xor;
++                            }
++                            $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
++                            $_ciphertext.= $_block ^ $_key;
++                        }
++                    } else {
++                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                            $in = $_xor;
++                            '.$encrypt_block.'
++                            $_xor = $in;
++                            $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
++                        }
++                        $_key = $_xor;
++                    }
++                    if ($self->continuousBuffer) {
++                        $self->encryptIV = $_xor;
++                        if ($_start = $_plaintext_len % '.$block_size.') {
++                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
++                        }
++                    }
++                    return $_ciphertext;
++                    ';
++
++                $decrypt = $init_encrypt . '
++                    $_plaintext = "";
++                    $_ciphertext_len = strlen($_text);
++                    $_xor = $self->decryptIV;
++                    $_buffer = &$self->debuffer;
++
++                    if (strlen($_buffer["xor"])) {
++                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                            $_block = substr($_text, $_i, '.$block_size.');
++                            if (strlen($_block) > strlen($_buffer["xor"])) {
++                                $in = $_xor;
++                                '.$encrypt_block.'
++                                $_xor = $in;
++                                $_buffer["xor"].= $_xor;
++                            }
++                            $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
++                            $_plaintext.= $_block ^ $_key;
++                        }
++                    } else {
++                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                            $in = $_xor;
++                            '.$encrypt_block.'
++                            $_xor = $in;
++                            $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
++                        }
++                        $_key = $_xor;
++                    }
++                    if ($self->continuousBuffer) {
++                        $self->decryptIV = $_xor;
++                        if ($_start = $_ciphertext_len % '.$block_size.') {
++                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
++                        }
++                    }
++                    return $_plaintext;
++                    ';
++                break;
++            case self::MODE_STREAM:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    '.$encrypt_block.'
++                    return $_ciphertext;
++                    ';
++                $decrypt = $init_decrypt . '
++                    $_plaintext = "";
++                    '.$decrypt_block.'
++                    return $_plaintext;
++                    ';
++                break;
++            // case self::MODE_CBC:
++            default:
++                $encrypt = $init_encrypt . '
++                    $_ciphertext = "";
++                    $_plaintext_len = strlen($_text);
++
++                    $in = $self->encryptIV;
++
++                    for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
++                        $in = substr($_text, $_i, '.$block_size.') ^ $in;
++                        '.$encrypt_block.'
++                        $_ciphertext.= $in;
++                    }
++
++                    if ($self->continuousBuffer) {
++                        $self->encryptIV = $in;
++                    }
++
++                    return $_ciphertext;
++                    ';
++
++                $decrypt = $init_decrypt . '
++                    $_plaintext = "";
++                    $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
++                    $_ciphertext_len = strlen($_text);
++
++                    $_iv = $self->decryptIV;
++
++                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
++                        $in = $_block = substr($_text, $_i, '.$block_size.');
++                        '.$decrypt_block.'
++                        $_plaintext.= $in ^ $_iv;
++                        $_iv = $_block;
++                    }
++
++                    if ($self->continuousBuffer) {
++                        $self->decryptIV = $_iv;
++                    }
++
++                    return $self->_unpad($_plaintext);
++                    ';
++                break;
++        }
++
++        // Create the $inline function and return its name as string. Ready to run!
++        return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
++    }
++
++    /**
++     * 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
++     * uniqe 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
++     */
++    function &_getLambdaFunctions()
++    {
++        static $functions = array();
++        return $functions;
++    }
++
++    /**
++     * Generates a digest from $bytes
++     *
++     * @see self::_setupInlineCrypt()
++     * @access private
++     * @param $bytes
++     * @return string
++     */
++    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 = pack('H*', sha1($hash));
++                    $result .= $t ^ $hash;
++                }
++                return $result . pack('H*', sha1($hash));
++        }
++    }
++}
+diff -ruN libraries/phpseclib/Crypt/Random.php ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Random.php
+--- libraries/phpseclib/Crypt/Random.php	1969-12-31 19:00:00.000000000 -0500
++++ ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Random.php	2016-03-17 06:11:18.000000000 -0400
+@@ -0,0 +1,243 @@
++<?php
++
++/**
++ * Random Number Generator
++ *
++ * PHP version 5
++ *
++ * Here's a short example of how to use this library:
++ * <code>
++ * <?php
++ *    include 'vendor/autoload.php';
++ *
++ *    echo bin2hex(\phpseclib\Crypt\Random::string(8));
++ * ?>
++ * </code>
++ *
++ * @category  Crypt
++ * @package   Random
++ * @author    Jim Wigginton <terrafrost@php.net>
++ * @copyright 2007 Jim Wigginton
++ * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
++ * @link      http://phpseclib.sourceforge.net
++ */
++
++namespace phpseclib\Crypt;
++
++use phpseclib\Crypt\AES;
++use phpseclib\Crypt\Base;
++use phpseclib\Crypt\Blowfish;
++use phpseclib\Crypt\DES;
++use phpseclib\Crypt\RC4;
++use phpseclib\Crypt\TripleDES;
++use phpseclib\Crypt\Twofish;
++
++/**
++ * Pure-PHP Random Number Generator
++ *
++ * @package Random
++ * @author  Jim Wigginton <terrafrost@php.net>
++ * @access  public
++ */
++class Random
++{
++    /**
++     * Generate a random string.
++     *
++     * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
++     * microoptimizations because this function has the potential of being called a huge number of times.
++     * eg. for RSA key generation.
++     *
++     * @param int $length
++     * @return string
++     */
++    static function string($length)
++    {
++        if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
++            try {
++                return \random_bytes($length);
++            } catch (\Throwable $e) {
++                // If a sufficient source of randomness is unavailable, random_bytes() will throw an
++                // object that implements the Throwable interface (Exception, TypeError, Error).
++                // We don't actually need to do anything here. The string() method should just continue
++                // as normal. Note, however, that if we don't have a sufficient source of randomness for
++                // random_bytes(), most of the other calls here will fail too, so we'll end up using
++                // the PHP implementation.
++            }
++        }
++
++        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
++            // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
++            // ie. class_alias is a function that was introduced in PHP 5.3
++            if (extension_loaded('mcrypt') && function_exists('class_alias')) {
++                return mcrypt_create_iv($length);
++            }
++            // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was,
++            // to quote <http://php.net/ChangeLog-5.php#5.3.4>, "possible blocking behavior". as of 5.3.4
++            // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both
++            // call php_win32_get_random_bytes():
++            //
++            // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008
++            // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392
++            //
++            // php_win32_get_random_bytes() is defined thusly:
++            //
++            // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80
++            //
++            // we're calling it, all the same, in the off chance that the mcrypt extension is not available
++            if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) {
++                return openssl_random_pseudo_bytes($length);
++            }
++        } else {
++            // method 1. the fastest
++            if (extension_loaded('openssl')) {
++                return openssl_random_pseudo_bytes($length);
++            }
++            // method 2
++            static $fp = true;
++            if ($fp === true) {
++                // warning's will be output unles the error suppression operator is used. errors such as
++                // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc.
++                $fp = @fopen('/dev/urandom', 'rb');
++            }
++            if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource()
++                return fread($fp, $length);
++            }
++            // method 3. pretty much does the same thing as method 2 per the following url:
++            // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391
++            // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're
++            // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir
++            // restrictions or some such
++            if (extension_loaded('mcrypt')) {
++                return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
++            }
++        }
++        // at this point we have no choice but to use a pure-PHP CSPRNG
++
++        // cascade entropy across multiple PHP instances by fixing the session and collecting all
++        // environmental variables, including the previous session data and the current session
++        // data.
++        //
++        // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
++        // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
++        // PHP isn't low level to be able to use those as sources and on a web server there's not likely
++        // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
++        // however, a ton of people visiting the website. obviously you don't want to base your seeding
++        // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
++        // by the user and (2) this isn't just looking at the data sent by the current user - it's based
++        // on the data sent by all users. one user requests the page and a hash of their info is saved.
++        // another user visits the page and the serialization of their data is utilized along with the
++        // server envirnment stuff and a hash of the previous http request data (which itself utilizes
++        // a hash of the session data before that). certainly an attacker should be assumed to have
++        // full control over his own http requests. he, however, is not going to have control over
++        // everyone's http requests.
++        static $crypto = false, $v;
++        if ($crypto === false) {
++            // save old session data
++            $old_session_id = session_id();
++            $old_use_cookies = ini_get('session.use_cookies');
++            $old_session_cache_limiter = session_cache_limiter();
++            $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
++            if ($old_session_id != '') {
++                session_write_close();
++            }
++
++            session_id(1);
++            ini_set('session.use_cookies', 0);
++            session_cache_limiter('');
++            session_start();
++
++            $v = $seed = $_SESSION['seed'] = pack('H*', sha1(
++                serialize($_SERVER) .
++                serialize($_POST) .
++                serialize($_GET) .
++                serialize($_COOKIE) .
++                serialize($GLOBALS) .
++                serialize($_SESSION) .
++                serialize($_OLD_SESSION)
++            ));
++            if (!isset($_SESSION['count'])) {
++                $_SESSION['count'] = 0;
++            }
++            $_SESSION['count']++;
++
++            session_write_close();
++
++            // restore old session data
++            if ($old_session_id != '') {
++                session_id($old_session_id);
++                session_start();
++                ini_set('session.use_cookies', $old_use_cookies);
++                session_cache_limiter($old_session_cache_limiter);
++            } else {
++                if ($_OLD_SESSION !== false) {
++                    $_SESSION = $_OLD_SESSION;
++                    unset($_OLD_SESSION);
++                } else {
++                    unset($_SESSION);
++                }
++            }
++
++            // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
++            // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
++            // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
++            // original hash and the current hash. we'll be emulating that. for more info see the following URL:
++            //
++            // http://tools.ietf.org/html/rfc4253#section-7.2
++            //
++            // see the is_string($crypto) part for an example of how to expand the keys
++            $key = pack('H*', sha1($seed . 'A'));
++            $iv = pack('H*', sha1($seed . 'C'));
++
++            // ciphers are used as per the nist.gov link below. also, see this link:
++            //
++            // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
++            switch (true) {
++                case class_exists('\phpseclib\Crypt\AES'):
++                    $crypto = new AES(Base::MODE_CTR);
++                    break;
++                case class_exists('\phpseclib\Crypt\Twofish'):
++                    $crypto = new Twofish(Base::MODE_CTR);
++                    break;
++                case class_exists('\phpseclib\Crypt\Blowfish'):
++                    $crypto = new Blowfish(Base::MODE_CTR);
++                    break;
++                case class_exists('\phpseclib\Crypt\TripleDES'):
++                    $crypto = new TripleDES(Base::MODE_CTR);
++                    break;
++                case class_exists('\phpseclib\Crypt\DES'):
++                    $crypto = new DES(Base::MODE_CTR);
++                    break;
++                case class_exists('\phpseclib\Crypt\RC4'):
++                    $crypto = new RC4();
++                    break;
++                default:
++                    user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded');
++                    return false;
++            }
++
++            $crypto->setKey($key);
++            $crypto->setIV($iv);
++            $crypto->enableContinuousBuffer();
++        }
++
++        //return $crypto->encrypt(str_repeat("\0", $length));
++
++        // the following is based off of ANSI X9.31:
++        //
++        // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
++        //
++        // OpenSSL uses that same standard for it's random numbers:
++        //
++        // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
++        // (do a search for "ANS X9.31 A.2.4")
++        $result = '';
++        while (strlen($result) < $length) {
++            $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21
++            $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20
++            $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20
++            $result.= $r;
++        }
++        return substr($result, 0, $length);
++    }
++}
+diff -ruN libraries/phpseclib/Crypt/Rijndael.php ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Rijndael.php
+--- libraries/phpseclib/Crypt/Rijndael.php	1969-12-31 19:00:00.000000000 -0500
++++ ../phpmyadmin-4.6.0/libraries/phpseclib/Crypt/Rijndael.php	2016-03-17 06:11:18.000000000 -0400
+@@ -0,0 +1,941 @@
++<?php
++
++/**
++ * Pure-PHP implementation of Rijndael.
++ *
++ * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
++ *
++ * PHP version 5
++ *
++ * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If
++ * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
++ * {@link self::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 self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
++ *
++ * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
++ * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
++ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
++ * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
++ * are first defined as valid key / block lengths in
++ * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
++ * Extensions: Other block and Cipher Key lengths.
++ * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
++ *
++ * {@internal The variable names are the same as those in
++ * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
++ *
++ * Here's a short example of how to use this library:
++ * <code>
++ * <?php
++ *    include 'vendor/autoload.php';
++ *
++ *    $rijndael = new \phpseclib\Crypt\Rijndael();
++ *
++ *    $rijndael->setKey('abcdefghijklmnop');
++ *
++ *    $size = 10 * 1024;
++ *    $plaintext = '';
++ *    for ($i = 0; $i < $size; $i++) {
++ *        $plaintext.= 'a';
++ *    }
++ *
++ *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));
++ * ?>
++ * </code>
++ *
++ * @category  Crypt
++ * @package   Rijndael
++ * @author    Jim Wigginton <terrafrost@php.net>
++ * @copyright 2008 Jim Wigginton
++ * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
++ * @link      http://phpseclib.sourceforge.net
++ */
++namespace phpseclib\Crypt;
++
++if (! defined('PHPMYADMIN')) {
++    exit;
++}
++
++use phpseclib\Crypt\Base;
++
++/**
++ * Pure-PHP implementation of Rijndael.
++ *
++ * @package Rijndael
++ * @author  Jim Wigginton <terrafrost@php.net>
++ * @access  public
++ */
++class Rijndael extends Base
++{
++    /**
++     * The mcrypt specific name of the cipher
++     *
++     * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
++     * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable
++     * or not for the current $block_size/$key_length.
++     * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
++     *
++     * @see \phpseclib\Crypt\Base::cipher_name_mcrypt
++     * @see \phpseclib\Crypt\Base::engine
++     * @see self::isValidEngine()
++     * @var string
++     * @access private
++     */
++    var $cipher_name_mcrypt = 'rijndael-128';
++
++    /**
++     * The default salt used by setPassword()
++     *
++     * @see \phpseclib\Crypt\Base::password_default_salt
++     * @see \phpseclib\Crypt\Base::setPassword()
++     * @var string
++     * @access private
++     */
++    var $password_default_salt = 'phpseclib';
++
++    /**
++     * The Key Schedule
++     *
++     * @see self::_setup()
++     * @var array
++     * @access private
++     */
++    var $w;
++
++    /**
++     * The Inverse Key Schedule
++     *
++     * @see self::_setup()
++     * @var array
++     * @access private
++     */
++    var $dw;
++
++    /**
++     * The Block Length divided by 32
++     *
++     * @see self::setBlockLength()
++     * @var int
++     * @access private
++     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size
++     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could
++     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
++     *    of that, we'll just precompute it once.
++     */
++    var $Nb = 4;
++
++    /**
++     * The Key Length (in bytes)
++     *
++     * @see self::setKeyLength()
++     * @var int
++     * @access private
++     * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
++     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
++     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
++     *    of that, we'll just precompute it once.
++     */
++    var $key_length = 16;
++
++    /**
++     * The Key Length divided by 32
++     *
++     * @see self::setKeyLength()
++     * @var int
++     * @access private
++     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
++     */
++    var $Nk = 4;
++
++    /**
++     * The Number of Rounds
++     *
++     * @var int
++     * @access private
++     * @internal The max value is 14, the min value is 10.
++     */
++    var $Nr;
++
++    /**
++     * Shift offsets
++     *
++     * @var array
++     * @access private
++     */
++    var $c;
++
++    /**
++     * Holds the last used key- and block_size information
++     *
++     * @var array
++     * @access private
++     */
++    var $kl;
++
++    /**
++     * Sets the key length.
++     *
++     * Valid key lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
++     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
++     *
++     * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
++     *       and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
++     *       192/256 bits as, for example, mcrypt will do.
++     *
++     *       That said, if you want be compatible with other Rijndael and AES implementations,
++     *       you should not setKeyLength(160) or setKeyLength(224).
++     *
++     * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
++     *             the mcrypt php extension, even if available.
++     *             This results then in slower encryption.
++     *
++     * @access public
++     * @param int $length
++     */
++    function setKeyLength($length)
++    {
++        switch (true) {
++            case $length <= 128:
++                $this->key_length = 16;
++                break;
++            case $length <= 160:
++                $this->key_length = 20;
++                break;
++            case $length <= 192:
++                $this->key_length = 24;
++                break;
++            case $length <= 224:
++                $this->key_length = 28;
++                break;
++            default:
++                $this->key_length = 32;
++        }
++
++        parent::setKeyLength($length);
++    }
++
++    /**
++     * Sets the block length
++     *
++     * Valid block lengths are 128, 160, 192, 224, and 256.  If the length is less than 128, it will be rounded up to
++     * 128.  If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount.
++     *
++     * @access public
++     * @param int $length
++     */
++    function setBlockLength($length)
++    {
++        $length >>= 5;
++        if ($length > 8) {
++            $length = 8;
++        } elseif ($length < 4) {
++            $length = 4;
++        }
++        $this->Nb = $length;
++        $this->block_size = $length << 2;
++        $this->changed = true;
++        $this->_setEngine();
++    }
++
++    /**
++     * Test for engine validity
++     *
++     * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
++     *
++     * @see \phpseclib\Crypt\Base::__construct()
++     * @param int $engine
++     * @access public
++     * @return bool
++     */
++    function isValidEngine($engine)
++    {
++        switch ($engine) {
++            case self::ENGINE_OPENSSL:
++                if ($this->block_size != 16) {
++                    return false;
++                }
++                $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
++                $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode();
++                break;
++            case self::ENGINE_MCRYPT:
++                $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
++                if ($this->key_length % 8) { // is it a 160/224-bit key?
++                    // mcrypt is not usable for them, only for 128/192/256-bit keys
++                    return false;
++                }
++        }
++
++        return parent::isValidEngine($engine);
++    }
++
++    /**
++     * Encrypts a block
++     *
++     * @access private
++     * @param string $in
++     * @return string
++     */
++    function _encryptBlock($in)
++    {
++        static $tables;
++        if (empty($tables)) {
++            $tables = &$this->_getTables();
++        }
++        $t0   = $tables[0];
++        $t1   = $tables[1];
++        $t2   = $tables[2];
++        $t3   = $tables[3];
++        $sbox = $tables[4];
++
++        $state = array();
++        $words = unpack('N*', $in);
++
++        $c = $this->c;
++        $w = $this->w;
++        $Nb = $this->Nb;
++        $Nr = $this->Nr;
++
++        // addRoundKey
++        $wc = $Nb - 1;
++        foreach ($words as $word) {
++            $state[] = $word ^ $w[++$wc];
++        }
++
++        // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
++        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
++        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
++        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
++        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1],
++        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
++
++        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
++        $temp = array();
++        for ($round = 1; $round < $Nr; ++$round) {
++            $i = 0; // $c[0] == 0
++            $j = $c[1];
++            $k = $c[2];
++            $l = $c[3];
++
++            while ($i < $Nb) {
++                $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^
++                            $t1[$state[$j] >> 16 & 0x000000FF] ^
++                            $t2[$state[$k] >>  8 & 0x000000FF] ^
++                            $t3[$state[$l]       & 0x000000FF] ^
++                            $w[++$wc];
++                ++$i;
++                $j = ($j + 1) % $Nb;
++                $k = ($k + 1) % $Nb;
++                $l = ($l + 1) % $Nb;
++            }
++            $state = $temp;
++        }
++
++        // subWord
++        for ($i = 0; $i < $Nb; ++$i) {
++            $state[$i] =   $sbox[$state[$i]       & 0x000000FF]        |
++                          ($sbox[$state[$i] >>  8 & 0x000000FF] <<  8) |
++                          ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) |
++                          ($sbox[$state[$i] >> 24 & 0x000000FF] << 24);
++        }
++
++        // shiftRows + addRoundKey
++        $i = 0; // $c[0] == 0
++        $j = $c[1];
++        $k = $c[2];
++        $l = $c[3];
++        while ($i < $Nb) {
++            $temp[$i] = ($state[$i] & 0xFF000000) ^
++                        ($state[$j] & 0x00FF0000) ^
++                        ($state[$k] & 0x0000FF00) ^
++                        ($state[$l] & 0x000000FF) ^
++                         $w[$i];
++            ++$i;
++            $j = ($j + 1) % $Nb;
++            $k = ($k + 1) % $Nb;
++            $l = ($l + 1) % $Nb;
++        }
++
++        switch ($Nb) {
++            case 8:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
++            case 7:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
++            case 6:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
++            case 5:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
++            default:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
++        }
++    }
++
++    /**
++     * Decrypts a block
++     *
++     * @access private
++     * @param string $in
++     * @return string
++     */
++    function _decryptBlock($in)
++    {
++        static $invtables;
++        if (empty($invtables)) {
++            $invtables = &$this->_getInvTables();
++        }
++        $dt0   = $invtables[0];
++        $dt1   = $invtables[1];
++        $dt2   = $invtables[2];
++        $dt3   = $invtables[3];
++        $isbox = $invtables[4];
++
++        $state = array();
++        $words = unpack('N*', $in);
++
++        $c  = $this->c;
++        $dw = $this->dw;
++        $Nb = $this->Nb;
++        $Nr = $this->Nr;
++
++        // addRoundKey
++        $wc = $Nb - 1;
++        foreach ($words as $word) {
++            $state[] = $word ^ $dw[++$wc];
++        }
++
++        $temp = array();
++        for ($round = $Nr - 1; $round > 0; --$round) {
++            $i = 0; // $c[0] == 0
++            $j = $Nb - $c[1];
++            $k = $Nb - $c[2];
++            $l = $Nb - $c[3];
++
++            while ($i < $Nb) {
++                $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^
++                            $dt1[$state[$j] >> 16 & 0x000000FF] ^
++                            $dt2[$state[$k] >>  8 & 0x000000FF] ^
++                            $dt3[$state[$l]       & 0x000000FF] ^
++                            $dw[++$wc];
++                ++$i;
++                $j = ($j + 1) % $Nb;
++                $k = ($k + 1) % $Nb;
++                $l = ($l + 1) % $Nb;
++            }
++            $state = $temp;
++        }
++
++        // invShiftRows + invSubWord + addRoundKey
++        $i = 0; // $c[0] == 0
++        $j = $Nb - $c[1];
++        $k = $Nb - $c[2];
++        $l = $Nb - $c[3];
++
++        while ($i < $Nb) {
++            $word = ($state[$i] & 0xFF000000) |
++                    ($state[$j] & 0x00FF0000) |
++                    ($state[$k] & 0x0000FF00) |
++                    ($state[$l] & 0x000000FF);
++
++            $temp[$i] = $dw[$i] ^ ($isbox[$word       & 0x000000FF]        |
++                                  ($isbox[$word >>  8 & 0x000000FF] <<  8) |
++                                  ($isbox[$word >> 16 & 0x000000FF] << 16) |
++                                  ($isbox[$word >> 24 & 0x000000FF] << 24));
++            ++$i;
++            $j = ($j + 1) % $Nb;
++            $k = ($k + 1) % $Nb;
++            $l = ($l + 1) % $Nb;
++        }
++
++        switch ($Nb) {
++            case 8:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]);
++            case 7:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]);
++            case 6:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]);
++            case 5:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]);
++            default:
++                return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]);
++        }
++    }
++
++    /**
++     * Setup the key (expansion)
++     *
++     * @see \phpseclib\Crypt\Base::_setupKey()
++     * @access private
++     */
++    function _setupKey()
++    {
++        // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
++        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
++        static $rcon = array(0,
++            0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
++            0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
++            0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
++            0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
++            0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
++            0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
++        );
++
++        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
++            // already expanded
++            return;
++        }
++        $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size);
++
++        $this->Nk = $this->key_length >> 2;
++        // see Rijndael-ammended.pdf#page=44
++        $this->Nr = max($this->Nk, $this->Nb) + 6;
++
++        // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
++        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
++        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
++        //     "Table 2: Shift offsets for different block lengths"
++        switch ($this->Nb) {
++            case 4:
++            case 5:
++            case 6:
++                $this->c = array(0, 1, 2, 3);
++                break;
++            case 7:
++                $this->c = array(0, 1, 2, 4);
++                break;
++            case 8:
++                $this->c = array(0, 1, 3, 4);
++        }
++
++        $w = array_values(unpack('N*words', $this->key));
++
++        $length = $this->Nb * ($this->Nr + 1);
++        for ($i = $this->Nk; $i < $length; $i++) {
++            $temp = $w[$i - 1];
++            if ($i % $this->Nk == 0) {
++                // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
++                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
++                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
++                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
++                $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
++                $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk];
++            } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
++                $temp = $this->_subWord($temp);
++            }
++            $w[$i] = $w[$i - $this->Nk] ^ $temp;
++        }
++
++        // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
++        // and generate the inverse key schedule.  more specifically,
++        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
++        // "The key expansion for the Inverse Cipher is defined as follows:
++        //        1. Apply the Key Expansion.
++        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
++        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
++        list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables();
++        $temp = $this->w = $this->dw = array();
++        for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
++            if ($col == $this->Nb) {
++                if ($row == 0) {
++                    $this->dw[0] = $this->w[0];
++                } else {
++                    // subWord + invMixColumn + invSubWord = invMixColumn
++                    $j = 0;
++                    while ($j < $this->Nb) {
++                        $dw = $this->_subWord($this->w[$row][$j]);
++                        $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^
++                                    $dt1[$dw >> 16 & 0x000000FF] ^
++                                    $dt2[$dw >>  8 & 0x000000FF] ^
++                                    $dt3[$dw       & 0x000000FF];
++                        $j++;
++                    }
++                    $this->dw[$row] = $temp;
++                }
++
++                $col = 0;
++                $row++;
++            }
++            $this->w[$row][$col] = $w[$i];
++        }
++
++        $this->dw[$row] = $this->w[$row];
++
++        // Converting to 1-dim key arrays (both ascending)
++        $this->dw = array_reverse($this->dw);
++        $w  = array_pop($this->w);
++        $dw = array_pop($this->dw);
++        foreach ($this->w as $r => $wr) {
++            foreach ($wr as $c => $wc) {
++                $w[]  = $wc;
++                $dw[] = $this->dw[$r][$c];
++            }
++        }
++        $this->w  = $w;
++        $this->dw = $dw;
++    }
++
++    /**
++     * Performs S-Box substitutions
++     *
++     * @access private
++     * @param int $word
++     */
++    function _subWord($word)
++    {
++        static $sbox;
++        if (empty($sbox)) {
++            list(, , , , $sbox) = $this->_getTables();
++        }
++
++        return  $sbox[$word       & 0x000000FF]        |
++               ($sbox[$word >>  8 & 0x000000FF] <<  8) |
++               ($sbox[$word >> 16 & 0x000000FF] << 16) |
++               ($sbox[$word >> 24 & 0x000000FF] << 24);
++    }
++
++    /**
++     * Provides the mixColumns and sboxes tables
++     *
++     * @see self::_encryptBlock()
++     * @see self::_setupInlineCrypt()
++     * @see self::_subWord()
++     * @access private
++     * @return array &$tables
++     */
++    function &_getTables()
++    {
++        static $tables;
++        if (empty($tables)) {
++            // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
++            // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
++            // those are the names we'll use.
++            $t3 = array_map('intval', array(
++                // with array_map('intval', ...) we ensure we have only int's and not
++                // some slower floats converted by php automatically on high values
++                0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
++                0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
++                0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
++                0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
++                0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
++                0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
++                0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
++                0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
++                0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
++                0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
++                0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
++                0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
++                0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
++                0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
++                0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
++                0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
++                0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
++                0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
++                0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
++                0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
++                0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
++                0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
++                0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
++                0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
++                0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
++                0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
++                0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
++                0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
++                0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
++                0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
++                0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
++                0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
++            ));
++
++            foreach ($t3 as $t3i) {
++                $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >>  8) & 0x00FFFFFF);
++                $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF);
++                $t2[] = (($t3i <<  8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF);
++            }
++
++            $tables = array(
++                // The Precomputed mixColumns tables t0 - t3
++                $t0,
++                $t1,
++                $t2,
++                $t3,
++                // The SubByte S-Box
++                array(
++                    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
++                    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
++                    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
++                    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
++                    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
++                    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
++                    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
++                    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
++                    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
++                    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
++                    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
++                    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
++                    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
++                    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
++                    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
++                    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
++                )
++            );
++        }
++        return $tables;
++    }
++
++    /**
++     * Provides the inverse mixColumns and inverse sboxes tables
++     *
++     * @see self::_decryptBlock()
++     * @see self::_setupInlineCrypt()
++     * @see self::_setupKey()
++     * @access private
++     * @return array &$tables
++     */
++    function &_getInvTables()
++    {
++        static $tables;
++        if (empty($tables)) {
++            $dt3 = array_map('intval', array(
++                0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
++                0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
++                0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
++                0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
++                0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
++                0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
++                0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
++                0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
++                0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
++                0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
++                0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
++                0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
++                0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
++                0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
++                0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
++                0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
++                0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
++                0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
++                0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
++                0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
++                0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
++                0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
++                0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
++                0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
++                0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
++                0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
++                0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
++                0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
++                0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
++                0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
++                0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
++                0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
++            ));
++
++            foreach ($dt3 as $dt3i) {
++                $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >>  8) & 0x00FFFFFF);
++                $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF);
++                $dt2[] = (($dt3i <<  8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF);
++            };
++
++            $tables = array(
++                // The Precomputed inverse mixColumns tables dt0 - dt3
++                $dt0,
++                $dt1,
++                $dt2,
++                $dt3,
++                // The inverse SubByte S-Box
++                array(
++                    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
++                    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
++                    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
++                    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
++                    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
++                    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
++                    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
++                    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
++                    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
++                    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
++                    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
++                    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
++                    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
++                    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
++                    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
++                    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
++                )
++            );
++        }
++        return $tables;
++    }
++
++    /**
++     * Setup the performance-optimized function for de/encrypt()
++     *
++     * @see \phpseclib\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 =& 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;
++                    $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];
++    }
++}
+diff -ruN libraries/phpseclib/LICENSE ../phpmyadmin-4.6.0/libraries/phpseclib/LICENSE
+--- libraries/phpseclib/LICENSE	1969-12-31 19:00:00.000000000 -0500
++++ ../phpmyadmin-4.6.0/libraries/phpseclib/LICENSE	2016-03-17 06:11:18.000000000 -0400
+@@ -0,0 +1,21 @@
++Copyright 2007-2013 TerraFrost and other contributors
++http://phpseclib.sourceforge.net/
++
++Permission is hereby granted, free of charge, to any person obtaining
++a copy of this software and associated documentation files (the
++"Software"), to deal in the Software without restriction, including
++without limitation the rights to use, copy, modify, merge, publish,
++distribute, sublicense, and/or sell copies of the Software, and to
++permit persons to whom the Software is furnished to do so, subject to
++the following conditions:
++
++The above copyright notice and this permission notice shall be
++included in all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
++LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
++OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2040.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2040.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2040.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2040.patch	2016-04-21 11:56:20.000000000 -0400
@@ -0,0 +1,18 @@
+Description: fix for CVE-2016-2040
+ 9f3488fc3ab6b83618dbb4bebbea4b973764e2ac and
+ 27eb98faedcdcd0b856577fcbdfe3e87b2445345 were not included because
+ the code was not present.
+Author: Antoine Beaupré <anarcat@debian.org>
+Origin: upstream, https://github.com/phpmyadmin/phpmyadmin/commit/0ce4fd2750491a54d27f94cc1403f9da21738aa6
+
+--- a/db_search.php
++++ b/db_search.php
+@@ -251,7 +251,7 @@ if (isset($_REQUEST['submit_search'])) {
+             $this_url_params['sql_query'] = $newsearchsqls['select_fields'];
+              $browse_result_path = 'sql.php' . PMA_generate_common_url($this_url_params);
+              ?>
+-            <td> <a name="browse_search" href="<?php echo $browse_result_path; ?>" onclick="loadResult('<?php echo $browse_result_path ?> ',' <?php echo  $each_table?> ' , '<?php echo PMA_generate_common_url($GLOBALS['db'], $each_table)?>','<?php echo ($GLOBALS['cfg']['AjaxEnable']); ?>');return false;" ><?php echo __('Browse') ?></a>   </td>
++            <td> <a name="browse_search" href="<?php echo $browse_result_path; ?>" onclick="loadResult('<?php echo $browse_result_path ?> ',' <?php echo  PMA_escapeJsString(htmlspecialchars($each_table) ?> ' , '<?php echo PMA_generate_common_url($GLOBALS['db'], $each_table)?>','<?php echo ($GLOBALS['cfg']['AjaxEnable']); ?>');return false;" ><?php echo __('Browse') ?></a>   </td>
+             <?php
+             $this_url_params['sql_query'] = $newsearchsqls['delete'];
+             $delete_result_path = 'sql.php' . PMA_generate_common_url($this_url_params);
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2041.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2041.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2041.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2041.patch	2016-04-22 10:40:45.000000000 -0400
@@ -0,0 +1,57 @@
+Description: fix for CVE-2016-2041
+Author: Antoine Beaupré <anarcat@orangeseeds.org>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: vendor
+Forwarded: https://github.com/phpmyadmin/phpmyadmin/commit/fe62b69a5b032de8e1d9d0a04456c1cecf46428c
+Reviewed-By: no
+Last-Update: 2016-01-30
+
+--- a/libraries/common.inc.php
++++ b/libraries/common.inc.php
+@@ -229,7 +229,7 @@ unset($key, $value, $variables_whitelist
+  * so we now check if a subform is submitted
+  */
+ $__redirect = null;
+-if (isset($_POST['usesubform'])) {
++if (isset($_POST['usesubform']) && ! defined('PMA_MINIMUM_COMMON')) {
+     // if a subform is present and should be used
+     // the rest of the form is deprecated
+     $subform_id = key($_POST['usesubform']);
+@@ -469,7 +469,7 @@ if (PMA_checkPageValidity($_REQUEST['bac
+  * @todo variables should be handled by their respective owners (objects)
+  * f.e. lang, server, collation_connection in PMA_Config
+  */
+-if (! PMA_isValid($_REQUEST['token']) || $_SESSION[' PMA_token '] != $_REQUEST['token']) {
++if (! PMA_isValid($_REQUEST['token']) || !hash_equals($_SESSION[' PMA_token '], $_REQUEST['token'])) {
+     /**
+      *  List of parameters which are allowed from unsafe source
+      */
+@@ -727,7 +727,7 @@ if (@file_exists($_SESSION['PMA_Theme']-
+     }
+ }
+ 
+-if (! defined('PMA_MINIMUM_COMMON')) {
++if (! defined('PMA_MINIMUM_COMMON') || defined('PMA_SETUP')) {
+     /**
+      * Character set conversion.
+      */
+--- a/libraries/core.lib.php
++++ b/libraries/core.lib.php
+@@ -718,4 +718,12 @@ function PMA_includeJS($url) {
+         return '<script src="./js/' . $url . '" type="text/javascript"></script>' . "\n";
+     }
+ }
++/* Compatibility with PHP < 5.6 */
++if(! function_exists('hash_equals')) {
++    function hash_equals($a, $b) {
++        $ret = strlen($a) ^ strlen($b);
++        $ret |= array_sum(unpack("C*", $a ^ $b));
++        return ! $ret;
++    }
++}
+ ?>
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2045.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2045.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2045.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2045.patch	2016-04-22 10:40:50.000000000 -0400
@@ -0,0 +1,99 @@
+This is a modified version of the upstream patches. In particular, the
+following code was not found in the 3.4 release:
+
+ * libraries/Response.class.php
+ * lint.php
+ * normalization.php
+ * version_check.php
+
+From 0a24f92d081033576bfdd9d4bdec1a54501734c1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C4=8Ciha=C5=99?= <michal@cihar.com>
+Date: Mon, 18 Jan 2016 09:24:23 +0100
+Subject: [PATCH] Set correct content type for JSON responses
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Michal Čihař <michal@cihar.com>
+---
+ import_status.php                     |  6 +++---
+ libraries/Response.class.php          |  5 +----
+ libraries/core.lib.php                | 20 ++++++++++++++++++++
+ libraries/display_import_ajax.lib.php |  2 +-
+ lint.php                              |  5 +++--
+ normalization.php                     |  2 ++
+ setup/validate.php                    |  2 +-
+ version_check.php                     |  2 +-
+ 8 files changed, 32 insertions(+), 12 deletions(-)
+
+--- a/import_status.php
++++ b/import_status.php
+@@ -8,13 +8,13 @@
+ require_once './libraries/common.inc.php';
+ require_once './libraries/display_import_ajax.lib.php';
+ 
+-// AJAX requests can't be cached!
+-header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+-header("Expires: Sat, 11 Jan 1991 06:30:00 GMT"); // Date in the past
+-
+ // $GLOBALS["message"] is used for asking for an import message
+ if (isset($GLOBALS["message"]) && $GLOBALS["message"]) {
+ 
++    // AJAX requests can't be cached!
++    header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
++    header("Expires: Sat, 11 Jan 1991 06:30:00 GMT"); // Date in the past
++
+     header('Content-type: text/html');
+ 
+     // wait 0.3 sec before we check for $_SESSION variable, which is set inside import.php
+--- a/libraries/core.lib.php
++++ b/libraries/core.lib.php
+@@ -631,6 +631,26 @@ function PMA_array_read($path, $array, $
+  */
+ function PMA_array_write($path, &$array, $value)
+ {
++ * Outputs application/json headers. This includes no caching.
++ *
++ * @return void
++ */
++function PMA_headerJSON()
++{
++    if (defined('TESTSUITE') && ! defined('PMA_TEST_HEADERS')) {
++        return;
++    }
++    // No caching
++    PMA_noCacheHeader();
++    // MIME type
++    header('Content-Type: application/json; charset=UTF-8');
++    // Disable content sniffing in browser
++    // This is needed in case we include HTML in JSON, browser might assume it's
++    // html to display
++    header('X-Content-Type-Options: nosniff');
++}
++
++/**
+     $keys = explode('/', $path);
+     $last_key = array_pop($keys);
+     $a =& $array;
+--- a/libraries/display_import_ajax.lib.php
++++ b/libraries/display_import_ajax.lib.php
+@@ -81,7 +81,7 @@ function PMA_import_nopluginCheck() {
+   * @param $id - ID of transfer, usually $upload_id from display_import_ajax.lib.php
+   */
+ function PMA_importAjaxStatus($id) {
+-    header('Content-type: application/json');
++    PMA_headerJSON();
+     echo json_encode(PMA_getUploadStatus($id));
+ }
+ ?>
+--- a/setup/validate.php
++++ b/setup/validate.php
+@@ -14,7 +14,7 @@ require './lib/common.inc.php';
+ $validators = array();
+ require './libraries/config/validate.lib.php';
+ 
+-header('Content-type: application/json');
++PMA_headerJSON();
+ 
+ $ids = PMA_isValid($_POST['id'], 'scalar') ? $_POST['id'] : null;
+ $vids = explode(',', $ids);
diff -Nru phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2560.patch phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2560.patch
--- phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2560.patch	1969-12-31 19:00:00.000000000 -0500
+++ phpmyadmin-3.4.11.1/debian/patches/CVE-2016-2560.patch	2016-04-22 10:49:13.000000000 -0400
@@ -0,0 +1,35 @@
+Description: fix found issues for CVE-2016-2560
+ That CVE was fixed by 5 distinct commits. Only two of those commits
+ would affect code found in wheezy. The others were:
+ .
+  * 7ddce5e39a4e12cd351732955394bc7055c280eb: file not present, vulnerability not found in wheezy
+  * 0667ea8ac7519d7e642eade2686dc393d5faeae3: vulnerability present in 3.4.3.1, but code mysteriously not found in wheezy
+  * fe3be9f4b9edd54dc39919e7dfeaaf4a67c1cf83: vulnerability introduced in 052fd61f (3.5.1)
+ .
+ This patch is made of porting the remaining two commits to wheezy, by hand.
+Author: Antoine Beaupré <anarcat@debian.org>
+Origin: upstream, b8f1e0f325f8f32bd82af64111d8c2e9055a363c 73c8245a3d1893a710447957e28dcfb18d9b47ad
+Forwarded: not-needed
+
+--- a/js/functions.js
++++ b/js/functions.js
+@@ -64,7 +31,7 @@ function pdfPaperSize(a,b){switch(a.toUp
+ "x"?1218.9:1729.13;case "RA3":return b=="x"?864.57:1218.9;case "RA4":return b=="x"?609.45:864.57;case "SRA0":return b=="x"?2551.18:3628.35;case "SRA1":return b=="x"?1814.17:2551.18;case "SRA2":return b=="x"?1275.59:1814.17;case "SRA3":return b=="x"?907.09:1275.59;case "SRA4":return b=="x"?637.8:907.09;case "LETTER":return b=="x"?612:792;case "LEGAL":return b=="x"?612:1008;case "EXECUTIVE":return b=="x"?521.86:756;case "FOLIO":return b=="x"?612:936}return 0}
+ function popupBSMedia(a,b,c,d,e,f){if(e==undefined)e=640;if(f==undefined)f=480;window.open("bs_play_media.php?"+a+"&bs_reference="+b+"&media_type="+c+"&custom_type="+d,"viewBSMedia","width="+e+", height="+f+", resizable=1, scrollbars=1, status=0")}function requestMIMETypeChange(a,b,c,d){if(undefined==d)d="";var e=prompt("Enter custom MIME type",d);e&&e!=d&&changeMIMEType(a,b,c,e)}
+ function changeMIMEType(a,b,c,d){jQuery.post("bs_change_mime_type.php",{bs_db:a,bs_table:b,bs_reference:c,bs_new_mime_type:d})}
+-$(document).ready(function(){$(".inline_edit_sql").live("click",function(){var a=$(this).prev().find("input[name='server']").val(),b=$(this).prev().find("input[name='db']").val(),c=$(this).prev().find("input[name='table']").val(),d=$(this).prev().find("input[name='token']").val(),e=$(this).prev().find("input[name='sql_query']").val(),f=$(this).parent().prev().find(".inner_sql"),j=f.html(),g='<textarea name="sql_query_edit" id="sql_query_edit">'+e+"</textarea>\n";g+='<input type="button" class="btnSave" value="'+
++$(document).ready(function(){$(".inline_edit_sql").live("click",function(){var a=$(this).prev().find("input[name='server']").val(),b=$(this).prev().find("input[name='db']").val(),c=$(this).prev().find("input[name='table']").val(),d=$(this).prev().find("input[name='token']").val(),e=$(this).prev().find("input[name='sql_query']").val(),f=$(this).parent().prev().find(".inner_sql"),j=f.html(),g='<textarea name="sql_query_edit" id="sql_query_edit">'+escapeHtml(e)+"</textarea>\n";g+='<input type="button" class="btnSave" value="'+
+ PMA_messages.strGo+'">\n';g+='<input type="button" class="btnDiscard" value="'+PMA_messages.strCancel+'">\n';f.replaceWith(g);$(".btnSave").each(function(){$(this).click(function(){e=$(this).prev().val();window.location.replace("import.php?server="+encodeURIComponent(a)+"&db="+encodeURIComponent(b)+"&table="+encodeURIComponent(c)+"&sql_query="+encodeURIComponent(e)+"&show_query=1&token="+d)})});$(".btnDiscard").each(function(){$(this).click(function(){$(this).closest(".sql").html('<span class="syntax"><span class="inner_sql">'+
+ j+"</span></span>")})});return false});$(".sqlbutton").click(function(a){a.target.id=="clear"?$("#sqlquery").val(""):insertQuery(a.target.id);return false});$("#export_type").change(function(){if($("#export_type").val()=="svg"){$("#show_grid_opt").attr("disabled","disabled");$("#orientation_opt").attr("disabled","disabled");$("#with_doc").attr("disabled","disabled");$("#show_table_dim_opt").removeAttr("disabled");$("#all_table_same_wide").removeAttr("disabled");$("#paper_opt").removeAttr("disabled",
+ "disabled");$("#show_color_opt").removeAttr("disabled","disabled")}else if($("#export_type").val()=="dia"){$("#show_grid_opt").attr("disabled","disabled");$("#with_doc").attr("disabled","disabled");$("#show_table_dim_opt").attr("disabled","disabled");$("#all_table_same_wide").attr("disabled","disabled");$("#paper_opt").removeAttr("disabled","disabled");$("#show_color_opt").removeAttr("disabled","disabled");$("#orientation_opt").removeAttr("disabled","disabled")}else if($("#export_type").val()=="eps"){$("#show_grid_opt").attr("disabled",
+--- a/libraries/Config.class.php
++++ b/libraries/Config.class.php
+@@ -808,7 +808,7 @@ class PMA_Config
+                 $pma_absolute_uri .= '@';
+             }
+             // Add hostname
+-            $pma_absolute_uri .= $url['host'];
++            $pma_absolute_uri .= urlencode($url['host']);
+             // Add port, if it not the default one
+             if (! empty($url['port'])
+               && (($url['scheme'] == 'http' && $url['port'] != 80)
diff -Nru phpmyadmin-3.4.11.1/debian/patches/series phpmyadmin-3.4.11.1/debian/patches/series
--- phpmyadmin-3.4.11.1/debian/patches/series	2015-10-28 14:48:04.000000000 -0400
+++ phpmyadmin-3.4.11.1/debian/patches/series	2016-04-22 11:53:59.000000000 -0400
@@ -10,3 +10,10 @@
 CVE-2014-9218.patch
 CVE-2015-2206.patch
 CVE-2015-3902.patch
+CVE-2016-1927.patch
+CVE-2016-2038.patch
+CVE-2016-2039.patch
+CVE-2016-2040.patch
+CVE-2016-2041.patch
+CVE-2016-2045.patch
+CVE-2016-2560.patch
As usual, I have uploaded a signed test package to my personal
repository:

https://people.debian.org/~anarcat/debian/wheezy-lts/

I'll be testing those on live servers this afternoon.

A.

-- 
The history of any one part of the earth, like the life of a soldier,
consists of long periods of boredom and short periods of terror.
                       - British geologist Derek V. Ager

Reply to: