[英]Search Encrypted MySQL Database
假设一个 MySQL 数据库有两个字段:姓名和电子邮件。 此外,假设出于隐私考虑,这两个字段都需要在静态时进行安全加密。 并假设第三个字段包含一个 GUID,它是用于加密 name/amail 字段的密钥。 (第三个字段值与另一个值一起用作加密密钥,以减少所有加密都具有“主”密钥的可能性。)
该应用程序使用 PHP(版本 7.4+)和 MySQL。
当数据静态加密时,您将如何在数据库中搜索明文值(姓名或电子邮件)?
添加的数据将使用 openssl_encrypt() 进行加密。 (并将上述内容更改为 MySQL。)
当数据静态加密时,您将如何在数据库中搜索明文值(姓名或电子邮件)?
你不能用一般的任意加密数据做到这一点,但就像一个图书馆CipherSweet使这很容易。
该文档应该可以帮助您安装库。
要使用它,您需要先设置一个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 位。 这是一个捏造的数字; 您需要在此处查看用于指导的值的盲索引规划。
现在,您需要在将数据读/写到 MySQL 数据库时更新代码,使用$rowProcessor
透明地$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
参数(具有抽象层)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.