views:

268

answers:

1

Hi,

I'm trying to encrypt a string, 50-150 characters long, with AES in a mode other than ECB (due to security issues). I wrote an encryption class and am able to encrypt/decrypt perfectly in ECB mode, however when I switch to CBC, CTR or OFB mode, I fail to get the original plaintext back.

Source:

define('DEFAULT_ENCRYPTION_KEY', 'asdHRMfjkahguglw84tlrogl9y8kamaFDaufasds');

class Encryption
    {
    private $mode = 'ctr';
    private $algo = 'rijndael-128';
    private $td  = null;

    function __construct($key = DEFAULT_ENCRYPTION_KEY)
     {
     $this->td = mcrypt_module_open($this->algo, '', $this->mode, '');
     $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), MCRYPT_DEV_URANDOM);
     $key = substr($key, 0, mcrypt_enc_get_key_size($this->td));
     mcrypt_generic_init($this->td, $key, $iv);
     }

    public function encrypt($data)
     {
     $encrypted_data = mcrypt_generic($this->td, $data);
     return $encrypted_data;
     } 

    public function decrypt($data)
     {
     $decrypted_data = mdecrypt_generic($this->td, $data);
     $decrypted_data = rtrim($decrypted_data, "\0");
     return $decrypted_data;
     }

    function __destruct()
     {
     mcrypt_generic_deinit($this->td);
     mcrypt_module_close($this->td);
     }

    }

$crypt1 = new Encryption();
$enc = $crypt1->encrypt('hello world');

$crypt2 = new Encryption();
$dec = $crypt2->decrypt($enc);

echo $dec;

The return value $dec, does not equal 'hello world'.

Any ideas?

+1  A: 

It looks like you are discarding the initialization vector, $iv. You'll need to know the IV to successfully decrypt the message. The IV is not secret; it is usually passed along with the ciphertext in some sort of enveloping format.

Because there's no feedback from block to block, ECB doesn't need an initialization vector. But block chaining modes need some data to "bootstrap" the cipher mode.

erickson
Hm, but if I use the class like this, the IV should stay the same:$crypt1 = new Encryption();$enc = $crypt1->encrypt('hello world');$dec = $crypt1->decrypt($enc);However, it still produces random plaintext as output.
Matic
That's assuming that the IV is stored inside $td somewhere, which isn't necessarily the case. It would be hard to argue that doing so is good design, since in most applications the same cipher object is unlikely to encrypt and decrypt the same message, and when encrypting multiple messages a different IV should be used for each message.
erickson