简体   繁体   中英

Search Encrypted MySQL Database

Assume a MySQL database that has two fields: name and email. Also, assume that both fields need to be securely encrypted at rest due to privacy concerns. And assume that a third field contains a GUID that is the key used to encrypt the name/amail fields. (The third field value is used along with another value as the encryption key to reduce the possibility of having a 'master' key for all encryption. )

The application uses PHP (Version 7.4+) and MySQL.

How would you search the database for a plaintext value (name or email) when the data is encrypted at rest?

Added Data will be encrypted with openssl_encrypt(). (And changed the above to MySQL.)

How would you search the database for a plaintext value (name or email) when the data is encrypted at rest?

You can't do this in general with arbitrarily encrypted data, but a library like CipherSweet make this really easy.

The documentation should help you get the library installed.

To use it, you'll want to first setup a KeyProvider , then create an EncryptedRow object like so:

<?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 */
    )
);

In this example, I added two blind indexes with a size of 16 bits each. This is a fudged number; you'll want to look at blind index planning for which values to use for guidance here.

Now you need to update your code when you read/write data into your MySQL database, using $rowProcessor to transparently encrypt/decrypt your data on-the-fly (in diff format):

 /** @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);

Next, you're going to need to tweak for your lookup logic.

- $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;
+ }

The exact code changes necessary will look different based on whatever your original code looks like. I'm just trying to demonstrate the structure here.

This will allow you to store encrypted data in your database yet still use the provided name or email parameters in the WHERE clause of your SQL queries (with a layer of abstraction).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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