Implement rijndael optional cookie encryption.

This commit is contained in:
Heath Nail 2012-05-29 19:25:01 -04:00
parent 06476a22da
commit 304d001dfb
3 changed files with 97 additions and 8 deletions

View file

@ -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 @@ class CookieComponent extends Component {
}
/**
* 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 @@ class CookieComponent extends Component {
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 @@ class CookieComponent extends Component {
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 @@ class CookieComponent extends Component {
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 file

@ -157,4 +157,51 @@ class SecurityTest extends CakeTestCase {
$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 file

@ -155,4 +155,38 @@ class Security {
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;
}
}