Skip to content

Commit

Permalink
Merge pull request #6 from odandb/feature/tests-perfs
Browse files Browse the repository at this point in the history
Add tests & enhance perfs while performing encryption/decryption
  • Loading branch information
magi-web authored Nov 23, 2022
2 parents c1c2542 + 6940a19 commit 2c73f76
Show file tree
Hide file tree
Showing 24 changed files with 524 additions and 15 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,12 @@
phpunit.xml
.phpunit.result.cache
composer.lock
.idea/
cache/
var/
tests/coverage/
.DS_Store
.php_cs.cache
.php-cs-fixer.cache
*.sqlite
.preload.php
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@
"symfony/yaml": "^4.4 || ^5.1 || ^6.0"
},
"require-dev": {
"doctrine/doctrine-bundle": "^2.7",
"roave/security-advisories": "dev-latest",
"symfony/phpunit-bridge": "^5.1 || ^6.0"
"symfony/doctrine-bridge": "^5.1 || ^6.0",
"symfony/dotenv": "^5.1 || ^6.0",
"symfony/framework-bundle": "^5.1 || ^6.0",
"symfony/phpunit-bridge": "^5.1 || ^6.0",
"symfony/test-pack": "^1.0"
},
"suggest": {
"phpdocumentor/reflection-docblock": "To use the PHPDoc"
Expand Down
22 changes: 21 additions & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="./vendor/autoload.php"
bootstrap="tests/bootstrap.php"
verbose="true"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="APP_DEBUG" value="false" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="KERNEL_CLASS" value="Odandb\DoctrineCiphersweetEncryptionBundle\Tests\App\Kernel" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_DEPRECATIONS_HELPER" value="999999" />
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
<env name="BOOTSTRAP_CLEAR_CACHE_ENV" value="true"/>
<env name="DOCTRINE_CIPHERSWEET_KEY" value="d6e9b37eacf3da581519a71f29a1d08e5552d3cf490d75db33b1c6f8e4b4fe50"/>
</php>

<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
47 changes: 40 additions & 7 deletions src/Encryptors/CiphersweetEncryptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,25 @@ public function __construct(CipherSweet $engine)

public function prepareForStorage(object $entity, string $fieldName, string $string, bool $index = true, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): array
{
$entitClassName= \get_class($entity);
$entitClassName = \get_class($entity);

$output = [];
if (isset($this->cache[$entitClassName][$fieldName][$string])) {
return $this->cache[$entitClassName][$fieldName][$string];
$output[] = $this->cache[$entitClassName][$fieldName][$string];
if ($index) {
$output[] = [$fieldName.'_bi' => $this->getBlindIndex($entitClassName, $fieldName, $string, $filterBits, $fastIndexing)];
} else {
$output[] = [];
}

return $output;
}

return $this->doEncrypt($entitClassName, $fieldName, $string, $index, $filterBits, $fastIndexing);
}

protected function doEncrypt(string $entitClassName, string $fieldName, string $string, bool $index = true, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): array
{
$encryptedField = (new EncryptedField($this->engine, $entitClassName, $fieldName));
if ($index) {
$encryptedField->addBlindIndex(
Expand All @@ -39,18 +53,32 @@ public function prepareForStorage(object $entity, string $fieldName, string $str

$result = $encryptedField->prepareForStorage($string);

$this->cache[$entitClassName][$fieldName][$string] = $result;
$this->cache[$entitClassName][$fieldName][$string] = $result[0];
$this->cache[$entitClassName][$fieldName][$result[0]] = $string;

$this->biCache[$entitClassName][$fieldName][$string] = $result[1][$fieldName.'_bi'];

return $result;
}

public function decrypt(string $entity_classname, string $fieldName, string $string, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): string
{
return (new EncryptedField($this->engine, $entity_classname, $fieldName))
->addBlindIndex(
new BlindIndex($fieldName.'_bi', [], $filterBits, $fastIndexing)
)
if (isset($this->cache[$entity_classname][$fieldName][$string])) {
return $this->cache[$entity_classname][$fieldName][$string];
}

return $this->doDecrypt($entity_classname, $fieldName, $string);
}

protected function doDecrypt(string $entity_classname, string $fieldName, string $string): string
{
$decryptedValue = (new EncryptedField($this->engine, $entity_classname, $fieldName))
->decryptValue($string);

$this->cache[$entity_classname][$fieldName][$string] = $decryptedValue;
$this->cache[$entity_classname][$fieldName][$decryptedValue] = $string;

return $decryptedValue;
}

public function getBlindIndex($entityName, $fieldName, string $value, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): string
Expand All @@ -59,6 +87,11 @@ public function getBlindIndex($entityName, $fieldName, string $value, int $filte
return $this->biCache[$entityName][$fieldName][$value];
}

return $this->doGetBlindIndex($entityName, $fieldName, $value, $filterBits, $fastIndexing);
}

private function doGetBlindIndex($entityName, $fieldName, string $value, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): string
{
$index = (new EncryptedField($this->engine, $entityName, $fieldName))
->addBlindIndex(
new BlindIndex($fieldName.'_bi', [], $filterBits, $fastIndexing)
Expand Down
4 changes: 2 additions & 2 deletions src/Services/IndexableFieldsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
namespace Odandb\DoctrineCiphersweetEncryptionBundle\Services;


use Doctrine\ORM\EntityRepository;
use Odandb\DoctrineCiphersweetEncryptionBundle\Configuration\EncryptedField;
use Odandb\DoctrineCiphersweetEncryptionBundle\Configuration\IndexableField;
use Odandb\DoctrineCiphersweetEncryptionBundle\Encryptors\EncryptorInterface;
use Odandb\DoctrineCiphersweetEncryptionBundle\Entity\IndexedEntityInterface;
use Odandb\DoctrineCiphersweetEncryptionBundle\Exception\MissingPropertyFromReflectionException;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Annotations\Reader;
use Doctrine\ORM\EntityManagerInterface;

Expand All @@ -33,7 +33,7 @@ public function __construct(Reader $annReader, EntityManagerInterface $em, Index

public function getChunksForMultiThread(string $className, int $chuncksLength): array
{
/** @var ServiceEntityRepository $repo */
/** @var EntityRepository $repo */
$repo = $this->em->getRepository($className);
$result = $repo->createQueryBuilder('c')
->select('c.id')
Expand Down
6 changes: 3 additions & 3 deletions src/Services/IndexesGenerators/ValueEndingByGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class ValueEndingByGenerator implements IndexesGeneratorInterface
*/
public function generate(string $value): array
{
$possibleValues[] = $value;
$possibleValues = [];

for($i=1, $len = mb_strlen($value); $i < $len; $i++) {
$possibleValues[] = mb_substr($value, 0, -$i);
for($i=1, $len = mb_strlen($value); $i <= $len; $i++) {
$possibleValues[] = mb_substr($value, -$i);
}

return $possibleValues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ValueStartingByGenerator implements IndexesGeneratorInterface
{
public function generate(string $value): array
{
$possibleValues = [$value];
$possibleValues = [];

for($i=1, $len = mb_strlen($value); $i <= $len; $i++) {
$possibleValues[] = mb_substr($value, 0, $i);
Expand Down
47 changes: 47 additions & 0 deletions tests/App/Kernel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);


namespace Odandb\DoctrineCiphersweetEncryptionBundle\Tests\App;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;

class Kernel extends BaseKernel
{
use MicroKernelTrait;

private const CONFIG_EXTS = '.{php,xml,yaml,yml}';

public function registerBundles(): iterable
{
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if ($envs[$this->environment] ?? $envs['all'] ?? false) {
yield new $class();
}
}
}

public function getProjectDir(): string
{
return \dirname(__DIR__).'/App';
}

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
$container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400 || $this->debug);
$container->setParameter('container.dumper.inline_factories', true);

$loader->load($this->getProjectDir().'/config/services'.self::CONFIG_EXTS, 'glob');
$loader->load($this->getProjectDir().'/config/{packages}/*'.self::CONFIG_EXTS, 'glob');

$confDir = $this->getProjectDir().'/../../src/Resources/config';
$loader->load($confDir.'/encryption-services'.self::CONFIG_EXTS, 'glob');
}
}
42 changes: 42 additions & 0 deletions tests/App/bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env php
<?php

use Odandb\DoctrineCiphersweetEncryptionBundle\Tests\App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\ErrorHandler\Debug;

if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
}

set_time_limit(0);

require dirname(__DIR__) . '/../../vendor/autoload.php';

if (!class_exists(Application::class)) {
throw new LogicException('You need to add "symfony/framework-bundle" as a Composer dependency.');
}

$input = new ArgvInput();
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
}

if ($input->hasParameterOption('--no-debug', true)) {
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
}

require dirname(__DIR__) . '/config/bootstrap.php';

if ($_SERVER['APP_DEBUG']) {
umask(0000);

if (class_exists(Debug::class)) {
Debug::enable();
}
}

$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$application = new Application($kernel);
$application->run($input);
25 changes: 25 additions & 0 deletions tests/App/config/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

use Symfony\Component\Dotenv\Dotenv;

require dirname(__DIR__).'/../../vendor/autoload.php';

// // Load cached env vars if the .env.local.php file exists
// // Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
// if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && (!isset($env['APP_ENV']) || ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV'])) {
// foreach ($env as $k => $v) {
// $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
// }
// } elseif (!class_exists(Dotenv::class)) {
// throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
// } else {
// // load all the .env files
// (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
// }

$_SERVER += $_ENV;
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
$_SERVER['APP_DEBUG'] ??= $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
7 changes: 7 additions & 0 deletions tests/App/config/bundles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Odandb\DoctrineCiphersweetEncryptionBundle\OdandbDoctrineCiphersweetEncryptionBundle::class => ['all' => true],
];
27 changes: 27 additions & 0 deletions tests/App/config/packages/doctrine.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
doctrine:
dbal:
default_connection: default
connections:
default:
# configure these for your database server
driver: 'pdo_sqlite'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
url: 'sqlite:///%kernel.project_dir%/var/data.db'
orm:
default_entity_manager: default
auto_generate_proxy_classes: true
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/../Model'
prefix: 'Odandb\DoctrineCiphersweetEncryptionBundle\Tests\Model\MyEntity'
alias: App
2 changes: 2 additions & 0 deletions tests/App/config/packages/framework.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
framework:
test: true
3 changes: 3 additions & 0 deletions tests/App/config/packages/routing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
framework:
router:
utf8: true
4 changes: 4 additions & 0 deletions tests/App/config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
_defaults:
autowire: true
autoconfigure: true
29 changes: 29 additions & 0 deletions tests/Encryptors/CiphersweetEncryptorObservable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);


namespace Odandb\DoctrineCiphersweetEncryptionBundle\Tests\Encryptors;


use Odandb\DoctrineCiphersweetEncryptionBundle\Encryptors\CiphersweetEncryptor;

class CiphersweetEncryptorObservable extends CiphersweetEncryptor
{
public array $callsCount = [
'encrypt' => 0,
'decrypt' => 0,
];

protected function doEncrypt(string $entitClassName, string $fieldName, string $string, bool $index = true, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): array
{
$this->callsCount['encrypt']++;
return parent::doEncrypt($entitClassName, $fieldName, $string, $index, $filterBits, $fastIndexing);
}

protected function doDecrypt(string $entity_classname, string $fieldName, string $string): string
{
$this->callsCount['decrypt']++;
return parent::doDecrypt($entity_classname, $fieldName, $string);
}
}
Loading

0 comments on commit 2c73f76

Please sign in to comment.