Cipher:
Encryption Mode:
Key Length:
Key Length:
Block Length:
Key Derivation:
<?php include('Crypt/AESRijndaelDESTripleDESRC4.php'); $cipher = new Crypt_AESRijndaelDESTripleDESRC4(CRYPT_DESAESRIJNDAEL_MODE_ECBCFBOFBCTRCRYPT_DES_MODE_3CBC); // could use CRYPT_DES_MODE_CBC // could use CRYPT_DES_MODE_CBC or CRYPT_DES_MODE_CBC3 // could use CRYPT_RIJNDAEL_MODE_CBC // could use CRYPT_AES_MODE_CBC $cipher->setBlockLength(160); $cipher->setBlockLength(192); $cipher->setBlockLength(224); $cipher->setBlockLength(256); // keys are null-padded to the closest valid size // longer than the longest key and it's truncated //$cipher->setKeyLength(128160192224256); //$cipher->setKeyLength(128192256); $cipher->setKey('abcdefghijklmnopqrstuvwxijklmnopijklmnopqrstuvwxqrstuvwxyz123456yz3456'); $cipher->setPassword('whatever'); // the following does the same thing: //$cipher->setPassword('whatever', 'pbkdf2', 'sha1', 'phpseclib/salt', 1000, 128 / 8, 128192256 / 8, 128160192224256 / 8); //$cipher->setIV('...'); // defaults to all-NULLs if not explicitely defined $cipher->disablePadding(); $size = 10 * 1024; $size-= 16; // make the plaintext length a multiple of the block length $size-= 16; // make the plaintext length a multiple of the block length $size-= 4; // make the plaintext length a multiple of the block length $plaintext = str_repeat('a', $size); echo $cipher->decrypt($cipher->encrypt($plaintext)); // without continuous mode the following would yield the same output as the above // with continuous mode it's treated the same way str_repeat('a', 2 * $size) would be $plaintext = str_repeat('a', $size); echo $cipher->decrypt($cipher->encrypt($plaintext)); ?>
In theory, encrypting a string using a stream cipher should yield the same results no matter how that string is partitioned out. At least when enableContinuousBuffer() has been called. This is not the case with mcrypt. The following link demonstrates how phpseclib's rewritten CFB implementation (CFB mode is one of several modes that turn block ciphers into stream ciphers) guarantees this behavior:
Most stream ciphers (and block ciphers operating in a mode - like CTR, CFB and OFB - that turns them into stream ciphers) work by generating a stream of pseudorandom characters called a keystream and then XOR'ing that with the plaintext. This *effectively* makes them one-time pads which, in theory, can provide perfect secrecy. The problem with one-time pads is that they're not as versatile as one might desire. Among other things, a keystream must never be reset, lest it be possible for an attacker to recover the keystream via a known-plaintext attack. ie. $ciphertext ^ $plaintext = $key
. If $key
is constant (because the keystream's being reset or something) than an attacker can recover any $plaintext
, but if not - if it's dynamic - then the only key that an attacker could recover is their own.
Inner chaining, as used by SSH1, does DES three times on the whole string. Outer chaining, as used by SSH2 and most other 3DES implementations, does DES three times on each block. Outer chaining is generally considered more secure.
The following table compares the speed of five different pure-PHP implementations of AES (one of which is Crypt_Rijndael and one of which is Crypt_AES) when ran on 150KB of text on a 1.8GHz Pentium 4-M. The numbers listed are averaged from five different trials and are measured in seconds. phpseclib's two implementations are highlighted. All implementations can be viewed by clicking on their names.
Implementation | Speed |
movable-type.phps | 15.6844158172 |
phpaes.phps | 39.9537248135 |
phpclasses1.phps | 15.0100150108 |
phpclasses2.phps | 62.591713190079 |
phpseclib-aes.phps | 2.03581542968752 |
phpseclib-rijndael.phps | 2.62501101493836 |
As can be seen, phpseclib's implementations are the fastest. phpseclib-aes.phps is faster than phpseclib-rijndael.phps because phpseclib-rijndael.phps has to contend with multiple block sizes whereas phpseclib-aes.phps does not. Note that if mcrypt weren't explicitily disabled phpseclib would have been even faster.