Created
April 21, 2012 01:38
-
-
Save kaz29/2433176 to your computer and use it in GitHub Desktop.
EncryptBehavior for CakePHP2.x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Encrypt behavior | |
* | |
*/ | |
class EncryptBehavior extends ModelBehavior { | |
// Encryption settings | |
const CIPHER = MCRYPT_RIJNDAEL_128; | |
const MODE = MCRYPT_MODE_CBC; | |
const KEY_SIZE = 32; | |
const IV_SIZE = 16; | |
const IV_SOURCE = MCRYPT_DEV_URANDOM; | |
private $key = null; | |
public function setup(Model $Model, $config = array()) | |
{ | |
if(!extension_loaded('mcrypt')){ | |
throw new RuntimeException('EncryptBehavior requires the mcrypt extension'); | |
} elseif(!isset($config['key'])){ | |
throw new RuntimeException('Bad configuration'); | |
} elseif(($length = mb_strlen($config['key'], '8bit')) !== self::KEY_SIZE){ | |
throw new RuntimeException('Encryption key length must to be ' . self::KEY_SIZE . ' byte, but got ' . $length); | |
} else { | |
$_settings = array( | |
'key' => null, | |
'fields' => array(), | |
); | |
$this->settings[$Model->name] = array_merge($_settings, $config); | |
} | |
} | |
public function encrypt(Model $Model, $token) | |
{ | |
$data = serialize($token); | |
$iv = mcrypt_create_iv(self::IV_SIZE, self::IV_SOURCE); | |
$cipherText = mcrypt_encrypt(self::CIPHER, $this->settings[$Model->name]['key'], $data, self::MODE, $iv); | |
return base64_encode($iv . $cipherText); | |
} | |
public function decrypt(Model $Model, $cipherText) | |
{ | |
$cipherText = base64_decode($cipherText); | |
$iv = substr($cipherText, 0, self::IV_SIZE); | |
$cipherText = substr($cipherText, self::IV_SIZE); | |
$data = mcrypt_decrypt(self::CIPHER, $this->settings[$Model->name]['key'], $cipherText, self::MODE, $iv); | |
return unserialize($data); | |
} | |
public function beforeSave(Model $Model) | |
{ | |
foreach ($this->settings[$Model->name]['fields'] as $field) { | |
if (!array_key_exists($field, $Model->data[$Model->name])) | |
continue ; | |
$Model->data[$Model->name][$field] = $this->encrypt($Model, $Model->data[$Model->name][$field]); | |
} | |
return true; | |
} | |
public function afterFind(Model $Model, $results, $primary) | |
{ | |
if ($primary === false) { | |
foreach($results as $key => &$value) { | |
foreach ($this->settings[$Model->name]['fields'] as $field) { | |
if ($key === $field) { | |
$value = $this->decrypt($Model, $value); | |
} | |
} | |
} | |
} else { | |
foreach($results as &$data) { | |
foreach ($this->settings[$Model->name]['fields'] as $field) { | |
if (isset($data[$Model->name][$field])) { | |
$data[$Model->name][$field] = $this->decrypt($Model, $data[$Model->name][$field]); | |
} | |
} | |
} | |
} | |
return $results; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$encryption_params=null; | |
class Encryption extends CakeTestModel | |
{ | |
var $name = 'Encryption'; | |
public function __construct($id = false, $table = null, $ds = null) { | |
global $encryption_params; | |
if (is_null($encryption_params)) { | |
$this->actsAs = array( | |
'Encrypt' | |
); | |
} else { | |
$this->actsAs = array( | |
'Encrypt' => $encryption_params, | |
); | |
} | |
parent::__construct($id, $table, $ds); | |
} | |
} | |
class EncriptBehaviorTestCase extends CakeTestCase | |
{ | |
public $fixtures = array( | |
'app.encryption', | |
); | |
/** | |
* setUp method | |
* | |
* @return void | |
*/ | |
public function setUp() { | |
parent::setUp(); | |
} | |
/** | |
* tearDown method | |
* | |
* @return void | |
*/ | |
public function tearDown() { | |
parent::tearDown(); | |
unset($this->Encryption); | |
} | |
/** | |
* @test | |
*/ | |
function BadConfiguration() | |
{ | |
try { | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
} catch (RuntimeException $e) { | |
return ; | |
} | |
$this->fail('BadConfiguration'); | |
} | |
/** | |
* @test | |
*/ | |
function EncryptionKeyLengthError1() | |
{ | |
try { | |
global $encryption_params; | |
$encryption_params = array('key'=>''); | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
} catch (RuntimeException $e) { | |
return ; | |
} | |
$this->fail('Encryption key length Error1'); | |
} | |
/** | |
* @test | |
*/ | |
function EncryptionKeyLengthError2() | |
{ | |
try { | |
global $encryption_params; | |
$encryption_params = array('key' => "1234567890123456789012345678901"); | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
} catch (RuntimeException $e) { | |
return ; | |
} | |
$this->fail('Encryption key length Error2'); | |
} | |
/** | |
* @test | |
*/ | |
function EncryptionKeyLengthError3() | |
{ | |
try { | |
global $encryption_params; | |
$encryption_params = array('key' => "123456789012345678901234567890123"); | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
} catch (RuntimeException $e) { | |
return ; | |
} | |
$this->fail('Encryption key length Error3'); | |
} | |
/** | |
* @test | |
*/ | |
function SimpleEncryption() | |
{ | |
global $encryption_params; | |
$encryption_params = array('key' => "12345678901234567890123456789012"); | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
$plaintext = 'TESTTEST'; | |
$encrypted = $this->Encryption->encrypt($plaintext); | |
$this->assertFalse(empty($encrypted)); | |
$decrypted = $this->Encryption->decrypt($encrypted); | |
$this->assertFalse(empty($decrypted)); | |
$this->assertNotEqual($plaintext, $encrypted); | |
$this->assertEqual($plaintext, $decrypted); | |
} | |
/** | |
* @test | |
*/ | |
function AutoEncryption() | |
{ | |
global $encryption_params; | |
$encryption_params = array( | |
'key' => "12345678901234567890123456789012", | |
'fields' => array('encrypt'), | |
); | |
$this->Encryption = ClassRegistry::init('Encryption'); | |
$plaintext1 = 'TESTTESTTEST'; | |
$plaintext2 = 'FOOBAR'; | |
$data = array( | |
'encrypt' => $plaintext1, | |
); | |
$this->Encryption->create(); | |
$this->Encryption->set($data); | |
$actual = $this->Encryption->save(); | |
$this->assertNotEqual($actual['Encryption']['encrypt'], $plaintext1); | |
$data = array( | |
'encrypt' => $plaintext2, | |
); | |
$this->Encryption->create(); | |
$this->Encryption->set($data); | |
$actual = $this->Encryption->save(); | |
$this->assertNotEqual($actual['Encryption']['encrypt'], $plaintext2); | |
$actual = $this->Encryption->find('all', array('order'=>array('id'))); | |
$expected = array( | |
'Encryption' => array( | |
'id' => 1, | |
'encrypt' => $plaintext1, | |
) | |
); | |
$this->assertEqual($actual[0], $expected); | |
$expected = array( | |
'Encryption' => array( | |
'id' => 2, | |
'encrypt' => $plaintext2, | |
) | |
); | |
$this->assertEqual($actual[1], $expected); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class EncryptionFixture extends CakeTestFixture { | |
var $name = 'Encryption'; | |
var $fields = array( | |
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'length' => 20, 'key' => 'primary'), | |
'encrypt' => array('type' => 'text', 'null' => true, 'default' => NULL), | |
); | |
var $records = array(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment