Automatic DB Field Encryption in CakePHP
July 29, 2009 – 1:37 pmI’ve written the following behavior for a project I recently completed in Cake, and I thought it would be worth sharing:
class CryptableBehavior extends ModelBehavior { var $settings = array(); function setup(&$model, $settings) { if (!isset($this->settings[$model->alias])) { $this->settings[$model->alias] = array( 'fields' => array() ); } $this->settings[$model->alias] = array_merge($this->settings[$model->alias], $settings); } function beforeFind(&$model, $queryData) { foreach ($this->settings[$model->alias]['fields'] AS $field) { if (isset($queryData['conditions'][$model->alias.'.'.$field])) { $queryData['conditions'][$model->alias.'.'.$field] = $this->encrypt($queryData['conditions'][$model->alias.'.'.$field]); } } return $queryData; } function afterFind(&$model, $results, $primary) { foreach ($this->settings[$model->alias]['fields'] AS $field) { if ($primary) { foreach ($results AS $key => $value) { if (isset($value[$model->alias][$field])) { $results[$key][$model->alias][$field] = $this->decrypt($value[$model->alias][$field]); } } } else { if (isset($results[$field])) { $results[$field] = $this->decrypt($results[$field]); } } } return $results; } function beforeSave(&$model) { foreach ($this->settings[$model->alias]['fields'] AS $field) { if (isset($model->data[$model->alias][$field])) { $model->data[$model->alias]['cleartext_'.$field] = $model->data[$model->alias][$field]; $model->data[$model->alias][$field] = $this->encrypt($model->data[$model->alias][$field]); } } return true; } public function encrypt($data) { if ($data !== '') { return base64_encode(mcrypt_encrypt(Configure::read('Cryptable.cipher'), Configure::read('Cryptable.key'), $data, 'cbc', Configure::read('Cryptable.iv'))); } else { return ''; } } public function decrypt($data, $data2 = null) { if (is_object($data)) { unset($data); $data = $data2; } if ($data != '') { return trim(mcrypt_decrypt(Configure::read('Cryptable.cipher'), Configure::read('Cryptable.key'), base64_decode($data), 'cbc', Configure::read('Cryptable.iv'))); } else { return ''; } } }
All you need to do is add three lines to your bootstrap, and then load the behavior in any model you want to use it.
Here are the lines for your bootstrap:
Configure::write('Cryptable.cipher', 'rijndael-192'); Configure::write('Cryptable.key','random key string here'); Configure::write('Cryptable.iv', base64_decode('base64 encoded IV here')); // Create with mcrypt_create_iv with the appropriate size for your cipher
Here’s an example of how to load it in your model:
var $actsAs = array( 'Cryptable' => array( 'fields' => array( 'password' ) ) );
If you need to encrypt or decrypt a field outside of the normal find methods, you can simply call those methods on the model, passing in the string that needs worked on.
Download Cyptable Behavior
9 Responses to “Automatic DB Field Encryption in CakePHP”
I would suppose you could just use config/core.php salt for this too?
By
cdburgess on Jul 29, 2009
For the encryption key itself, yes. But you still need to set the IV and the encryption scheme to use.
By
Utoxin on Jul 29, 2009
What about the Security::cipher method? Wouldn’t be easier to use that instead?
By
Éber Freitas Dias on Jul 29, 2009
It would (arguably) be easier, but it’s not as flexible.
This allows you to choose the exact cipher system you want to use, including the IV and the passphrase, and does it all automatically on find and save calls, so you rarely ever have to call the encrypt and decrypt methods manually. It also avoids the extra layer of objects that you would add by using the Security class. Not a major savings, but it adds up.
By
Utoxin on Jul 30, 2009
Also, I just went and looked at the source code for Security::cipher. I’m not confident that it is cryptographically secure. It’s probably secure against a casual attack, but it doesn’t look very robust.
By
Utoxin on Jul 30, 2009
Great behaviour, a part from being useful, it’s very nice to see people that know how to use cake!
By
Julien on Nov 24, 2009
Could you elaborate a bit more on creating the IV please? I bet it’s dead obvious, but i’m not sure how to create that.
Thanks
Will
By
Will on Dec 1, 2009
This is the basic idea for creating the IV.
By
Utoxin on Dec 2, 2009