diff --git a/src/EncryptedRow.php b/src/EncryptedRow.php index 4301dd7..8b087ab 100644 --- a/src/EncryptedRow.php +++ b/src/EncryptedRow.php @@ -14,6 +14,7 @@ }; use ParagonIE\ConstantTime\Hex; use SodiumException; +use TypeError; /** * Class EncryptedRow @@ -232,6 +233,34 @@ public function createCompoundIndex( return $index; } + /** + * Create a fast compound blind index then add it to this EncryptedRow object. + * + * @param string $name + * @param array $columns + * @param int $filterBits + * @param array $hashConfig + * @return CompoundIndex + * + * @throws CipherSweetException + */ + public function createFastCompoundIndex( + string $name, + array $columns = [], + int $filterBits = 256, + array $hashConfig = [] + ): CompoundIndex { + $index = new FastCompoundIndex( + $name, + $columns, + $filterBits, + true, + $hashConfig + ); + $this->addCompoundIndex($index); + return $index; + } + /** * Calculate a blind index (or compound blind index) output for this row. * @@ -422,10 +451,10 @@ public function decryptRow( } if ( !empty($this->aadSourceField[$field]) - && + && \array_key_exists($this->aadSourceField[$field], $row) ) { - $aad = (string) $row[$this->aadSourceField[$field]]; + $aad = $this->coaxAadToString($row[$this->aadSourceField[$field]]); } else { $aad = ''; } @@ -453,7 +482,7 @@ public function decryptRow( * If any columns are defined in this object to be encrypted, the value * will be encrypted in-place in the returned array. * - * @param array $row + * @param array $row * @return array * * @throws ArrayKeyException @@ -463,7 +492,8 @@ public function decryptRow( */ public function encryptRow( #[\SensitiveParameter] - array $row + array $row, + bool $decode_json = false, ): array { /** @var array $return */ $return = $row; @@ -472,7 +502,7 @@ public function encryptRow( if (!\array_key_exists($field, $row)) { throw new ArrayKeyException( 'Expected value for column ' . - $field . + $field . ' on array, nothing given.' ); } @@ -482,14 +512,19 @@ public function encryptRow( ); if ( !empty($this->aadSourceField[$field]) - && + && \array_key_exists($this->aadSourceField[$field], $row) ) { - $aad = (string) $row[$this->aadSourceField[$field]]; + $aad = $this->coaxAadToString($row[$this->aadSourceField[$field]]); } else { $aad = ''; } if ($type === Constants::TYPE_JSON && !empty($this->jsonMaps[$field])) { + $return[$field] = $row[$field]; + // checks decode json option + if ($decode_json) { + $row[$field] = $this->formatJson($row[$field]); + } // JSON is a special case $jsonEncryptor = new EncryptedJsonField( $backend, @@ -497,10 +532,12 @@ public function encryptRow( $this->jsonMaps[$field], $this->jsonStrict[$field] ); - /** @psalm-suppress InvalidArgument */ - $return[$field] = $jsonEncryptor->encryptJson($row[$field], $aad); + $return[$field] = $jsonEncryptor->encryptJson($this->coaxToArray($row[$field]), $aad); continue; } + if (!is_scalar($row[$field])) { + throw new TypeError('Invalid type for ' . $field); + } $plaintext = $this->convertToString($row[$field], $type); $return[$field] = $backend->encrypt($plaintext, $key, $aad); } @@ -511,6 +548,20 @@ public function encryptRow( return $return; } + /** + * Decoding json field + * + * @param array|mixed|null $field + * @return array + */ + public function formatJson( + $field + ): array { + //decode json field then to take key from it to encrypt it + $field = isset($field) ? (is_string($field) ? (array)json_decode($field) : $field) : []; + return $field; + } + /** * Process an entire row, which means: * @@ -848,4 +899,42 @@ public function setTypedIndexes(bool $bool): static $this->typedIndexes = $bool; return $this; } + + /** + * @param mixed $input + * @return array + */ + protected function coaxToArray(mixed $input): array + { + if (is_array($input)) { + return $input; + } + if (is_null($input)) { + return []; + } + if (is_object($input)) { + /** psalm-suppress PossiblyInvalidCast */ + return (array) $input; + } + if (is_string($input)) { + return json_decode($input, true); + } + throw new TypeError("Cannot coax to array: " . gettype($input)); + } + + /** + * @param mixed $input + * @return string + */ + protected function coaxAadToString(mixed $input): string + { + if (is_string($input)) { + return $input; + } + if (is_numeric($input)) { + return '' . $input; + } + /** psalm-suppress PossiblyInvalidCast */ + return (string) $input; + } } diff --git a/src/FastCompoundIndex.php b/src/FastCompoundIndex.php new file mode 100644 index 0000000..5210a05 --- /dev/null +++ b/src/FastCompoundIndex.php @@ -0,0 +1,38 @@ + $columns + * @param int $filterBits + * @param bool $fastHash + * @param array $hashConfig + * + * @throws CipherSweetException + */ + public function __construct( + string $name, + array $columns = [], + int $filterBits = 256, + bool $fastHash = true, + array $hashConfig = [] + ) { + if (!$fastHash) { + throw new CipherSweetException("FastCompoundIndex cannot be turned slow"); + } + return parent::__construct( + $name, + $columns, + $filterBits, + $fastHash, + $hashConfig + ); + } +}