簡體   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