From 4f35baf58d57832e807e3254b95ab966ac0ddd65 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 3 Jan 2013 18:18:33 +0100 Subject: [PATCH 1/4] [task/travis-skipped-tests] List skipped tests on travis. Turn on PHPUnit's verbose mode so we get detailed information about skipped tests on travis (when there are any). --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff3b3497..9f4ca74c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ php: - 5.4 script: - - phpunit + - phpunit --verbose From bbb47168da7c36371eb2b921f720e9bcbe153cf3 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 3 Jan 2013 18:43:08 +0100 Subject: [PATCH 2/4] [task/fix-test-autoloader] Fix autoloader to support failing/erroring tests. Before showing error output PHPUnit 3.7.x calls class_exists() on some PHPUnit Extension class names that may not exist. Calling class_exists() already triggers the autoload function in which require() then obviously fails. We now check whether a file is includable by simply looping over all possible include directories. --- tests/bootstrap.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index eb7136b8..13a8e81b 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -9,14 +9,34 @@ // class files of phpseclib require() other dependencies. set_include_path(implode(PATH_SEPARATOR, array( dirname(__FILE__) . '/../phpseclib/', + dirname(__FILE__) . '/', get_include_path(), ))); +function phpseclib_is_includable($suffix) +{ + foreach (explode(PATH_SEPARATOR, get_include_path()) as $prefix) + { + $ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR; + $file = $prefix . $ds . $suffix; + + if (file_exists($file)) + { + return true; + } + } + + return false; +} + function phpseclib_autoload($class) { $file = str_replace('_', '/', $class) . '.php'; - require $file; + if (phpseclib_is_includable($file)) + { + require $file; + } } spl_autoload_register('phpseclib_autoload'); From 359e38b4d4e8201342aad876e4868acaf5b82936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-J=C3=BCrgen=20Petrich?= Date: Fri, 4 Jan 2013 14:23:34 +0700 Subject: [PATCH 3/4] fixed corrupted decrypt() in CTR mode $buffer['encrypted'] (which is always empty) should be $buffer['ciphertext'] or buffered stream will get corrupt... Example: define('CRYPT_AES_MODE',CRYPT_AES_MODE_INTERNAL);//in MODE_MCRYPT all is fine $aes = new Crypt_AES(CRYPT_AES_MODE_CTR); $aes->setKey(':-8'); $aes->enableContinuousBuffer(); $plaintext = ':-):-):-):-):-):-)'; for($i=0; $iDecrypt($aes->Encrypt($plaintext[$i])); } Output: :-):-):-):-):-):-( Expected: :-):-):-):-):-):-) After Bugfix, output is: :-):-):-):-):-):-) --- phpseclib/Crypt/Rijndael.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpseclib/Crypt/Rijndael.php b/phpseclib/Crypt/Rijndael.php index dc22488b..48795d22 100644 --- a/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/Crypt/Rijndael.php @@ -879,7 +879,7 @@ class Crypt_Rijndael { if ($this->continuousBuffer) { $this->decryptIV = $xor; if ($start = strlen($ciphertext) % $block_size) { - $buffer['ciphertext'] = substr($key, $start) . $buffer['encrypted']; + $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; } } break; @@ -1493,4 +1493,4 @@ class Crypt_Rijndael { } // vim: ts=4:sw=4:et: -// vim6: fdl=1: \ No newline at end of file +// vim6: fdl=1: From d1f71cc5a7b55ad65c741d2686b8541bec0d1a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-J=C3=BCrgen=20Petrich?= Date: Sat, 5 Jan 2013 16:23:35 +0700 Subject: [PATCH 4/4] Fixed CFB Decrypt(). Fixed OFB warnings Fixed/rewritten: Decrypt() in CFB mode to work clean with enableContinuousBuffer() Fixed: PHP's strlen(array()) warning in OFB mode, Fixed: disableContinuousBuffer() clear's now also the $enbuffer/$debuffer arrays so that multiple calls to enable/disableContinuousBuffer() will work without old buffers --- phpseclib/Crypt/Rijndael.php | 137 +++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 61 deletions(-) diff --git a/phpseclib/Crypt/Rijndael.php b/phpseclib/Crypt/Rijndael.php index 48795d22..ddd51415 100644 --- a/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/Crypt/Rijndael.php @@ -387,7 +387,7 @@ class Crypt_Rijndael { * @var String * @access private */ - var $enbuffer = array('encrypted' => '', 'xor' => ''); + var $enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0); /** * Decryption buffer for CTR, OFB and CFB modes @@ -396,7 +396,7 @@ class Crypt_Rijndael { * @var String * @access private */ - var $debuffer = array('ciphertext' => ''); + var $debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0); /** * Default Constructor. @@ -763,42 +763,46 @@ class Crypt_Rijndael { } break; case CRYPT_RIJNDAEL_MODE_CFB: - if (strlen($buffer['xor'])) { - $ciphertext = $plaintext ^ $buffer['xor']; - $iv = $buffer['encrypted'] . $ciphertext; - $start = strlen($ciphertext); - $buffer['encrypted'].= $ciphertext; - $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); - } else { - $ciphertext = ''; - $iv = $this->encryptIV; - $start = 0; - } + $iv = $this->encryptIV; + $pos = $this->continuousBuffer === true ? $buffer['pos'] : 0; + $len = strlen($plaintext); - for ($i = $start; $i < strlen($plaintext); $i+=$block_size) { - $block = substr($plaintext, $i, $block_size); - $xor = $this->_encryptBlock($iv); - $iv = $block ^ $xor; - if ($continuousBuffer && strlen($iv) != $block_size) { - $buffer = array( - 'encrypted' => $iv, - 'xor' => substr($xor, strlen($iv)) - ); + for ($i=0; $pos && $len; --$len, ++$i) + { + $iv[$pos] = $iv[$pos] ^ $plaintext[$i]; + $ciphertext .= $iv[$pos]; + $pos = ($pos+1) % $block_size; } - $ciphertext.= $iv; - } + for (; $len >= $block_size; $len-=$block_size, $i+=$block_size) + { + $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size); + $ciphertext .= $iv; + } + if ($len) + { + $iv = $this->_encryptBlock($iv); + while ($len--) + { + $iv[$pos] = $iv[$pos] ^ $plaintext[$i]; + $ciphertext .= $iv[$pos]; - if ($this->continuousBuffer) { - $this->encryptIV = $iv; - } + ++$i; + ++$pos; + } + } + if($this->continuousBuffer) + { + $this->encryptIV = $iv; + $buffer['pos'] = $pos; + } break; case CRYPT_RIJNDAEL_MODE_OFB: $xor = $this->encryptIV; - if (strlen($buffer)) { + if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $xor = $this->_encryptBlock($xor); - $buffer.= $xor; - $key = $this->_string_shift($buffer, $block_size); + $buffer['xor'].= $xor; + $key = $this->_string_shift($buffer['xor'], $block_size); $ciphertext.= substr($plaintext, $i, $block_size) ^ $key; } } else { @@ -811,7 +815,7 @@ class Crypt_Rijndael { if ($this->continuousBuffer) { $this->encryptIV = $xor; if ($start = strlen($plaintext) % $block_size) { - $buffer = substr($key, $start) . $buffer; + $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } } @@ -884,42 +888,51 @@ class Crypt_Rijndael { } break; case CRYPT_RIJNDAEL_MODE_CFB: - if (strlen($buffer['ciphertext'])) { - $plaintext = $ciphertext ^ substr($this->decryptIV, strlen($buffer['ciphertext'])); - $buffer['ciphertext'].= substr($ciphertext, 0, strlen($plaintext)); - if (strlen($buffer['ciphertext']) == $block_size) { - $xor = $this->_encryptBlock($buffer['ciphertext']); - $buffer['ciphertext'] = ''; - } - $start = strlen($plaintext); - $block = $this->decryptIV; - } else { - $plaintext = ''; - $xor = $this->_encryptBlock($this->decryptIV); - $start = 0; - } + $iv = $this->decryptIV; + $pos = $this->continuousBuffer === true ? $buffer['pos'] : 0; + $len = strlen($ciphertext); - for ($i = $start; $i < strlen($ciphertext); $i+=$block_size) { - $block = substr($ciphertext, $i, $block_size); - $plaintext.= $block ^ $xor; - if ($continuousBuffer && strlen($block) != $block_size) { - $buffer['ciphertext'].= $block; - $block = $xor; - } else if (strlen($block) == $block_size) { - $xor = $this->_encryptBlock($block); + // cfb routines inspired by: http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1 + for ($i=0; $pos && $len; --$len, ++$i) + { + $plaintext .= $iv[$pos] ^ $ciphertext[$i]; + $iv[$pos] = $ciphertext[$i]; + $pos = ($pos+1) % $block_size; + } + + for (; $len >= $block_size; $len-=$block_size, $i+=$block_size) + { + $iv = $this->_encryptBlock($iv); + $cb = substr($ciphertext, $i, $block_size); + $plaintext .= $iv ^ $cb; + $iv = $cb; + } + + if ($len) + { + $iv = $this->_encryptBlock($iv); + while ($len--) + { + $plaintext .= $iv[$pos] ^ $ciphertext[$i]; + $iv[$pos] = $ciphertext[$i]; + + ++$i; + ++$pos; + } + } + if ($this->continuousBuffer) + { + $this->decryptIV = $iv; + $buffer['pos'] = $pos; } - } - if ($this->continuousBuffer) { - $this->decryptIV = $block; - } break; case CRYPT_RIJNDAEL_MODE_OFB: $xor = $this->decryptIV; - if (strlen($buffer)) { + if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $xor = $this->_encryptBlock($xor); - $buffer.= $xor; - $key = $this->_string_shift($buffer, $block_size); + $buffer['xor'].= $xor; + $key = $this->_string_shift($buffer['xor'], $block_size); $plaintext.= substr($ciphertext, $i, $block_size) ^ $key; } } else { @@ -932,7 +945,7 @@ class Crypt_Rijndael { if ($this->continuousBuffer) { $this->decryptIV = $xor; if ($start = strlen($ciphertext) % $block_size) { - $buffer = substr($key, $start) . $buffer; + $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } } @@ -1454,6 +1467,8 @@ class Crypt_Rijndael { $this->continuousBuffer = false; $this->encryptIV = $this->iv; $this->decryptIV = $this->iv; + $this->enbuffer = array('encrypted' => '', 'xor' => '', 'pos' => 0); + $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0); } /**