当数据被静态加密时,您将如何在数据库中搜索明文值(姓名或电子邮件)?
您不能一般对任意加密的数据执行此操作,但是像 CipherSweet 这样的库可以让这非常容易。
文档应该可以帮助您安装库。
要使用它,您首先需要setup a KeyProvider,然后创建一个EncryptedRow 对象,如下所示:
<?php
use ParagonIE\CipherSweet\BlindIndex;
use ParagonIE\CipherSweet\CipherSweet;
use ParagonIE\CipherSweet\CompoundIndex;
use ParagonIE\CipherSweet\EncryptedRow;
use ParagonIE\CipherSweet\Backend\FIPSCrypto;
use ParagonIE\CipherSweet\KeyProvider\StringProvider;
// Example key provider
$keyProvider = new StringProvider('4e1c44f87b4cdf21808762970b356891db180a9dd9850e7baf2a79ff3ab8a2fc');
// Setup the engine with a key provider. FIPSCrypto uses OpenSSL.
$engine = new CipherSweet($provider, new FIPSCrypto());
// EncryptedRow object setup:
$rowProcessor = (new EncryptedRow($engine, 'your_table_name_here'))
->addTextField('name')
->addTextField('email');
$rowProcessor->addBlindIndex(
'name',
new BlindIndex(
'my_table__name_literal',
16 /* See below */
)
);
$rowProcessor->addBlindIndex(
'email',
new BlindIndex(
'my_table__email_literal',
16 /* See below */
)
);
在此示例中,我添加了两个盲索引,每个索引的大小为 16 位。这是一个捏造的数字;您需要查看 blind index planning 以在此处使用哪些值作为指导。
现在您需要在将数据读/写到 MySQL 数据库时更新您的代码,使用 $rowProcessor 透明地即时加密/解密您的数据(以差异格式):
/** @var array<string, mixed> $inputValues */
- $db->insert('your_table_name_here', $inputValues);
+ [$inputValuesSomeEncrypted, $indices] = $rowProcessor->prepareForStorage($inputValues);
+ // If you wish to store the blind indexes in the same table:
+ $inputValuesSomeEncrypted['name_idx'] = $indices['my_table__name_literal'];
+ $inputValuesSomeEncrypted['email_idx'] = $indices['my_table__email_literal'];
+ $db->insert('your_table_name_here', $inputValuesSomeEncrypted);
接下来,您需要调整查找逻辑。
- $rows = $db->lookup("name = ? OR email = ?", [$row['name'], $row['email']]);
+ $index1 = $rowProcessor->getBlindIndex('my_table__name_literal', $row);
+ $index2 = $rowProcessor->getBlindIndex('my_table__email_literal', $row);
+ $rowsWithCiphertext = $db->lookup("name_idx = ? OR email_idx = ?", [$index1, $index2]);
+
+ /* We need to post-process to eliminate coincidences in the blind index */
+ $rows = [];
+ foreach ($rowsWithCiphertext as $rowC) {
+ $decrypted = $rowProcessor->decryptRow($rowC);
+ if (!hash_equals($decrypted['name'], $row['name']) && !hash_equals($decrypted['email'], $row['email'])) {
+ continue;
+ }
+ $rows[] = $decrypted;
+ }
根据您的原始代码的外观,必要的确切代码更改看起来会有所不同。我只是想在这里演示一下结构。
这将允许您将加密数据存储在数据库中仍然在 SQL 查询的 WHERE 子句中使用提供的 name 或 email 参数(带有抽象层)。