Skip to content

Commit

Permalink
Use random iv values in rijndael.
Browse files Browse the repository at this point in the history
Using fixed iv values has a number of known problems like dictionary
attacks against the cipher key. Use a random iv value for all future
encrpyted values. Provide backwards compatibility for values encrypted
with fixed iv's, and silently upgrade values for enhanced security.
  • Loading branch information
markstory committed Feb 10, 2013
1 parent 613aa19 commit 974ac44
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
19 changes: 18 additions & 1 deletion lib/Cake/Test/Case/Utility/SecurityTest.php
Expand Up @@ -256,10 +256,27 @@ public function testRijndael() {
$result = Security::rijndael('', $key, 'encrypt');
$this->assertEquals('', Security::rijndael($result, $key, 'decrypt'));

$result = Security::rijndael($txt, $key = 'this is my key of over 32 chars, yes it is', 'encrypt');
$key = 'this is my key of over 32 chars, yes it is';
$result = Security::rijndael($txt, $key, 'encrypt');
$this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt'));
}

/**
* Test that rijndael() can still decrypt values with a fixed iv.
*
* @return
*/
public function testRijndaelBackwardCompatibility() {
$this->skipIf(!function_exists('mcrypt_encrypt'));

$txt = 'The quick brown fox jumped over the lazy dog.';
$key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';

// Encrypted before random iv
$value = base64_decode('1WPjnq96LMzLGwNgmudHF+cAIqVUN5DaUZEpf5tm1EzSgt5iYY9o3d66iRI/fKJLTlTVGsa8HzW0jDNitmVXoQ==');
$this->assertEquals($txt, Security::rijndael($value, $key, 'decrypt'));
}

/**
* testRijndaelInvalidOperation method
*
Expand Down
17 changes: 15 additions & 2 deletions lib/Cake/Utility/Security.php
Expand Up @@ -198,6 +198,10 @@ public static function cipher($text, $key) {
/**
* Encrypts/Decrypts a text using the given key using rijndael method.
*
* Prior to 2.3.1, a fixed initialization vector was used. This was not
* secure. This method now uses a random iv, and will silently upgrade values when
* they are re-encrypted.
*
* @param string $text Encrypted string to decrypt, normal string to encrypt
* @param string $key Key to use as the encryption key for encrypted data.
* @param string $operation Operation to perform, encrypt or decrypt
Expand All @@ -218,12 +222,21 @@ public static function rijndael($text, $key, $operation) {
}
$algorithm = MCRYPT_RIJNDAEL_256;
$mode = MCRYPT_MODE_CBC;
$ivSize = mcrypt_get_iv_size($algorithm, $mode);

$cryptKey = substr($key, 0, 32);
$iv = substr($key, strlen($key) - 32, 32);

if ($operation === 'encrypt') {
return mcrypt_encrypt($algorithm, $cryptKey, $text, $mode, $iv);
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
return $iv . '$$' . mcrypt_encrypt($algorithm, $cryptKey, $text, $mode, $iv);
}
// Backwards compatible decrypt with fixed iv
if (substr($text, $ivSize, 2) !== '$$') {
$iv = substr($key, strlen($key) - 32, 32);
return rtrim(mcrypt_decrypt($algorithm, $cryptKey, $text, $mode, $iv), "\0");
}
$iv = substr($text, 0, $ivSize);
$text = substr($text, $ivSize + 2);
return rtrim(mcrypt_decrypt($algorithm, $cryptKey, $text, $mode, $iv), "\0");
}

Expand Down

0 comments on commit 974ac44

Please sign in to comment.