Skip to content

Commit

Permalink
Add check on encryptor for already encrypted values
Browse files Browse the repository at this point in the history
  • Loading branch information
magi-web authored and maxhelias committed May 9, 2023
1 parent 17671e9 commit f64228d
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/Encryptors/CiphersweetEncryptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ public function prepareForStorage(object $entity, string $fieldName, string $str
{
$entitClassName = \get_class($entity);

if ($this->isValueEncrypted($string)) {
// If the value is already encrypted and there is no need to get blind index,
// We return it as is.
if (!$index) {
return [$string, []];
}

// Otherwise, we try to decrypt it and we generate the corresponding Blind Index
$decryptedString = $this->decrypt($entitClassName, $fieldName, $string, $filterBits, $fastIndexing);
return [$string, [$fieldName.'_bi' => $this->getBlindIndex($entitClassName, $fieldName, $decryptedString, $filterBits, $fastIndexing)]];
}

$output = [];
if (isset($this->cache[$entitClassName][$fieldName][$string])) {
$output[] = $this->cache[$entitClassName][$fieldName][$string];
Expand Down Expand Up @@ -65,6 +77,11 @@ protected function doEncrypt(string $entitClassName, string $fieldName, string $

public function decrypt(string $entity_classname, string $fieldName, string $string, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): string
{
// If $string is not encrypted, we return it as is.
if (!$this->isValueEncrypted($string)) {
return $string;
}

if (isset($this->cache[$entity_classname][$fieldName][$string])) {
return $this->cache[$entity_classname][$fieldName][$string];
}
Expand Down Expand Up @@ -109,4 +126,11 @@ public function getPrefix(): string
{
return $this->engine->getBackend()->getPrefix();
}

public function isValueEncrypted(?string $value): bool
{
return $value !== null && strpos($value, $this->getPrefix()) === 0;
}


}
2 changes: 2 additions & 0 deletions src/Encryptors/EncryptorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ public function decrypt(string $entity_classname, string $fieldName, string $str
public function getBlindIndex($entityName, $fieldName, string $value, int $filterBits = self::DEFAULT_FILTER_BITS, bool $fastIndexing = self::DEFAULT_FAST_INDEXING): string;

public function getPrefix(): string;

public function isValueEncrypted(?string $value): bool;
}
2 changes: 1 addition & 1 deletion src/Subscribers/DoctrineCiphersweetSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ private function handleDecryptOperation(int $oid, $value, \ReflectionProperty $r
*/
private function isValueEncrypted(?string $value): bool
{
return $value !== null && strpos($value, $this->encryptor->getPrefix()) === 0;
return $this->encryptor->isValueEncrypted($value);
}

/**
Expand Down
25 changes: 25 additions & 0 deletions tests/Unit/Encryptors/CiphersweetEncryptorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,29 @@ public function testDecrypt()
$this->assertSame('test', $result);
$this->assertSame(0, $this->encryptor->callsCount['decrypt'], 'doDecrypt is never called because cache is set upon prepareForStorage call');
}

public function testDecryptNonEncryptedValue()
{
[$encryptedString] = $this->encryptor->prepareForStorage(new MyEntity('132456'), 'account_name', 'test');

$decryptedString = $this->encryptor->decrypt(MyEntity::class, 'account_name', $encryptedString);
$untouchedString = $this->encryptor->decrypt(MyEntity::class, 'account_name', $decryptedString);

$this->assertSame($decryptedString, $untouchedString);
$this->assertSame(1, $this->encryptor->callsCount['encrypt']);
$this->assertSame(0, $this->encryptor->callsCount['decrypt'], 'doDecrypt is never called either because of cache set upon prepareForStorage call or we detect value is already decrypted');
}

public function testEncryptAlreadyEncryptedValue()
{
[$encryptedString] = $this->encryptor->prepareForStorage(new MyEntity('132456'), 'account_name', 'test', false);
[$unTouchedEncryptedString] = $this->encryptor->prepareForStorage(new MyEntity('132456'), 'account_name', 'test', false);
[$unTouchedEncryptedStringBis, $bi] = $this->encryptor->prepareForStorage(new MyEntity('132456'), 'account_name', 'test', true);

$this->assertSame($encryptedString, $unTouchedEncryptedString);
$this->assertSame($encryptedString, $unTouchedEncryptedStringBis);
$this->assertSame(8, mb_strlen($bi['account_name_bi']));
$this->assertSame(1, $this->encryptor->callsCount['encrypt']);
$this->assertSame(0, $this->encryptor->callsCount['decrypt']);
}
}

0 comments on commit f64228d

Please sign in to comment.