Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Cookie encryption #471 #672

Merged
merged 1 commit into from

4 participants

@sitedyno

If it's too late for 2.2, just let me know and I will resubmit later. There should be no BC issues that I can see. Ready and willing to update as needed :)

I believe this would close the following tickets (provide an easy workaround at any rate).
http://cakephp.lighthouseapp.com/projects/42648/tickets/471-securitycipher-function-cannot-decrypt
http://cakephp.lighthouseapp.com/projects/42648/tickets/176
http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2043-php5-suhosin-breaks-securitycipher#ticket-2043-2
http://cakephp.lighthouseapp.com/projects/42648/tickets/1524

lib/Cake/Utility/Security.php
@@ -155,4 +155,36 @@ public static function cipher($text, $key) {
return $out;
}
+/**
+ * Encrypts/Decrypts a text using the given key. To use this encryption method
+ * for cookies call $this->Cookie->type('rijndael'); in
@lorenzo Owner
lorenzo added a note

No references to Cookie should be placed in this class. It is fine to add to the Cookie component, though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lorenzo
Owner

This is +1 for me

@markstory
Owner

My only whine is no tests for Security::rijndael(). A few tests covering the exceptional cases and the encrypt/decrypt steps would be ideal.

@markstory
Owner

Outside of that I think its a great addition :)

@sitedyno

Working on some tests

@sitedyno

If there is anything else let me know :)

@ADmad
Collaborator

Could you please squash the commits into one? Since all commits relate to a single feature its better to have a single commit in the history so that its easier to track down something in future.

@sitedyno

Done.

@markstory
Owner

I think this is good to go, I'll update the docs tomorrow night and merge this in.

@markstory markstory was assigned
@markstory markstory merged commit 085ad0b into cakephp:2.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 30, 2012
  1. @sitedyno
This page is out of date. Refresh to see the latest.
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;
+ }
+
}
Something went wrong with that request. Please try again.