From 5c9eab15cc070be2eef20c41340f290b79530904 Mon Sep 17 00:00:00 2001 From: Alexandr Burov Date: Fri, 21 Apr 2017 14:59:35 +0300 Subject: [PATCH 01/12] Switched mcrypt to openssl, because mcrypt has been deprecated as of PHP 7.1.0 --- .gitignore | 5 +- Command/DoctrineDecryptDatabaseCommand.php | 53 ++++++------- Command/DoctrineEncryptDatabaseCommand.php | 2 +- .../DoctrineEncryptExtension.php | 34 ++++---- Encryptors/AES192Encryptor.php | 79 +++++++++++++++++++ Encryptors/AES256Encryptor.php | 67 ++++++++++------ Encryptors/Rijndael128Encryptor.php | 72 ----------------- Encryptors/Rijndael256Encryptor.php | 72 ----------------- Encryptors/VariableEncryptor.php | 49 ++++++------ .../Library/Encryptor/AES128Encryptor.php | 77 ++++++++++++++++++ .../Encryptor/Rijndael192Encryptor.php | 70 ---------------- .../YourBundle/Resources/config/config.yml | 4 +- Resources/doc/commands.md | 12 +-- Resources/doc/configuration.md | 14 ++-- Resources/doc/custom_encryptor.md | 54 +++++++------ Resources/doc/example_of_usage.md | 2 +- Resources/doc/installation.md | 2 +- Tests/AES192EncryptorTest.php | 56 +++++++++++++ Tests/AES256EncryptorTest.php | 56 +++++++++++++ Tests/VariableEncryptorTest.php | 41 ++++++++++ composer.json | 4 +- phpunit.xml.dist | 8 ++ 22 files changed, 484 insertions(+), 349 deletions(-) create mode 100644 Encryptors/AES192Encryptor.php delete mode 100644 Encryptors/Rijndael128Encryptor.php delete mode 100644 Encryptors/Rijndael256Encryptor.php create mode 100644 Example/YourBundle/Library/Encryptor/AES128Encryptor.php delete mode 100644 Example/YourBundle/Library/Encryptor/Rijndael192Encryptor.php create mode 100644 Tests/AES192EncryptorTest.php create mode 100644 Tests/AES256EncryptorTest.php create mode 100644 Tests/VariableEncryptorTest.php create mode 100644 phpunit.xml.dist diff --git a/.gitignore b/.gitignore index ba9ecfc3..744e1e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -composer.json -.idea/ \ No newline at end of file +composer.lock +.idea/ +.php_cs.cache \ No newline at end of file diff --git a/Command/DoctrineDecryptDatabaseCommand.php b/Command/DoctrineDecryptDatabaseCommand.php index 1633359a..31fdcaa6 100644 --- a/Command/DoctrineDecryptDatabaseCommand.php +++ b/Command/DoctrineDecryptDatabaseCommand.php @@ -3,8 +3,6 @@ namespace Ambta\DoctrineEncryptBundle\Command; use Ambta\DoctrineEncryptBundle\DependencyInjection\DoctrineEncryptExtension; -use Doctrine\Common\Annotations\AnnotationReader; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -12,14 +10,13 @@ use Symfony\Component\Console\Question\ConfirmationQuestion; /** - * Decrypt whole database on tables which are encrypted + * Decrypt whole database on tables which are encrypted. * * @author Marcel van Nuil * @author Michael Feinbier */ class DoctrineDecryptDatabaseCommand extends AbstractCommand { - /** * {@inheritdoc} */ @@ -28,7 +25,7 @@ protected function configure() $this ->setName('doctrine:decrypt:database') ->setDescription('Decrypt whole database on tables which are encrypted') - ->addArgument("encryptor", InputArgument::OPTIONAL, 'The encryptor you want to decrypt the database with') + ->addArgument('encryptor', InputArgument::OPTIONAL, 'The encryptor you want to decrypt the database with') ->addArgument('batchSize', InputArgument::OPTIONAL, 'The update/flush batch size', 20); } @@ -45,17 +42,17 @@ protected function execute(InputInterface $input, OutputInterface $output) $batchSize = $input->getArgument('batchSize'); //If encryptor has been set use that encryptor else use default - if($input->getArgument('encryptor')) { - if(isset($supportedExtensions[$input->getArgument('encryptor')])) { + if ($input->getArgument('encryptor')) { + if (isset($supportedExtensions[$input->getArgument('encryptor')])) { $this->subscriber->setEncryptor($supportedExtensions[$input->getArgument('encryptor')]); } else { - if(class_exists($input->getArgument('encryptor'))) - { + if (class_exists($input->getArgument('encryptor'))) { $this->subscriber->setEncryptor($input->getArgument('encryptor')); } else { $output->writeln('\nGiven encryptor does not exists'); - $output->writeln('Supported encryptors: ' . implode(', ', array_keys($supportedExtensions))); - $output->writeln('You can also define your own class. (example: Ambta\DoctrineEncryptBundle\Encryptors\Rijndael128Encryptor)'); + $output->writeln('Supported encryptors: '.implode(', ', array_keys($supportedExtensions))); + $output->writeln('You can also define your own class. (example: \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor)'); + return; } } @@ -66,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output) //Set counter and loop through entity manager meta data $propertyCount = 0; - foreach($metaDataArray as $metaData) { + foreach ($metaDataArray as $metaData) { if ($metaData->isMappedSuperclass) { continue; } @@ -76,11 +73,11 @@ protected function execute(InputInterface $input, OutputInterface $output) } $confirmationQuestion = new ConfirmationQuestion( - "\n" . count($metaDataArray) . " entities found which are containing " . $propertyCount . " properties with the encryption tag. \n\n" . - "Which are going to be decrypted with [" . $this->subscriber->getEncryptor() . "]. \n\n" . - "Wrong settings can mess up your data and it will be unrecoverable. \n" . - "I advise you to make a backup. \n\n" . - "Continue with this action? (y/yes)", false + "\n".count($metaDataArray).' entities found which are containing '.$propertyCount." properties with the encryption tag. \n\n". + 'Which are going to be decrypted with ['.$this->subscriber->getEncryptor()."]. \n\n". + "Wrong settings can mess up your data and it will be unrecoverable. \n". + "I advise you to make a backup. \n\n". + 'Continue with this action? (y/yes)', false ); if (!$question->ask($input, $output, $confirmationQuestion)) { @@ -93,40 +90,39 @@ protected function execute(InputInterface $input, OutputInterface $output) $valueCounter = 0; //Loop through entity manager meta data - foreach($this->getEncryptionableEntityMetaData() as $metaData) { + foreach ($this->getEncryptionableEntityMetaData() as $metaData) { $i = 0; $iterator = $this->getEntityIterator($metaData->name); $totalCount = $this->getTableCount($metaData->name); $output->writeln(sprintf('Processing %s', $metaData->name)); $progressBar = new ProgressBar($output, $totalCount); - foreach($iterator as $row) { + foreach ($iterator as $row) { $entity = $row[0]; //Create reflectionClass for each entity - $entityReflectionClass = New \ReflectionClass($entity); + $entityReflectionClass = new \ReflectionClass($entity); //Get the current encryptor used $encryptorUsed = $this->subscriber->getEncryptor(); //Loop through the property's in the entity - foreach($this->getEncryptionableProperties($metaData) as $property) { + foreach ($this->getEncryptionableProperties($metaData) as $property) { //Get and check getters and setters $methodeName = ucfirst($property->getName()); - $getter = "get" . $methodeName; - $setter = "set" . $methodeName; + $getter = 'get'.$methodeName; + $setter = 'set'.$methodeName; //Check if getter and setter are set - if($entityReflectionClass->hasMethod($getter) && $entityReflectionClass->hasMethod($setter)) { - + if ($entityReflectionClass->hasMethod($getter) && $entityReflectionClass->hasMethod($setter)) { //Get decrypted data $unencrypted = $entity->$getter(); //Set raw data $entity->$setter($unencrypted); - $valueCounter++; + ++$valueCounter; } } @@ -139,13 +135,12 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->entityManager->clear(); } $progressBar->advance(1); - $i++; + ++$i; //Set the encryptor again $this->subscriber->setEncryptor($encryptorUsed); } - $progressBar->finish(); $output->writeln(''); //Get the current encryptor used @@ -158,6 +153,6 @@ protected function execute(InputInterface $input, OutputInterface $output) } //Say it is finished - $output->writeln("\nDecryption finished values found: " . $valueCounter . ", decrypted: " . $this->subscriber->decryptCounter . ".\nAll values are now decrypted."); + $output->writeln("\nDecryption finished values found: ".$valueCounter.', decrypted: '.$this->subscriber->decryptCounter.".\nAll values are now decrypted."); } } diff --git a/Command/DoctrineEncryptDatabaseCommand.php b/Command/DoctrineEncryptDatabaseCommand.php index f40cd30b..17640617 100644 --- a/Command/DoctrineEncryptDatabaseCommand.php +++ b/Command/DoctrineEncryptDatabaseCommand.php @@ -54,7 +54,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $output->writeln('\nGiven encryptor does not exists'); $output->writeln('Supported encryptors: ' . implode(', ', array_keys($supportedExtensions))); - $output->writeln('You can also define your own class. (example: Ambta\DoctrineEncryptBundle\Encryptors\Rijndael128Encryptor)'); + $output->writeln('You can also define your own class. (example: \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor)'); return; } } diff --git a/DependencyInjection/DoctrineEncryptExtension.php b/DependencyInjection/DoctrineEncryptExtension.php index 884a467a..1df0f980 100644 --- a/DependencyInjection/DoctrineEncryptExtension.php +++ b/DependencyInjection/DoctrineEncryptExtension.php @@ -2,6 +2,8 @@ namespace Ambta\DoctrineEncryptBundle\DependencyInjection; +use Ambta\DoctrineEncryptBundle\Encryptors\AES192Encryptor; +use Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -14,22 +16,24 @@ * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} */ -class DoctrineEncryptExtension extends Extension { - - public static $supportedEncryptorClasses = array('rijndael256' => 'Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor', - 'rijndael128'=> 'Ambta\DoctrineEncryptBundle\Encryptors\Rijndael128Encryptor'); +class DoctrineEncryptExtension extends Extension +{ + public static $supportedEncryptorClasses = [ + AES256Encryptor::METHOD_NAME => AES256Encryptor::class, + AES192Encryptor::METHOD_NAME => AES192Encryptor::class, + ]; /** - * {@inheritDoc} + * {@inheritdoc} */ - public function load(array $configs, ContainerBuilder $container) { - + public function load(array $configs, ContainerBuilder $container) + { //Create configuration object $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); //Set orm-service in array of services - $services = array('orm' => 'orm-services'); + $services = ['orm' => 'orm-services']; //set supported encryptor classes $supportedEncryptorClasses = self::$supportedEncryptorClasses; @@ -44,11 +48,11 @@ public function load(array $configs, ContainerBuilder $container) { } //If empty encryptor class, use Rijndael 256 encryptor - if(empty($config['encryptor_class'])) { - if(isset($config['encryptor']) and isset($supportedEncryptorClasses[$config['encryptor']])) { + if (empty($config['encryptor_class'])) { + if (isset($config['encryptor']) and isset($supportedEncryptorClasses[$config['encryptor']])) { $config['encryptor_class'] = $supportedEncryptorClasses[$config['encryptor']]; } else { - $config['encryptor_class'] = $supportedEncryptorClasses['rijndael256']; + $config['encryptor_class'] = $supportedEncryptorClasses[AES256Encryptor::METHOD_NAME]; } } @@ -57,17 +61,17 @@ public function load(array $configs, ContainerBuilder $container) { $container->setParameter('ambta_doctrine_encrypt.secret_key', $config['secret_key']); //Load service file - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load(sprintf('%s.yml', $services['orm'])); - } /** - * Get alias for configuration + * Get alias for configuration. * * @return string */ - public function getAlias() { + public function getAlias() + { return 'ambta_doctrine_encrypt'; } } diff --git a/Encryptors/AES192Encryptor.php b/Encryptors/AES192Encryptor.php new file mode 100644 index 00000000..36e56d39 --- /dev/null +++ b/Encryptors/AES192Encryptor.php @@ -0,0 +1,79 @@ + + */ +class AES192Encryptor implements EncryptorInterface +{ + const METHOD_NAME = 'AES-192'; + const ENCRYPT_MODE = 'ECB'; + + /** + * @var string + */ + private $secretKey; + + /** + * @var string + */ + private $encryptMethod; + + /** + * @var string + */ + private $initializationVector; + + /** + * {@inheritdoc} + */ + public function __construct($key) + { + $this->secretKey = md5($key); + $this->encryptMethod = sprintf('%s-%s', self::METHOD_NAME, self::ENCRYPT_MODE); + $this->initializationVector = openssl_random_pseudo_bytes( + openssl_cipher_iv_length($this->encryptMethod) + ); + } + + /** + * {@inheritdoc} + */ + public function encrypt($data) + { + if (is_string($data)) { + return trim(base64_encode(openssl_encrypt( + $data, + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + ))).''; + } + + return $data; + } + + /** + * {@inheritdoc} + */ + public function decrypt($data) + { + if (is_string($data)) { + $data = str_replace('', '', $data); + + return trim(openssl_decrypt( + base64_decode($data), + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + )); + } + + return $data; + } +} diff --git a/Encryptors/AES256Encryptor.php b/Encryptors/AES256Encryptor.php index 33cff910..c94215e6 100644 --- a/Encryptors/AES256Encryptor.php +++ b/Encryptors/AES256Encryptor.php @@ -3,17 +3,25 @@ namespace Ambta\DoctrineEncryptBundle\Encryptors; /** - * Class for AES256 encryption - * + * Class for AES256 encryption. + * * @author Victor Melnik */ -class AES256Encryptor implements EncryptorInterface { +class AES256Encryptor implements EncryptorInterface +{ + const METHOD_NAME = 'AES-256'; + const ENCRYPT_MODE = 'ECB'; /** * @var string */ private $secretKey; + /** + * @var string + */ + private $encryptMethod; + /** * @var string */ @@ -22,37 +30,50 @@ class AES256Encryptor implements EncryptorInterface { /** * {@inheritdoc} */ - public function __construct($key) { + public function __construct($key) + { $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), - MCRYPT_RAND + $this->encryptMethod = sprintf('%s-%s', self::METHOD_NAME, self::ENCRYPT_MODE); + $this->initializationVector = openssl_random_pseudo_bytes( + openssl_cipher_iv_length($this->encryptMethod) ); } /** * {@inheritdoc} */ - public function encrypt($data) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, - $data, - MCRYPT_MODE_ECB, - $this->initializationVector - ))); + public function encrypt($data) + { + if (is_string($data)) { + return trim(base64_encode(openssl_encrypt( + $data, + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + ))).''; + } + + return $data; } /** * {@inheritdoc} */ - public function decrypt($data) { - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, - base64_decode($data), - MCRYPT_MODE_ECB, - $this->initializationVector - )); + public function decrypt($data) + { + if (is_string($data)) { + $data = str_replace('', '', $data); + + return trim(openssl_decrypt( + base64_decode($data), + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + )); + } + + return $data; } } diff --git a/Encryptors/Rijndael128Encryptor.php b/Encryptors/Rijndael128Encryptor.php deleted file mode 100644 index 5003f098..00000000 --- a/Encryptors/Rijndael128Encryptor.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ -class Rijndael128Encryptor implements EncryptorInterface { - - /** - * @var string - */ - private $secretKey; - - /** - * @var string - */ - private $initializationVector; - - /** - * {@inheritdoc} - */ - public function __construct($key) { - $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), - MCRYPT_RAND - ); - } - - /** - * {@inheritdoc} - */ - public function encrypt($data) { - - if(is_string($data)) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_128, - $this->secretKey, - $data, - MCRYPT_MODE_ECB, - $this->initializationVector - ))). ""; - } - - return $data; - - } - - /** - * {@inheritdoc} - */ - public function decrypt($data) { - - if(is_string($data)) { - - $data = str_replace("", "", $data); - - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_128, - $this->secretKey, - base64_decode($data), - MCRYPT_MODE_ECB, - $this->initializationVector - )); - } - - return $data; - } -} diff --git a/Encryptors/Rijndael256Encryptor.php b/Encryptors/Rijndael256Encryptor.php deleted file mode 100644 index 20d1011c..00000000 --- a/Encryptors/Rijndael256Encryptor.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ -class Rijndael256Encryptor implements EncryptorInterface { - - /** - * @var string - */ - private $secretKey; - - /** - * @var string - */ - private $initializationVector; - - /** - * {@inheritdoc} - */ - public function __construct($key) { - $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), - MCRYPT_RAND - ); - } - - /** - * {@inheritdoc} - */ - public function encrypt($data) { - - if(is_string($data)) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, - $data, - MCRYPT_MODE_ECB, - $this->initializationVector - ))). ""; - } - - return $data; - - } - - /** - * {@inheritdoc} - */ - public function decrypt($data) { - - if(is_string($data)) { - - $data = str_replace("", "", $data); - - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, - base64_decode($data), - MCRYPT_MODE_ECB, - $this->initializationVector - )); - } - - return $data; - } -} diff --git a/Encryptors/VariableEncryptor.php b/Encryptors/VariableEncryptor.php index 7267d1f8..f34fc4e0 100644 --- a/Encryptors/VariableEncryptor.php +++ b/Encryptors/VariableEncryptor.php @@ -3,11 +3,13 @@ namespace Ambta\DoctrineEncryptBundle\Encryptors; /** - * Class for variable encryption - * + * Class for variable encryption. + * * @author Victor Melnik */ -class VariableEncryptor implements EncryptorInterface { +class VariableEncryptor implements EncryptorInterface +{ + const ENCRYPT_METHOD = 'AES-256-ECB'; /** * @var string @@ -22,27 +24,27 @@ class VariableEncryptor implements EncryptorInterface { /** * {@inheritdoc} */ - public function __construct($key) { + public function __construct($key) + { $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), - MCRYPT_RAND + $this->initializationVector = openssl_random_pseudo_bytes( + openssl_cipher_iv_length(self::ENCRYPT_METHOD) ); } /** * {@inheritdoc} */ - public function encrypt($data) { - - if(is_string($data)) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, + public function encrypt($data) + { + if (is_string($data)) { + return trim(base64_encode(openssl_encrypt( $data, - MCRYPT_MODE_ECB, + self::ENCRYPT_METHOD, + $this->secretKey, + 0, $this->initializationVector - ))) . ""; + ))).''; } /* @@ -51,25 +53,26 @@ public function encrypt($data) { * * Not used, needs improvement or other solution */ - if(is_integer($data)) { + if (is_integer($data)) { //Not sure } return $data; - } /** * {@inheritdoc} */ - public function decrypt($data) { + public function decrypt($data) + { + if (is_string($data)) { + $data = str_replace('', '', $data); - if(is_string($data)) { - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_256, - $this->secretKey, + return trim(openssl_decrypt( base64_decode($data), - MCRYPT_MODE_ECB, + self::ENCRYPT_METHOD, + $this->secretKey, + 0, $this->initializationVector )); } diff --git a/Example/YourBundle/Library/Encryptor/AES128Encryptor.php b/Example/YourBundle/Library/Encryptor/AES128Encryptor.php new file mode 100644 index 00000000..f1d3b0cc --- /dev/null +++ b/Example/YourBundle/Library/Encryptor/AES128Encryptor.php @@ -0,0 +1,77 @@ +secretKey = md5($key); + $this->encryptMethod = sprintf('%s-%s', self::ENCRYPT_NAME, self::ENCRYPT_MODE); + $this->initializationVector = openssl_random_pseudo_bytes( + openssl_cipher_iv_length($this->encryptMethod) + ); + } + + /** + * {@inheritdoc} + */ + public function encrypt($data) + { + if (is_string($data)) { + return trim(base64_encode(openssl_encrypt( + $data, + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + ))).''; + } + + return $data; + } + + /** + * {@inheritdoc} + */ + public function decrypt($data) + { + if (is_string($data)) { + $data = str_replace('', '', $data); + + return trim(openssl_decrypt( + base64_decode($data), + $this->encryptMethod, + $this->secretKey, + 0, + $this->initializationVector + )); + } + + return $data; + } +} diff --git a/Example/YourBundle/Library/Encryptor/Rijndael192Encryptor.php b/Example/YourBundle/Library/Encryptor/Rijndael192Encryptor.php deleted file mode 100644 index a330ed50..00000000 --- a/Example/YourBundle/Library/Encryptor/Rijndael192Encryptor.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -class MyRijndael192Encryptor implements EncryptorInterface { - - /** - * @var string - */ - private $secretKey; - - /** - * @var string - */ - private $initializationVector; - - /** - * {@inheritdoc} - */ - public function __construct($key) { - $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_192, MCRYPT_MODE_ECB), - MCRYPT_RAND - ); - } - - /** - * {@inheritdoc} - */ - public function encrypt($data) { - - if(is_string($data)) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_192, - $this->secretKey, - $data, - MCRYPT_MODE_ECB, - $this->initializationVector - ))). ""; - } - - return $data; - - } - - /** - * {@inheritdoc} - */ - public function decrypt($data) { - - if(is_string($data)) { - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_192, - $this->secretKey, - base64_decode($data), - MCRYPT_MODE_ECB, - $this->initializationVector - )); - } - - return $data; - } -} \ No newline at end of file diff --git a/Example/YourBundle/Resources/config/config.yml b/Example/YourBundle/Resources/config/config.yml index 9e5fd6f3..057f7631 100644 --- a/Example/YourBundle/Resources/config/config.yml +++ b/Example/YourBundle/Resources/config/config.yml @@ -1,4 +1,4 @@ ambta_doctrine_encrypt: secret_key: AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UW # Your own random 256 bit key (32 characters) - #encryptor: rijndael256 # rijndael256 or rijndael128 - encryptor_class: \Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor # your own encryption class \ No newline at end of file + #encryptor: AES-256 # AES-256 or AES-192 + encryptor_class: \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor # your own encryption class \ No newline at end of file diff --git a/Resources/doc/commands.md b/Resources/doc/commands.md index 6cf0ba52..d5f38745 100644 --- a/Resources/doc/commands.md +++ b/Resources/doc/commands.md @@ -25,7 +25,7 @@ DoctrineEncrypt\Entity\UserDetail has 13 properties which are encrypted. You can use the comment `doctrine:encrypt:database [encryptor]` to encrypt the current database. * Optional parameter [encryptor] - * An encryptor provided by the bundle (rijndael256 or rijndael128) or your own [encryption class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md). + * An encryptor provided by the bundle (AES-256 or AES-128) or your own [encryption class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md). * Default: Your encryptor set in the configuration file or the default encryption class when not set in the configuration file ``` @@ -35,11 +35,11 @@ $ php app/console doctrine:encrypt:database or you can provide an encryptor (optional). ``` -$ php app/console doctrine:encrypt:database rijndael256 +$ php app/console doctrine:encrypt:database AES-256 ``` ``` -$ php app/console doctrine:encrypt:database \Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor +$ php app/console doctrine:encrypt:database \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor ``` This command will return the amount of values encrypted in the database. @@ -54,7 +54,7 @@ Encryption finished values encrypted: 203 values. You can use the comment `doctrine:decrypt:database [encryptor]` to decrypt the current database. * Optional parameter [encryptor] - * An encryptor provided by the bundle (rijndael256 or rijndael128) or your own [encryption class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md). + * An encryptor provided by the bundle (AES-256 or AES-128) or your own [encryption class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md). * Default: Your encryptor set in the configuration file or the default encryption class when not set in the configuration file ``` @@ -64,11 +64,11 @@ $ php app/console doctrine:encrypt:database or you can provide an encryptor (optional). ``` -$ php app/console doctrine:encrypt:database rijndael256 +$ php app/console doctrine:decrypt:database AES-256 ``` ``` -$ php app/console doctrine:encrypt:database \Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor +$ php app/console doctrine:decrypt:database \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor ``` This command will return the amount of entities and the amount of values decrypted in the database. diff --git a/Resources/doc/configuration.md b/Resources/doc/configuration.md index 76296bef..db0c56cd 100644 --- a/Resources/doc/configuration.md +++ b/Resources/doc/configuration.md @@ -7,8 +7,8 @@ There are 3 paramaters in the configuration of the Doctrine encryption bundle wh * Default: empty, the bundle will use your Symfony2 secret key. * **encryptor** - The encryptor used to encrypt the data - * Encryptor name, currently available: rijndael128 and rijndael256 - * Default: rijndael256 + * Encryptor name, currently available: AES-192 and AES-256 + * Default: AES-256 * **encryptor_class** - Custom class for encrypting data * Encryptor class, [your own encryptor class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md) will override encryptor paramater @@ -19,8 +19,8 @@ There are 3 paramaters in the configuration of the Doctrine encryption bundle wh ``` yaml ambta_doctrine_encrypt: secret_key: AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UW # Your own random 256 bit key (32 characters) - encryptor: rijndael256 # rijndael256 or rijndael128 - encryptor_class: \Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor # your own encryption class + encryptor: AES-256 # AES-256 or AES-192 + encryptor_class: \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor # your own encryption class ``` ### xml @@ -29,10 +29,10 @@ ambta_doctrine_encrypt: AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UW - - rijndael256 + + AES-256 - \Ambta\DoctrineEncryptBundle\Encryptors\Rijndael256Encryptor + \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor ``` diff --git a/Resources/doc/custom_encryptor.md b/Resources/doc/custom_encryptor.md index 762865da..4ed4fed9 100644 --- a/Resources/doc/custom_encryptor.md +++ b/Resources/doc/custom_encryptor.md @@ -23,17 +23,23 @@ namespace YourBundle\Library\Encryptor; use Ambta\DoctrineEncryptBundle\Encryptors\EncryptorInterface; /** - * Class for variable encryption - * - * @author you + * Class for AES128 encryption. */ -class MyRijndael192Encryptor implements EncryptorInterface { +class MyAES128Encryptor implements EncryptorInterface +{ + const ENCRYPT_NAME = 'AES-128'; + const ENCRYPT_MODE = 'ECB'; /** * @var string */ private $secretKey; + /** + * @var string + */ + private $encryptMethod; + /** * @var string */ @@ -42,44 +48,46 @@ class MyRijndael192Encryptor implements EncryptorInterface { /** * {@inheritdoc} */ - public function __construct($key) { + public function __construct($key) + { $this->secretKey = md5($key); - $this->initializationVector = mcrypt_create_iv( - mcrypt_get_iv_size(MCRYPT_RIJNDAEL_192, MCRYPT_MODE_ECB), - MCRYPT_RAND + $this->encryptMethod = sprintf('%s-%s', self::ENCRYPT_NAME, self::ENCRYPT_MODE); + $this->initializationVector = openssl_random_pseudo_bytes( + openssl_cipher_iv_length($this->encryptMethod) ); } /** * {@inheritdoc} */ - public function encrypt($data) { - - if(is_string($data)) { - return trim(base64_encode(mcrypt_encrypt( - MCRYPT_RIJNDAEL_192, - $this->secretKey, + public function encrypt($data) + { + if (is_string($data)) { + return trim(base64_encode(openssl_encrypt( $data, - MCRYPT_MODE_ECB, + $this->encryptMethod, + $this->secretKey, + 0, $this->initializationVector - ))). ""; + ))).''; } return $data; - } /** * {@inheritdoc} */ - public function decrypt($data) { + public function decrypt($data) + { + if (is_string($data)) { + $data = str_replace('', '', $data); - if(is_string($data)) { - return trim(mcrypt_decrypt( - MCRYPT_RIJNDAEL_192, - $this->secretKey, + return trim(openssl_decrypt( base64_decode($data), - MCRYPT_MODE_ECB, + $this->encryptMethod, + $this->secretKey, + 0, $this->initializationVector )); } diff --git a/Resources/doc/example_of_usage.md b/Resources/doc/example_of_usage.md index 18028051..4d2fead7 100644 --- a/Resources/doc/example_of_usage.md +++ b/Resources/doc/example_of_usage.md @@ -149,4 +149,4 @@ So our information is encoded and all okay. ###Requirements -You need `DoctrineFixturesBundle` and `php-mcrypt` extension for this example +You need `DoctrineFixturesBundle` and `php-openssl` extension for this example diff --git a/Resources/doc/installation.md b/Resources/doc/installation.md index 41eb50ac..6cd053b6 100644 --- a/Resources/doc/installation.md +++ b/Resources/doc/installation.md @@ -7,7 +7,7 @@ ### Requirements * php 5.4 -* php-mcrypt +* php-openssl * [doctrine/orm](https://packagist.org/packages/doctrine/orm) >= 2.5 * [symfony/framework-bundle](https://packagist.org/packages/symfony/framework-bundle) >= 2.0 diff --git a/Tests/AES192EncryptorTest.php b/Tests/AES192EncryptorTest.php new file mode 100644 index 00000000..d27fa958 --- /dev/null +++ b/Tests/AES192EncryptorTest.php @@ -0,0 +1,56 @@ +encrypt($data); + + self::assertEquals($data, $aes->decrypt($encryptData)); + } + + /** + * @test + * @dataProvider getContentData() + * + * @param mixed $data + */ + public function checkEncryptorWithoutString($data) + { + $aes = new AES192Encryptor(self::SECRET_KEY); + $encryptData = $aes->encrypt($data); + + self::assertEquals($encryptData, $data); + self::assertEquals($data, $aes->decrypt($encryptData)); + } + + /** + * @return array + */ + public function getContentData() + { + return [ + [1234], + [100.123], + [true], + [false], + [null], + ]; + } +} diff --git a/Tests/AES256EncryptorTest.php b/Tests/AES256EncryptorTest.php new file mode 100644 index 00000000..9b0b28d9 --- /dev/null +++ b/Tests/AES256EncryptorTest.php @@ -0,0 +1,56 @@ +encrypt($data); + + self::assertEquals($data, $aes->decrypt($encryptData)); + } + + /** + * @test + * @dataProvider getContentData() + * + * @param mixed $data + */ + public function checkEncryptorOtherTypes($data) + { + $aes = new AES256Encryptor(self::SECRET_KEY); + $encryptData = $aes->encrypt($data); + + self::assertEquals($encryptData, $data); + self::assertEquals($data, $aes->decrypt($encryptData)); + } + + /** + * @return array + */ + public function getContentData() + { + return [ + [1234], + [100.123], + [true], + [false], + [null], + ]; + } +} diff --git a/Tests/VariableEncryptorTest.php b/Tests/VariableEncryptorTest.php new file mode 100644 index 00000000..e8b8d782 --- /dev/null +++ b/Tests/VariableEncryptorTest.php @@ -0,0 +1,41 @@ +encrypt($data); + + self::assertEquals($data, $aes->decrypt($encryptData)); + } + + /** + * @test + */ + public function checkEncryptorWithoutString() + { + $aes = new VariableEncryptor(self::SECRET_KEY); + + $data = 12345; + $encryptData = $aes->encrypt($data); + + self::assertEquals($encryptData, $data); + self::assertEquals($data, $aes->decrypt($encryptData)); + } +} diff --git a/composer.json b/composer.json index 75506de8..7336c2f0 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,10 @@ "license": "MIT", "description": "Symfony 2 bundle which allows to encrypt data in database with some encrypt algorithm", "require": { - "php": ">=5.4", + "php": ">=5.6", "symfony/framework-bundle": ">=2.5", "doctrine/orm": ">=2.5", - "ext-mcrypt": "*" + "ext-openssl": "*" }, "autoload": { "psr-0": { "Ambta\\DoctrineEncryptBundle": "" } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..6558ba06 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,8 @@ + + + + + ./Tests + + + \ No newline at end of file From 1ee23c8c9399ea80819ca3418407d5445a39c6ad Mon Sep 17 00:00:00 2001 From: Alexandr Burov Date: Fri, 21 Apr 2017 15:04:44 +0300 Subject: [PATCH 02/12] Rename package --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7336c2f0..598419dd 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "ambta/doctrine-encrypt-bundle", + "name": "smoked/doctrine-encrypt-bundle", "type": "library", "keywords": ["doctrine", "symfony", "aes256", "rijndael", "encrypt", "decrypt"], "license": "MIT", From 40f46643cc472a25750d0143c9080c40f8c2cc32 Mon Sep 17 00:00:00 2001 From: Alexandr Burov Date: Wed, 3 May 2017 11:48:26 +0300 Subject: [PATCH 03/12] Revert all entities to original state. --- Subscribers/DoctrineEncryptSubscriber.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Subscribers/DoctrineEncryptSubscriber.php b/Subscribers/DoctrineEncryptSubscriber.php index 8b38887d..e91e0a8b 100644 --- a/Subscribers/DoctrineEncryptSubscriber.php +++ b/Subscribers/DoctrineEncryptSubscriber.php @@ -169,8 +169,18 @@ public function postLoad(LifecycleEventArgs $args) { */ public function preFlush(PreFlushEventArgs $preFlushEventArgs) { $unitOfWork = $preFlushEventArgs->getEntityManager()->getUnitOfWork(); - foreach($unitOfWork->getScheduledEntityInsertions() as $entity) { - $this->processFields($entity); + foreach ($unitOfWork->getIdentityMap() as $className => $entities) { + $class = $preFlushEventArgs->getEntityManager()->getClassMetadata($className); + if ($class->isReadOnly) { + continue; + } + + foreach ($entities as $entity) { + if ($entity instanceof Proxy && !$entity->__isInitialized__) { + continue; + } + $this->processFields($entity); + } } } From c2c60440502ba1cea566dc37a8f0f506fccde620 Mon Sep 17 00:00:00 2001 From: Steve Winter Date: Thu, 26 Oct 2017 10:59:54 +0300 Subject: [PATCH 04/12] Allow the encryption suffix which is added to the DB content to be defined through configuration --- DependencyInjection/Configuration.php | 2 ++ .../DoctrineEncryptExtension.php | 6 +++++ Encryptors/AES192Encryptor.php | 12 ++++++--- Encryptors/AES256Encryptor.php | 12 ++++++--- Encryptors/EncryptorInterface.php | 2 +- Encryptors/VariableEncryptor.php | 12 ++++++--- .../Library/Encryptor/AES128Encryptor.php | 12 ++++++--- Resources/config/orm-services.yml | 3 ++- Resources/doc/configuration.md | 7 ++++++ Resources/doc/custom_encryptor.md | 15 ++++++++--- Resources/doc/usage.md | 2 +- Services/Encryptor.php | 4 +-- Subscribers/DoctrineEncryptSubscriber.php | 25 ++++++++++++------- composer.json | 2 +- 14 files changed, 85 insertions(+), 31 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 8da38bbd..a71c5f7a 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -28,6 +28,8 @@ public function getConfigTreeBuilder() { ->children() ->scalarNode('secret_key') ->end() + ->scalarNode('encrypted_suffix') + ->end() ->scalarNode('encryptor') ->end() ->scalarNode('encryptor_class') diff --git a/DependencyInjection/DoctrineEncryptExtension.php b/DependencyInjection/DoctrineEncryptExtension.php index 1df0f980..fb42376a 100644 --- a/DependencyInjection/DoctrineEncryptExtension.php +++ b/DependencyInjection/DoctrineEncryptExtension.php @@ -47,6 +47,12 @@ public function load(array $configs, ContainerBuilder $container) } } + //If no encryption suffix then set the default + if (empty($config['encrypted_suffix'])) { + $config['encrypted_suffix'] = ''; + } + + //If empty encryptor class, use Rijndael 256 encryptor if (empty($config['encryptor_class'])) { if (isset($config['encryptor']) and isset($supportedEncryptorClasses[$config['encryptor']])) { diff --git a/Encryptors/AES192Encryptor.php b/Encryptors/AES192Encryptor.php index 36e56d39..1e08035e 100644 --- a/Encryptors/AES192Encryptor.php +++ b/Encryptors/AES192Encryptor.php @@ -17,6 +17,11 @@ class AES192Encryptor implements EncryptorInterface */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * @var string */ @@ -30,9 +35,10 @@ class AES192Encryptor implements EncryptorInterface /** * {@inheritdoc} */ - public function __construct($key) + public function __construct($key, $suffix) { $this->secretKey = md5($key); + $this->suffix = $suffix; $this->encryptMethod = sprintf('%s-%s', self::METHOD_NAME, self::ENCRYPT_MODE); $this->initializationVector = openssl_random_pseudo_bytes( openssl_cipher_iv_length($this->encryptMethod) @@ -51,7 +57,7 @@ public function encrypt($data) $this->secretKey, 0, $this->initializationVector - ))).''; + ))).$this->suffix; } return $data; @@ -63,7 +69,7 @@ public function encrypt($data) public function decrypt($data) { if (is_string($data)) { - $data = str_replace('', '', $data); + $data = str_replace($this->suffix, '', $data); return trim(openssl_decrypt( base64_decode($data), diff --git a/Encryptors/AES256Encryptor.php b/Encryptors/AES256Encryptor.php index c94215e6..c0a78ca5 100644 --- a/Encryptors/AES256Encryptor.php +++ b/Encryptors/AES256Encryptor.php @@ -17,6 +17,11 @@ class AES256Encryptor implements EncryptorInterface */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * @var string */ @@ -30,9 +35,10 @@ class AES256Encryptor implements EncryptorInterface /** * {@inheritdoc} */ - public function __construct($key) + public function __construct($key, $suffix) { $this->secretKey = md5($key); + $this->suffix = $suffix; $this->encryptMethod = sprintf('%s-%s', self::METHOD_NAME, self::ENCRYPT_MODE); $this->initializationVector = openssl_random_pseudo_bytes( openssl_cipher_iv_length($this->encryptMethod) @@ -51,7 +57,7 @@ public function encrypt($data) $this->secretKey, 0, $this->initializationVector - ))).''; + ))).$this->suffix; } return $data; @@ -63,7 +69,7 @@ public function encrypt($data) public function decrypt($data) { if (is_string($data)) { - $data = str_replace('', '', $data); + $data = str_replace($this->suffix, '', $data); return trim(openssl_decrypt( base64_decode($data), diff --git a/Encryptors/EncryptorInterface.php b/Encryptors/EncryptorInterface.php index 671497fb..83d91c91 100644 --- a/Encryptors/EncryptorInterface.php +++ b/Encryptors/EncryptorInterface.php @@ -13,7 +13,7 @@ interface EncryptorInterface { * Must accept secret key for encryption * @param string $secretKey the encryption key */ - public function __construct($secretKey); + public function __construct($secretKey, $suffix); /** * @param string $data Plain text to encrypt diff --git a/Encryptors/VariableEncryptor.php b/Encryptors/VariableEncryptor.php index f34fc4e0..7c7baa74 100644 --- a/Encryptors/VariableEncryptor.php +++ b/Encryptors/VariableEncryptor.php @@ -16,6 +16,11 @@ class VariableEncryptor implements EncryptorInterface */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * @var string */ @@ -24,9 +29,10 @@ class VariableEncryptor implements EncryptorInterface /** * {@inheritdoc} */ - public function __construct($key) + public function __construct($key, $suffix) { $this->secretKey = md5($key); + $this->suffix = $suffix; $this->initializationVector = openssl_random_pseudo_bytes( openssl_cipher_iv_length(self::ENCRYPT_METHOD) ); @@ -44,7 +50,7 @@ public function encrypt($data) $this->secretKey, 0, $this->initializationVector - ))).''; + ))).$this->suffix; } /* @@ -66,7 +72,7 @@ public function encrypt($data) public function decrypt($data) { if (is_string($data)) { - $data = str_replace('', '', $data); + $data = str_replace($this->suffix, '', $data); return trim(openssl_decrypt( base64_decode($data), diff --git a/Example/YourBundle/Library/Encryptor/AES128Encryptor.php b/Example/YourBundle/Library/Encryptor/AES128Encryptor.php index f1d3b0cc..17db1b57 100644 --- a/Example/YourBundle/Library/Encryptor/AES128Encryptor.php +++ b/Example/YourBundle/Library/Encryptor/AES128Encryptor.php @@ -15,6 +15,11 @@ class AES128Encryptor implements EncryptorInterface */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * @var string */ @@ -28,9 +33,10 @@ class AES128Encryptor implements EncryptorInterface /** * {@inheritdoc} */ - public function __construct($key) + public function __construct($key, $suffix) { $this->secretKey = md5($key); + $this->suffix = $suffix; $this->encryptMethod = sprintf('%s-%s', self::ENCRYPT_NAME, self::ENCRYPT_MODE); $this->initializationVector = openssl_random_pseudo_bytes( openssl_cipher_iv_length($this->encryptMethod) @@ -49,7 +55,7 @@ public function encrypt($data) $this->secretKey, 0, $this->initializationVector - ))).''; + ))).$this->suffix; } return $data; @@ -61,7 +67,7 @@ public function encrypt($data) public function decrypt($data) { if (is_string($data)) { - $data = str_replace('', '', $data); + $data = str_replace($this->suffix, '', $data); return trim(openssl_decrypt( base64_decode($data), diff --git a/Resources/config/orm-services.yml b/Resources/config/orm-services.yml index a46943ce..2967b299 100644 --- a/Resources/config/orm-services.yml +++ b/Resources/config/orm-services.yml @@ -1,7 +1,7 @@ services: ambta_doctrine_encrypt.orm_subscriber: class: Ambta\DoctrineEncryptBundle\Subscribers\DoctrineEncryptSubscriber - arguments: ["@annotation_reader", "%ambta_doctrine_encrypt.encryptor_class_name%", "%ambta_doctrine_encrypt.secret_key%"] + arguments: ["@annotation_reader", "%ambta_doctrine_encrypt.encryptor_class_name%", "%ambta_doctrine_encrypt.secret_key%", "%ambta_doctrine_encrypt.encrypted_suffix%"] tags: - { name: doctrine.event_subscriber } ambta_doctrine_encrypt.subscriber: @@ -11,3 +11,4 @@ services: arguments: - "%ambta_doctrine_encrypt.encryptor_class_name%" - "%ambta_doctrine_encrypt.secret_key%" + - "%ambta_doctrine_encrypt.encrypted_suffix%" diff --git a/Resources/doc/configuration.md b/Resources/doc/configuration.md index db0c56cd..5ff9bf4d 100644 --- a/Resources/doc/configuration.md +++ b/Resources/doc/configuration.md @@ -6,6 +6,10 @@ There are 3 paramaters in the configuration of the Doctrine encryption bundle wh * 32 character long string * Default: empty, the bundle will use your Symfony2 secret key. +* **encrypted_suffix** - The suffix to add to the end of encrypted strings + * any string which won't likely occur in the encrypted data + * Default: + * **encryptor** - The encryptor used to encrypt the data * Encryptor name, currently available: AES-192 and AES-256 * Default: AES-256 @@ -19,6 +23,7 @@ There are 3 paramaters in the configuration of the Doctrine encryption bundle wh ``` yaml ambta_doctrine_encrypt: secret_key: AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UW # Your own random 256 bit key (32 characters) + encrypted_suffix: # or any other string that you wish that won't cause issues with your DB encryptor: AES-256 # AES-256 or AES-192 encryptor_class: \Ambta\DoctrineEncryptBundle\Encryptors\AES256Encryptor # your own encryption class ``` @@ -29,6 +34,8 @@ ambta_doctrine_encrypt: AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UW + + ]]> AES-256 diff --git a/Resources/doc/custom_encryptor.md b/Resources/doc/custom_encryptor.md index 4ed4fed9..8ede9a12 100644 --- a/Resources/doc/custom_encryptor.md +++ b/Resources/doc/custom_encryptor.md @@ -1,8 +1,9 @@ + # Customer encryption class We can imagine that you want to use your own encryption class, it is simpel. -### Warning: make sure you add the `` after your encrypted string. +### Warning: make sure you add the encryption suffix after your encrypted string. 1. Create an new class and implement Ambta\DoctrineEncryptBundle\Encryptors\EncryptorInterface. 2. Create a constructor with the parameter secret key `__construct($secretKey)` @@ -35,6 +36,11 @@ class MyAES128Encryptor implements EncryptorInterface */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * @var string */ @@ -48,9 +54,10 @@ class MyAES128Encryptor implements EncryptorInterface /** * {@inheritdoc} */ - public function __construct($key) + public function __construct($key, $suffix) { $this->secretKey = md5($key); + $this->suffix = $suffix; $this->encryptMethod = sprintf('%s-%s', self::ENCRYPT_NAME, self::ENCRYPT_MODE); $this->initializationVector = openssl_random_pseudo_bytes( openssl_cipher_iv_length($this->encryptMethod) @@ -69,7 +76,7 @@ class MyAES128Encryptor implements EncryptorInterface $this->secretKey, 0, $this->initializationVector - ))).''; + ))).$this->suffix; } return $data; @@ -81,7 +88,7 @@ class MyAES128Encryptor implements EncryptorInterface public function decrypt($data) { if (is_string($data)) { - $data = str_replace('', '', $data); + $data = str_replace($this->suffix, '', $data); return trim(openssl_decrypt( base64_decode($data), diff --git a/Resources/doc/usage.md b/Resources/doc/usage.md index 21b44b6b..97c02f1b 100644 --- a/Resources/doc/usage.md +++ b/Resources/doc/usage.md @@ -43,7 +43,7 @@ class User { ``` It is as simple as that, the field will now be encrypted the first time the users entity gets edited. -We keep an prefix to check if data is encrypted or not so, unencrypted data will still work even if the field is encrypted. +We use a suffix () to check if data is encrypted or not so, unencrypted data will still work even if the field is encrypted. ## Console commands diff --git a/Services/Encryptor.php b/Services/Encryptor.php index db4ce748..9f2d4085 100644 --- a/Services/Encryptor.php +++ b/Services/Encryptor.php @@ -13,12 +13,12 @@ class Encryptor /** @var \Ambta\DoctrineEncryptBundle\Encryptors\EncryptorInterface */ protected $encryptor; - public function __construct($encryptName, $key) + public function __construct($encryptName, $key, $suffix) { $reflectionClass = new \ReflectionClass($encryptName); $this->encryptor = $reflectionClass->newInstanceArgs( array( - $key + $key, $suffix )); } diff --git a/Subscribers/DoctrineEncryptSubscriber.php b/Subscribers/DoctrineEncryptSubscriber.php index e91e0a8b..2d8ee6d3 100644 --- a/Subscribers/DoctrineEncryptSubscriber.php +++ b/Subscribers/DoctrineEncryptSubscriber.php @@ -46,6 +46,11 @@ class DoctrineEncryptSubscriber implements EventSubscriber { */ private $secretKey; + /** + * @var string + */ + private $suffix; + /** * Used for restoring the encryptor after changing it * @var string @@ -74,14 +79,15 @@ class DoctrineEncryptSubscriber implements EventSubscriber { * * This allows for the use of dependency injection for the encrypters. */ - public function __construct(Reader $annReader, $encryptorClass, $secretKey, EncryptorInterface $service = NULL) { + public function __construct(Reader $annReader, $encryptorClass, $secretKey, $suffix, EncryptorInterface $service = NULL) { $this->annReader = $annReader; $this->secretKey = $secretKey; + $this->suffix = $suffix; if ($service instanceof EncryptorInterface) { $this->encryptor = $service; } else { - $this->encryptor = $this->encryptorFactory($encryptorClass, $secretKey); + $this->encryptor = $this->encryptorFactory($encryptorClass, $secretKey, $suffix); } $this->restoreEncryptor = $this->encryptor; @@ -95,7 +101,7 @@ public function __construct(Reader $annReader, $encryptorClass, $secretKey, Encr public function setEncryptor($encryptorClass) { if(!is_null($encryptorClass)) { - $this->encryptor = $this->encryptorFactory($encryptorClass, $this->secretKey); + $this->encryptor = $this->encryptorFactory($encryptorClass, $this->secretKey, $this->suffix); return; } @@ -280,12 +286,13 @@ public function processFields($entity, $isEncryptOperation = true) { } /** - * Then decrypt, encrypt the information if not empty, information is an string and the tag is there (decrypt) or not (encrypt). - * The will be added at the end of an encrypted string so it is marked as encrypted. Also protects against double encryption/decryption + * Then decrypt, encrypt the information if not empty, information is a string and the encryption suffix () tag is there (decrypt) or not (encrypt). + * The encryption suffix () will be added at the end of an encrypted string so it is marked as encrypted. Also protects against double encryption/decryption */ + $suffixLength = (0 - strlen($this->suffix)); if($encryptorMethod == "decrypt") { if(!is_null($getInformation) and !empty($getInformation)) { - if(substr($getInformation, -5) == "") { + if(substr($getInformation, $suffixLength) == $this->suffix) { $this->decryptCounter++; $currentPropValue = $this->encryptor->decrypt(substr($getInformation, 0, -5)); $entity->$setter($currentPropValue); @@ -293,7 +300,7 @@ public function processFields($entity, $isEncryptOperation = true) { } } else { if(!is_null($getInformation) and !empty($getInformation)) { - if(substr($entity->$getter(), -5) != "") { + if(substr($entity->$getter(), $suffixLength) != $this->suffix) { $this->encryptCounter++; $currentPropValue = $this->encryptor->encrypt($entity->$getter()); $entity->$setter($currentPropValue); @@ -372,10 +379,10 @@ function getClassProperties($className){ * @return EncryptorInterface * @throws \RuntimeException */ - private function encryptorFactory($classFullName, $secretKey) { + private function encryptorFactory($classFullName, $secretKey, $suffix) { $refClass = new \ReflectionClass($classFullName); if ($refClass->implementsInterface(self::ENCRYPTOR_INTERFACE_NS)) { - return new $classFullName($secretKey); + return new $classFullName($secretKey, $suffix); } else { throw new \RuntimeException('Encryptor must implements interface EncryptorInterface'); } diff --git a/composer.json b/composer.json index 598419dd..e6a2e043 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "smoked/doctrine-encrypt-bundle", + "name": "matatirosoln/doctrine-encrypt-bundle", "type": "library", "keywords": ["doctrine", "symfony", "aes256", "rijndael", "encrypt", "decrypt"], "license": "MIT", From 08be39b1cedf1c8945ddd79445a78e3092d6f259 Mon Sep 17 00:00:00 2001 From: Steve Winter Date: Thu, 26 Oct 2017 11:16:52 +0300 Subject: [PATCH 05/12] Allow the encryption suffix which is added to the DB content to be defined through configuration --- DependencyInjection/DoctrineEncryptExtension.php | 1 + 1 file changed, 1 insertion(+) diff --git a/DependencyInjection/DoctrineEncryptExtension.php b/DependencyInjection/DoctrineEncryptExtension.php index fb42376a..ad8eb589 100644 --- a/DependencyInjection/DoctrineEncryptExtension.php +++ b/DependencyInjection/DoctrineEncryptExtension.php @@ -65,6 +65,7 @@ public function load(array $configs, ContainerBuilder $container) //Set parameters $container->setParameter('ambta_doctrine_encrypt.encryptor_class_name', $config['encryptor_class']); $container->setParameter('ambta_doctrine_encrypt.secret_key', $config['secret_key']); + $container->setParameter('ambta_doctrine_encrypt.encrypted_suffix', $config['encrypted_suffix']); //Load service file $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); From f671aa3ce80c9cacf57559634ffb1d39a9e89a26 Mon Sep 17 00:00:00 2001 From: JoeCotellese Date: Sun, 15 Apr 2018 10:42:12 -0400 Subject: [PATCH 06/12] Update installation.md Fix heading typo --- Resources/doc/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/doc/installation.md b/Resources/doc/installation.md index 41eb50ac..412fc070 100644 --- a/Resources/doc/installation.md +++ b/Resources/doc/installation.md @@ -1,4 +1,4 @@ -#Installation +# Installation 1. Download AmbtaDoctrineEncryptBundle using composer 2. Enable the database encryption bundle From f9a38fd4c6e3aaeb8521336caa70a71b8939b619 Mon Sep 17 00:00:00 2001 From: JoeCotellese Date: Sun, 15 Apr 2018 10:52:50 -0400 Subject: [PATCH 07/12] Update usage.md Fix typo in heading --- Resources/doc/usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/doc/usage.md b/Resources/doc/usage.md index 21b44b6b..f1045038 100644 --- a/Resources/doc/usage.md +++ b/Resources/doc/usage.md @@ -1,4 +1,4 @@ -#Usage +# Usage Lets imagine that we are storing some private data in our database and we don't want to somebody can see it even if he will get raw database on his hands in some dirty way. @@ -50,4 +50,4 @@ We keep an prefix to check if data is encrypted or not so, unencrypted dat There are some console commands that can help you encrypt your existing database or change encryption methods. Read more about the database encryption commands provided with this bundle. -#### [Console commands](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/commands.md) \ No newline at end of file +#### [Console commands](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/commands.md) From 4e82e21a57430b9cb72f7180960f1e4d938add0c Mon Sep 17 00:00:00 2001 From: JoeCotellese Date: Sun, 15 Apr 2018 11:06:27 -0400 Subject: [PATCH 08/12] Update README.md Fix annotation typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc5d5424..a4493611 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ More about us can be found on our website. [Ambta.com](https://ambta.com) ###What does it do exactly -It gives you the opportunity to add the @Encrypt annotation above each string property +It gives you the opportunity to add the @Encrypted annotation above each string property ```php /** - * @Encrypt + * @Encrypted */ protected $username; ``` From 94d54aefd4baf2f1d45296faf4c26af7b84ddd9b Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 13 Oct 2019 17:21:08 +0100 Subject: [PATCH 09/12] fix documentation markdown --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index dc5d5424..c36ad1b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#DoctrineEncryptBundle +#D octrineEncryptBundle Bundle allows to create doctrine entities with fields that will be protected with help of some encryption algorithm in database and it will be clearly for developer, because bundle is uses doctrine life cycle events @@ -10,7 +10,7 @@ I improved several things, i make better use of the doctrine events. and it work This will be an long term project we will be working on with long-term support and backward compatibility. We are using this bundle in all our own symfony2 project. More about us can be found on our website. [Ambta.com](https://ambta.com) -###What does it do exactly +### What does it do exactly It gives you the opportunity to add the @Encrypt annotation above each string property @@ -24,19 +24,19 @@ protected $username; The bundle uses doctrine his life cycle events to encrypt the data when inserted into the database and decrypt the data when loaded into your entity manager. It is only able to encrypt string values at the moment, numbers and other fields will be added later on in development. -###Advantages and disadvantaged of an encrypted database +### Advantages and disadvantaged of an encrypted database -####Advantages +#### Advantages - Information is stored safely - Not worrying about saving backups at other locations - Unreadable for employees managing the database -####Disadvantages +#### Disadvantages - Can't use ORDER BY on encrypted data - In SELECT WHERE statements the where values also have to be encrypted - When you lose your key you lose your data (Make a backup of the key on a safe location) -###Documentation +### Documentation This bundle is responsible for encryption/decryption of the data in your database. All encryption/decryption work on the server side. @@ -49,15 +49,15 @@ The following documents are available: * [Console commands](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/commands.md) * [Custom encryption class](https://github.com/ambta/DoctrineEncryptBundle/blob/master/Resources/doc/custom_encryptor.md) -###License +### License This bundle is under the MIT license. See the complete license in the bundle -###Versions +### Versions I'm using Semantic Versioning like described [here](http://semver.org) -###Todos +### Todos The following items will be done in order From af9e847d6a95c2f7e1da22e095f2e2c1a41e3280 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 13 Oct 2019 17:29:13 +0100 Subject: [PATCH 10/12] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tarmo Leppänen --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c36ad1b5..d9b374c1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#D octrineEncryptBundle +# DoctrineEncryptBundle Bundle allows to create doctrine entities with fields that will be protected with help of some encryption algorithm in database and it will be clearly for developer, because bundle is uses doctrine life cycle events From c5f5f5f2131e0f876cab6fb82fd8fc44d70903a2 Mon Sep 17 00:00:00 2001 From: Steve Winter Date: Sun, 26 Apr 2020 17:14:44 +0100 Subject: [PATCH 11/12] Adding SF 5 support --- DependencyInjection/Configuration.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index a71c5f7a..a0e7703e 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -20,8 +20,13 @@ class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { //Create tree builder - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('ambta_doctrine_encrypt'); + if (method_exists(TreeBuilder::class, 'getRootNode')) { + $treeBuilder = new TreeBuilder('ambta_doctrine_encrypt'); + $rootNode = $treeBuilder->getRootNode(); + } else { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('ambta_doctrine_encrypt'); + } // Grammar of config tree $rootNode From af383488608aa1b1c6bfac54faf082339f2d9e10 Mon Sep 17 00:00:00 2001 From: Marcel van Nuil Date: Mon, 27 Apr 2020 16:10:51 +0200 Subject: [PATCH 12/12] fixed #50, for 2.5 version see #50 - 2.5 version --- Resources/doc/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/doc/installation.md b/Resources/doc/installation.md index 0319337b..cb7392d1 100644 --- a/Resources/doc/installation.md +++ b/Resources/doc/installation.md @@ -18,7 +18,7 @@ AmbtaDoctrineEncryptBundle should be installed usin [Composer](http://getcompose ``` js { "require": { - "ambta/doctrine-encrypt-bundle": "2.4.*" + "ambta/doctrine-encrypt-bundle": "^2.5" } } ```