/src/PortePlugins/Crypt.php
PHP | 176 lines | 125 code | 11 blank | 40 comment | 19 complexity | 66d560fef22d1bea08b29062ac948d2e MD5 | raw file
- <?php
- /**
- * Copyright (c) 2008, SARL Adaltas. All rights reserved.
- * Code licensed under the BSD License:
- * http://www.php-pop.org/porte/license.html
- */
- /**
- * Plugin to store crypted content into the database.
- *
- * @author David Worms info(at)adaltas.com
- * @copyright 2008-2009 Adaltas
- */
- class PortePlugins_Crypt{
-
- public static $methods = array('AES'=>array('ECB'));
-
- /**
- * Register the plugin with a Porte instance.
- */
- public static function register(Porte $porte){
- PorteEvents::connect('model_property_before',array('PortePlugins_Crypt','_modelPropertyBefore'));
- }
-
- public static function _modelPropertyBefore($models,$type,$property){
- $model = $models->{$type};
- $propertyModel = $model['properties'][$property];
- if(!empty($propertyModel['crypt'])){
- switch(gettype($propertyModel['crypt'])){
- case 'boolean';
- case 'integer';
- $propertyModel['crypt'] = array(
- 'method' => 'AES');
- break;
- case 'string';
- $propertyModel['crypt'] = array(
- 'method' => 'AES',
- 'key'=>$propertyModel['crypt']);
- break;
- case 'array':
- // ok
- break;
- default:
- throw new PorteException('Invalid AES configuration "'.$type.'.'.$property.'": "'.PurLang::toString($propertyModel).'"');
- }
- if(!empty($models->config->crypt)){
- $propertyModel['crypt'] = array_merge($models->config->crypt,$propertyModel['crypt']);
- }else if(!empty($model['crypt'])){
- $propertyModel['crypt'] = array_merge($model['crypt'],$propertyModel['crypt']);
- }
- if(empty($propertyModel['crypt']['hex'])){
- $propertyModel['crypt']['hex'] = false;
- }
- if(array_key_exists('method',$propertyModel['crypt'])&&empty($propertyModel['crypt']['method'])){
- // it's ok, if method is defined but null or empty,
- // we only convert the value to hexadecimal
- $propertyModel['crypt']['method'] = null;
- }else if(empty($propertyModel['crypt']['method'])){
- $propertyModel['crypt']['method'] = 'AES';
- }else{
- $propertyModel['crypt']['method'] = strtoupper($propertyModel['crypt']['method']);
- if(!in_array($propertyModel['crypt']['method'],array_keys(self::$methods))){
- throw new PorteException('Incryption method not supported in "'.$type.'.'.$property.'": "'.$propertyModel['crypt']['method'].'"');
- }
- }
- if($propertyModel['crypt']['method']){
- if(empty($propertyModel['crypt']['mode'])){
- $propertyModel['crypt']['mode'] = self::$methods[$propertyModel['crypt']['method']][0];
- }else{
- $propertyModel['crypt']['mode'] = strtoupper($propertyModel['crypt']['mode']);
- }
- if(empty($propertyModel['crypt']['key'])){
- throw new PorteException('No available encryption key in "'.$type.'.'.$property.'"');
- }
- }
- $propertyModel['type'] = 'string';
- $propertyModel['class'] = 'PortePlugins_CryptType';
- $models->{$type}['properties'][$property] = $propertyModel;
- }
- }
-
- /**
- * Encryp the value with the AES 128 algorythm and convert it
- * into an hexadecimal representation.
- *
- * The result is Mysql compatible with the following statement:
- *
- * HEX(AES_ENCRYPT($value))
- *
- * Convert into an hexadecimal representation and crypt
- * AES 128 compatible mysql HEX(AES_ENCRYPT()) of a srting value
- *
- * @return string The string in hexadecimal
- * @param string $value The string to crypt
- * @param string $key The key for crypt
- */
- public static function encrypt($value, array $options) {
- if(empty($value)){
- return null;
- }
- if(!empty($options['method'])){
- switch($options['method']){
- case 'AES':
- if(empty($options['key'])){
- throw new InvalidArgumentException('No decrypt key provided');
- }
- $mode = constant('MCRYPT_MODE_'.$options['mode']);
- $value = mcrypt_encrypt(
- MCRYPT_RIJNDAEL_128,
- $options['key'],
- str_pad(
- $value,
- (16*(floor(strlen($value) / 16)+1)),
- chr(16-(strlen($value) % 16))),
- $mode,
- mcrypt_create_iv(
- mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, $mode),
- MCRYPT_DEV_URANDOM));
- break;
- default:
- throw new PorteException('Unsupported encryption method: "'.$options['method'].'"');
- }
-
- }
- if(!empty($options['hex'])){
- $value = bin2hex($value);
- }
-
- return $value;
- }
-
- /**
- * Decrypt an AES 128 encoding value
- * stored as an hexadecimal representation into a string.
- *
- * @return string The converted string
- * @param string $hexValue The string to crypt
- * @param string $key The key for crypt
- */
- public static function decrypt($value, array $options) {
- if(empty($value)){
- return null;
- }
- if(!empty($options['hex'])){
- $value = pack('H*', $value);
- }
- if(!empty($options['method'])){
- switch($options['method']){
- case 'AES':
- $mode = constant('MCRYPT_MODE_'.$options['mode']);
- if(empty($options['key'])){
- throw new InvalidArgumentException('No decrypt key provided');
- }
- $mode = constant('MCRYPT_MODE_'.$options['mode']);
- $value = mcrypt_decrypt(
- MCRYPT_RIJNDAEL_128,
- $options['key'],
- $value,
- $mode,
- mcrypt_create_iv(
- mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, $mode),
- MCRYPT_DEV_URANDOM ) );
- $value = rtrim(
- $value,
- ((ord(substr($value, strlen($value)-1, 1 )) >= 0 && ord(substr($value, strlen($value)-1, 1 ) ) <= 16 ) ? chr(ord(substr($value, strlen($value)-1, 1 ))): null) );
- break;
- default:
- throw new PorteException('Unsupported encryption method: "'.$options['method'].'"');
- }
-
- }
- return $value;
- }
-
- }