phpseclib/phpseclib — pull request #65 by petrich (2013-01-26 09:56:23+00:00)
Title: Rijndael: Performance update

Hi Terra... here the performance patch for Rijndael and AES. Getting even more performance then the mentioned 30-35%.

Speedtests/results:

Rijndael:
```php
$s=microtime(true);
$rijndael = new Crypt_Rijndael();
$rijndael->decrypt($rijndael->encrypt(str_repeat('a',1024*1024)));
echo "Time used de/encrypting 1MB: ". round(microtime(true) - $s, 1);
```
Old Code:
Time used de/encrypting 1MB: 17.8

New Code:
Time used de/encrypting 1MB: 7.4

AES:
```php
$s=microtime(true);
define('CRYPT_AES_MODE',CRYPT_AES_MODE_INTERNAL);
$aes = new Crypt_AES();
$aes->decrypt($aes->encrypt(str_repeat('a',1024*1024)));
echo "Time used de/encrypting 1MB: ". round(microtime(true) - $s, 1);
```
Old Code:
Time used de/encrypting 1MB: 13.9

New Code:
Time used de/encrypting 1MB: 4.3

(for AES.php: Be sure including also the updated Rijndael.php or AES won't work)

...

Remarks regarding the commit...
Using a low array() index range [0-255] in the mixColumn and sbox tables very speed up the [inv]MixColumns and [inv]subWord operations on those PHP array-ed tables.
This was the main thing for the performance win in Rijndael.php and AES.php

Additional to this, but currently only in AES.php, it was possible to use (selfrotating) integer vars ($state0-3) instead of using the smart (but performance expensive) selfsyncronizing array ($state[0-3]) for the words.
This brought (on my machine) about 25% extra performance in AES.php

It's possible to use the rotating interger vars ($state0-3/$State0-3) in a more efficient than currently (which will bring additional ~5% speed up), but will also blow up the code there, so i let it as it now is.

Also it's possible using the key arrays $w/$dw in a more (PHP)efficient way (brings about additional 2-4% speedup), but it was just not-looking-nice code... so i let it out... except you want it.
The code in AES.php _en/_decryptBlock() just looks to smart than blowing it up or make it unreadable for speed lower then 10% :-)

Using inline [inv]subWord'ing in the final round would bring about 2-4% performance (seems to depends on the machine/CPU features) but also will made the related code more or less unreadable so i also leave the [in]subWord'ing call's as it is.

At least it's, of course, also possible in Rijndael not dealing with the different blocksize in _de/_encryptBlock() but using block-optimized methods [ie: _de/_encryptBlock_128|160|192|224|256()] as you do it in AES.php to win about 30%-40% performance.
But this will blow up the Rijndael code up to 40% also (but good readable). I'm not sure you are interesseted in such an update for Rijndael, are you? Personally... i would like it for this performance win :-) leaving the current _de/_encryptBlock() additional in Rijndael.php as it is for academic and learning reasons.