[英]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.