开发者

How to encrypt a specific column in a MySQL table?

I am experimenting with creating a simple message system (PHP) page that uses a MySQL table to store the entries. The rough outline of the 开发者_开发知识库columns I'll use in the table are:

msg_id (primary key, auto_increment)

user_id (foreign key pointing to the user who created the message)

time (a DATETIME entry to provide msg timestamps)

msg (a VARCHAR containing the msg)

accessable (just an int(1), 0 means no one except the user himself can read the msg, and 1 means others can read it)

What I'm wondering is, what's the best way to encrypt the msg field so prying eyes can't read it (let's say, by opening the mysql CLI or phpMyAdmin and just read the value stored in a row)?

If "accessable" is set to 0, then only the user him/herself should be able to read it (by accessing some PHP page), but if set to 1, everyone else should be able to read it as well. I don't know how to tackle this, so any help is very appreciated!


Look here for list of possible encryption functions:

http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html

You can create trigger for update and check there field accessable. Something like that:

CREATE TRIGGER crypt_trg BEFORE UPDATE ON table FOR EACH ROW
BEGIN
  IF new.accessable = 0 THEN
    SET new.msg := ENCRYPT(new.msg, 'key');
  ELSE
    SET new.msg := DECRYPT(new.msg, 'key');
  END IF;
END;

You also can update all existing records in you table with this query:

UPDATE table SET msg = IF(accessable = 0, ENCRYPT(msg, 'key'), DECRYPT(msg, 'key'));

So you can select records for you PHP code:

SELECT msg_id, user_id, time, IF(accessable = 0, DECRYPT(msg, 'key'), msg) msg
FROM table

UPD. Also here was similar question:

MySQL encrypted columns


You can also encrypt the data prior to the query to insert it, so that MySQL doesn't even know it's encrypted, and decrypt it on retrieval in the application. For that, you should store it in a varbinary or blob column though.


So I had an idea that might accomplish this, but it's all conceptual.

Suppose that you had the value "Lorem ipsum dolor sit amet", and you wanted to do a search for "lorem". One way is that you could take the original and break it up into chunks (lowercased), and put them in a second table. The whole (original) value is in the original table column with row_id 123, but a new table called "chunks" might have:

row_id | chunk | foreign_row_id
1      | lo    | 123
2      | or    | 123
3      | re    | 123
4      | em    | 123
5      | m     | 123
6      |  i    | 123
7      | ip    | 123

Think of it like a substring index, where every substring is 2 characters long.

Now, when a user wanted to perform a search, you would similarly chunk that up, then do a lookup. If they typed "lo", then you see which foreign row IDs matched. But if they enter "lore", then you do a search for all foreign row IDs that had a matching chunk for "lo", "or", AND "re".

So far, not too practical. However, if the original value "Lorem ipsum dolor sit amet" is encrypted or hashed, then you could ALSO chunk up the 2-char substrings, encrypt/hash them, then do a lookup on the chunks instead or the full string. No decryption or unhashing necessary.

The logic would be:

  1. Chunk the search string
  2. Encrypt/hash each 2-char chunk
  3. Do the lookup and find all encrypted/hashed chunk matches.

Any match can then be fetched from the original table. This would protect the data at rest, because if the chunk table was compromised, they can't do anything with a bunch of encrypted/hashed 2-char values. You can't take 2 encrypted/hashed substrings and recombine them or get anything meaningful from them.

If I am the inventor and got to name this, since it's similar but not quite the same as making a Rainbow Table, I would called this "Fruity Pebbles Tables". Because of the chunks.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜