Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #672 from sitedyno/cookie-encryption-#471

Add stronger encryption, and make it available in cookiecomponent.

Fixes #471
Fixes #176
Fixes #2043
Fixes #1524
  • Loading branch information...
commit 085ad0bb42f31c50f49001bae14688a97c554033 2 parents 6c9b2a1 + 304d001
@markstory markstory authored
View
24 lib/Cake/Controller/Component/CookieComponent.php
@@ -130,11 +130,10 @@ class CookieComponent extends Component {
/**
* Type of encryption to use.
*
- * Currently only one method is available
+ * Currently two methods are available: cipher and rijndael
* Defaults to Security::cipher();
*
* @var string
- * @todo add additional encryption methods
*/
protected $_type = 'cipher';
@@ -343,14 +342,23 @@ public function destroy() {
}
/**
- * Will allow overriding default encryption method.
+ * Will allow overriding default encryption method. Use this method
+ * in ex: AppController::beforeFilter() before you have read or
+ * written any cookies.
*
* @param string $type Encryption method
* @return void
- * @todo NOT IMPLEMENTED
*/
public function type($type = 'cipher') {
- $this->_type = 'cipher';
+ $availableTypes = array(
+ 'cipher',
+ 'rijndael'
+ );
+ if (!in_array($type, $availableTypes)) {
+ trigger_error(__d('cake_dev', 'You must use cipher or rijndael for cookie encryption type'), E_USER_WARNING);
+ $type = 'cipher';
+ }
+ $this->_type = $type;
}
/**
@@ -439,7 +447,7 @@ protected function _encrypt($value) {
if ($this->_encrypted === true) {
$type = $this->_type;
- $value = "Q2FrZQ==." . base64_encode(Security::$type($value, $this->key));
+ $value = "Q2FrZQ==." . base64_encode(Security::$type($value, $this->key, 'encrypt'));
}
return $value;
}
@@ -462,7 +470,7 @@ protected function _decrypt($values) {
if ($pos !== false) {
$val = substr($val, 8);
- $decrypted[$name][$key] = $this->_explode(Security::$type(base64_decode($val), $this->key));
+ $decrypted[$name][$key] = $this->_explode(Security::$type(base64_decode($val), $this->key, 'decrypt'));
}
}
} else {
@@ -471,7 +479,7 @@ protected function _decrypt($values) {
if ($pos !== false) {
$value = substr($value, 8);
- $decrypted[$name] = $this->_explode(Security::$type(base64_decode($value), $this->key));
+ $decrypted[$name] = $this->_explode(Security::$type(base64_decode($value), $this->key, 'decrypt'));
}
}
}
View
47 lib/Cake/Test/Case/Utility/SecurityTest.php
@@ -157,4 +157,51 @@ public function testCipherEmptyKey() {
$key = '';
$result = Security::cipher($txt, $key);
}
+
+/**
+ * testRijndael method
+ *
+ * @return void
+ */
+ public function testRijndael() {
+ $txt = 'The quick brown fox jumped over the lazy dog.';
+ $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
+
+ $result = Security::rijndael($txt, $key, 'encrypt');
+ $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt'));
+
+ $result = Security::rijndael($key, $txt, 'encrypt');
+ $this->assertEquals($key, Security::rijndael($result, $txt, 'decrypt'));
+
+ $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');
+ $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt'));
+ }
+
+/**
+ * testRijndaelInvalidOperation method
+ *
+ * @expectedException PHPUnit_Framework_Error
+ * @return void
+ */
+ public function testRijndaelInvalidOperation() {
+ $txt = 'The quick brown fox jumped over the lazy dog.';
+ $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
+ $result = Security::rijndael($txt, $key, 'foo');
+ }
+
+/**
+ * testRijndaelInvalidKey method
+ *
+ * @expectedException PHPUnit_Framework_Error
+ * @return void
+ */
+ public function testRijndaelInvalidKey() {
+ $txt = 'The quick brown fox jumped over the lazy dog.';
+ $key = 'too small';
+ $result = Security::rijndael($txt, $key, 'encrypt');
+ }
+
}
View
34 lib/Cake/Utility/Security.php
@@ -155,4 +155,38 @@ public static function cipher($text, $key) {
return $out;
}
+/**
+ * Encrypts/Decrypts a text using the given key using rijndael method.
+ *
+ * @param string $text Encrypted string to decrypt, normal string to encrypt
+ * @param string $key Key to use
+ * @param string $operation Operation to perform, encrypt or decrypt
+ * @return string Encrypted/Descrypted string
+ */
+ public static function rijndael($text, $key, $operation) {
+ if (empty($key)) {
+ trigger_error(__d('cake_dev', 'You cannot use an empty key for Security::rijndael()'), E_USER_WARNING);
+ return '';
+ }
+ if (empty($operation) || !in_array($operation, array('encrypt', 'decrypt'))) {
+ trigger_error(__d('cake_dev', 'You must specify the operation for Security::rijndael(), either encrypt or decrypt'), E_USER_WARNING);
+ return '';
+ }
+ if (strlen($key) < 32) {
+ trigger_error(__d('cake_dev', 'You must use a key larger than 32 bytes for Security::rijndael()'), E_USER_WARNING);
+ return '';
+ }
+ $algorithm = 'rijndael-256';
+ $mode = 'cbc';
+ $cryptKey = substr($key, 0, 32);
+ $iv = substr($key, strlen($key) - 32, 32);
+ $out = '';
+ if ($operation === 'encrypt') {
+ $out .= mcrypt_encrypt($algorithm, $cryptKey, $text, $mode, $iv);
+ } elseif ($operation === 'decrypt') {
+ $out .= rtrim(mcrypt_decrypt($algorithm, $cryptKey, $text, $mode, $iv), "\0");
+ }
+ return $out;
+ }
+
}
Please sign in to comment.
Something went wrong with that request. Please try again.