繁体   English   中英

搜索加密的 MySQL 数据库

[英]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 子句中提供的nameemail参数(具有抽象层)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM