简体   繁体   中英

Best way to search encrypted data inside MySQL

I am encrypting using PHP before saving the encrypted data to MySQL. I am convinced this is a better way in the long run vs using MySQL's AES_* functions.

My question now is, is there an efficient way to search encrypted data aside from storing a searchable hashed version of the data? Eg, Two columns per data: first_name_encrypted, first_name_hashed.

$hashed_search = myhash('John');    
$q = "SELECT * FROM table WHERE first_name_hashed = '$hashed_search'";

This is what I do now, is there a better way?

My question now is, is there an efficient way to search encrypted data aside from storing a searchable hashed version of the data? Eg, Two columns per data: first_name_encrypted, first_name_hashed.

Close, but no cigar. See: How to search encrypted information with a blind index .

One example, using an authenticated encryption library instead of just using MySQL's built-in AES_*() features:

$first_name_hash = hash_hmac('sha256', $firstName, $secretKey);
$stmt = $db->prepare('SELECT * FROM table WHERE first_name_idx = ?');
$result = $db->execute([$first_name_hash])
    ->fetch(PDO::FETCH_ASSOC);
if ($result) {
    $first_name = Crypto::decrypt($result['first_name_encrypted'], $otherSecretKey);
}

A blind index based on HMAC-SHA256 is preferable to a simple hash.

Also: Use authenticated encryption. This is not negotiable.

Generally you shouldn't be encrypting data stored in a database that you need to search over.

In your example you give, it would be helpful to know the context of why you are grabbing a user by first name, and what your overall security concerns are...

$hashed_search = myhash('John');    
$q = 'SELECT * FROM table WHERE first_name_hashed = '.$hashed_search;

Is this a web app and your main concern is unencrypted transmission of a user's personal info over the network? Use an encrypted connection when sending data between the user's PC and the server (eg 'https').

Is your concern someone hacking the server and downloading a copy of the database? Consider limiting the amount of personally identifying info you are storing. Do you really need to store a user's real name?

Assuming you DO need to store personally identifying information about a user, consider using other methods to fetch their records from the database than using the personally identifying parts (ie don't grab them by 'first_name'). Consider grabbing a user by ID or by a Username that can be unrelated to their real names. This will allow you to make use of Indexing for fast retrieval of records and you can encrypt their personal info (first name, last name, email, phone #, etc) to your heart's content.

If this doesn't help you, maybe provide some more context about what you're trying to accomplish and why.

TLDR: Trying to search over encrypted data is a bad idea. Think of what problem you're trying to avoid and come up with an alternate solution.

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