Cipher Behavior with Zend_Filter for CakePHP 1.3 – Easy Two-Way Encryption

24 Feb
2010

Here’s a quickie – a Cipher behavior for CakePHP to handle two-way encryption of sensitive data. If you want to store, say, credit card information, you’ll need a way to retrieve it later; Cake’s built-in security hashing is one-way, meaning that once it’s encrypted it ain’t comin’ back. So, I turned to the Zend Framework and brought in Zend_Filter_Encrypt and Zend_Filter_Decrypt to handle the heavy lifting. This behavior uses mcrypt, so you need to have that PHP extension installed, which (as far as I can tell) is fairly standard.

Download the Cipher Behavior Source on Github

First things first – you need to throw a couple of libraries from the Zend Framework into your vendors folder. Yup, I love my Zend! CakePHP teams up very well with ZF.

You’ll need the following Zend Framework libraries (download the framework):

  • Zend_Filter (Zend/Filter.php and Zend/Filter)
  • Zend_Loader (Zend/Loader.php and Zend/Loader)

Put those files in your vendors folder. You’ll also need to update your include_path somewhere (say, app/bootstrap.php) with the following:

ini_set('include_path', ini_get('include_path') . ':' . APP . '/vendors');

I also recommend defining an autoload function somewhere for Zend classes (again, bootstrap.php is a good choice). A simple, Zend-only autoloader might look like this:

function __autoload($path) {
	if (substr($path, 0, 5) == 'Zend_') {
		include str_replace('_', '/', $path) . '.php';
	}
	return $path;
}

The behavior has three config options:

  • key: the encryption key to use. If null (default), then it’ll use the value of Configure::read(‘Security.salt’).
  • automatic: whether to automatically encrypt and decrypt data as it’s saved/retrieved. Defaults to true.
  • fields: an array of fields belong to the model that should be encrypted

Usage of the behavior itself is straightforward: just add Cipher to the $actsAs array of any model you’d like:

Class User extends AppModel {
    var $actsAs = array('Cipher');
}

Class Order extends AppModel {
    var $actsAs = array('Cipher' => array('fields' => array('credit_card', 'expiry')));
}

You can also manually decrypt and encrypt data, either by passing an array of find results (in which case the fields specified in ‘fields’ will be encrypted/decrypted), or by passing a string:

// Manually encrypt/decrypt the results of Model::find()
$encrypted = $this->encrypt($findResults);
$decrypted = $this->decrypt($encrypted );

// Manually encrypt/decrypt a string
$encryptedSecretString= $this->encrypt('my secret string');
$decryptedString = $this->decrypt($encryptedSecretString);

2 Responses to Cipher Behavior with Zend_Filter for CakePHP 1.3 – Easy Two-Way Encryption

Avatar

Louis Stephens

July 6th, 2010 at 7:32 am

I like what you have done here. I was wondering though, is there a way to achieve this using the built in cipher($key)? Sorry, I am pretty new to cake php, and I was told to use the cipher behavior that was in the cakephp bakery and modify it from using “blowfish” to using the built in “cipher” and to be honest I am quite lost.

Avatar

Jamie

July 6th, 2010 at 7:41 am

I highly recommend not using Cake’s cipher function, which is found in the Security class. It’s not true encryption. My behavior uses mcrypt, which is a very good php extension that handles two-way encryption. Blowfish is another decent encryption engine. I’d say that you should use either of those before you resort to Cake’s Security::cipher() function, which is a pretty weak encryption tool. Otherwise, I wouldn’t have written this behavior!

Is there a reason why you don’t want to use mcrypt or blowfish?

Comment Form

top