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?
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.