phpseclib/phpseclib — pull request #52 by petrich (2013-01-14 14:32:10+00:00)
Title: 3DES: Fixed ContinuousBuffer() in CTR/CFB/OFB

Hi Terra... finished with 3DES

FIXED: multiple calls to enable/disableContinuousBuffer() work's now in CTR/CFB/OFB
FIXED: "Illegal string offset" and strlen(array()) Warning/Notice
Performance improvement in CFB Mode with enableContinuousBuffer() using MODE_MCRYPT

Example for ContinuousBuffer() in CTR/CFB/OFB
```php
ini_set('error_reporting',E_ALL);
define('CRYPT_DES_MODE',CRYPT_DES_MODE_INTERNAL); // or CRYPT_DES_MODE_MCRYPT

$cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); // or CRYPT_DES_MODE_OFB or CRYPT_DES_MODE_CFB (similar results)
$cipher->setKey('1234567890123456');
$cipher->enableContinuousBuffer();
$ciphertext = $cipher->encrypt('1').$cipher->encrypt('2');
$cipher->disableContinuousBuffer();

echo bin2hex($ciphertext)."\n";
echo bin2hex($cipher->encrypt('12'));
```
Output:
af93
b4ec

Expected:
af93
af93

Output after bugfix:
af93
af93

...

Speedtest results in CFB Mode with enableContinuousBuffer() using MODE_MCRYPT
Old Code:
1000000 bytes, randomly partitionated between 1 and 1 bytes)... Time: 132.09
1000000 bytes, randomly partitionated between 1 and 7 bytes)... Time: 125.16
1000000 bytes, randomly partitionated between 7 and 7 bytes)... Time: 124.37
1000000 bytes, randomly partitionated between 8 and 8 bytes)... Time: 124
1000000 bytes, randomly partitionated between 8 and 9 bytes)... Time: 102.71
1000000 bytes, randomly partitionated between 1 and 10 bytes)... Time: 112.39
1000000 bytes, randomly partitionated between 16 and 16 bytes)... Time: 63.08
1000000 bytes, randomly partitionated between 16 and 17 bytes)... Time: 54.06
1000000 bytes, randomly partitionated between 1 and 50 bytes)... Time: 33.11
1000000 bytes, randomly partitionated between 1 and 100 bytes)... Time: 17.39
1000000 bytes, randomly partitionated between 1 and 200 bytes)... Time: 9.33
1000000 bytes, randomly partitionated between 1 and 300 bytes)... Time: 6.22
1000000 bytes, randomly partitionated between 1 and 400 bytes)... Time: 4.81
1000000 bytes, randomly partitionated between 1 and 500 bytes)... Time: 3.95
1000000 bytes, randomly partitionated between 1 and 600 bytes)... Time: 3.42
1000000 bytes, randomly partitionated between 1 and 700 bytes)... Time: 2.99
1000000 bytes, randomly partitionated between 1 and 800 bytes)... Time: 2.67
1000000 bytes, randomly partitionated between 1 and 900 bytes)... Time: 2.46
1000000 bytes, randomly partitionated between 1 and 1000 bytes)... Time: 2.27
1000000 bytes, randomly partitionated between 1 and 10000 bytes)... Time: 0.62

New Code:
1000000 bytes, randomly partitionated between 1 and 1 bytes)... Time: 9.37
1000000 bytes, randomly partitionated between 1 and 7 bytes)... Time: 3.76
1000000 bytes, randomly partitionated between 7 and 7 bytes)... Time: 2.99
1000000 bytes, randomly partitionated between 8 and 8 bytes)... Time: 2.85
1000000 bytes, randomly partitionated between 8 and 9 bytes)... Time: 2.76
1000000 bytes, randomly partitionated between 1 and 10 bytes)... Time: 3.25
1000000 bytes, randomly partitionated between 16 and 16 bytes)... Time: 2.51
1000000 bytes, randomly partitionated between 16 and 17 bytes)... Time: 2.29
1000000 bytes, randomly partitionated between 1 and 50 bytes)... Time: 1.79
1000000 bytes, randomly partitionated between 1 and 100 bytes)... Time: 1.4
1000000 bytes, randomly partitionated between 1 and 200 bytes)... Time: 1.22
1000000 bytes, randomly partitionated between 1 and 300 bytes)... Time: 1.15
1000000 bytes, randomly partitionated between 1 and 400 bytes)... Time: 1.12
1000000 bytes, randomly partitionated between 1 and 500 bytes)... Time: 1.11
1000000 bytes, randomly partitionated between 1 and 600 bytes)... Time: 1.08
1000000 bytes, randomly partitionated between 1 and 700 bytes)... Time: 1.07
1000000 bytes, randomly partitionated between 1 and 800 bytes)... Time: 1.14
1000000 bytes, randomly partitionated between 1 and 900 bytes)... Time: 1.05
1000000 bytes, randomly partitionated between 1 and 1000 bytes)... Time: 1.04
1000000 bytes, randomly partitionated between 1 and 10000 bytes)... Time: 0.51

Speedtestscript:
```php
define('CRYPT_DES_MODE',CRYPT_DES_MODE_MCRYPT);
$cipher = new Crypt_TripleDES(CRYPT_DES_MODE_CFB);
$cipher->setKey('1234567890123456');
$cipher->enableContinuousBuffer();
mt_srand(1);//fixed seed

foreach(array(array(1000000,1,1),array(1000000,1,7),array(1000000,7,7),array(1000000,8,8),array(1000000,8,9),array(1000000,1,10),array(1000000,16,16),array(1000000,16,17),array(1000000,1,50),array(1000000,1,100),array(1000000,1,200),array(1000000,1,300),array(1000000,1,400),array(1000000,1,500),array(1000000,1,600),array(1000000,1,700),array(1000000,1,800),array(1000000,1,900),array(1000000,1,1000),array(1000000,1,10000)) as $k=>$v)
{
$bytes_len=$v[0];
$part_min=$v[1];
$part_max=$v[2];
for($j=0;$j<1;$j++)
{
echo str_pad($bytes_len." bytes, randomly partitionated between $part_min and $part_max bytes)... ",70);
$s=microtime(true);

for($i=0;$i<$bytes_len;)
{
$part_len=mt_rand($part_min,$part_max);
$cipher->decrypt($cipher->encrypt(str_repeat('a',$part_len)));
$i+=$part_len;
}

$e=microtime(true);
echo "Time: ".round($e-$s,2)."\n";
}
}

```