Home  >  Article  >  Database  >  Example of how MySQL uses AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption

Example of how MySQL uses AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption

黄舟
黄舟Original
2018-05-18 16:55:462843browse

The AES_ENCRYPT ('password', 'key') function in MySQL can encrypt field values, and the AES_DECRYPT (field name of the table, 'key') function can decrypt the value. The following article mainly introduces you to MySQL. The correct method of encryption and decryption using AES_ENCRYPT() and AES_DECRYPT() is given in the article. Friends in need can refer to it.

Preface

I recently encountered a requirement at work: I need to use the AES_ENCRYPT() function The plaintext was encrypted and stored in MySQL, but some problems were encountered... Let's introduce it in detail below.

It is said that the encrypted ciphertext will be NULL after decryption.

took a look and found the table structure she sent:

# After looking at it, she encrypted one through the AES_DECRYPT() function string, and then insert it. After successful execution, a warning is displayed: <br>

Query OK, 1 row affected, 1 warning (0.00 sec)

(no error but warning, probably because of sql_mode)

At this time, she ignored the warning, and after decrypting it through AES_DECRYPT(), she found that the plaintext taken out was NULL.

Looking back at the table structure, we found that its field attribute is "varchar" && and the character set is ut8. The warning is as follows:

mysql> show warnings;
+---------+------+------------------------------------------------------------------------+
| Level | Code | Message        |
+---------+------+------------------------------------------------------------------------+
| Warning | 1366 | Incorrect string value: &#39;\xE3f767\x12...&#39; for column &#39;passwd&#39; at row 1 |
+---------+------+------------------------------------------------------------------------+
1 row in set (0.00 sec)

Checked it Document, take a look at the use of these two functions:

-- 将&#39;hello world&#39;加密,密钥为&#39;key&#39;,加密后的串存在@pass中
mysql> SET @pass=AES_ENCRYPT(&#39;hello world&#39;, &#39;key&#39;); 
Query OK, 0 rows affected (0.00 sec)

-- 看一下加密后串的长度(都为2的整数次方)
mysql> SELECT CHAR_LENGTH(@pass);
+--------------------+
| CHAR_LENGTH(@pass) |
+--------------------+
| 16   |
+--------------------+
1 row in set (0.00 sec)

-- 使用AES_DECRYPT()解密
mysql> SELECT AES_DECRYPT(@pass, &#39;key&#39;);
+---------------------------+
| AES_DECRYPT(@pass, &#39;key&#39;) |
+---------------------------+
| hello world  |
+---------------------------+
1 row in set (0.00 sec)

So how to save it?

Method ①:

Set the field attributes to varbinary/binary/four blob types, and other binary field attributes.

Create three fields with attributes varbinary, binary, and blob.

Encrypt 'plaintext1', 'text2', 'plaintext_text3' with the key key and store them in the table.

Finally take it out.

mysql> CREATE TABLE t_passwd (pass1 varbinary(16), pass2 binary(16), pass3 blob);
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t_passwd VALUES (AES_ENCRYPT(&#39;明文1&#39;, &#39;key&#39;), AES_ENCRYPT(&#39;text2&#39;, &#39;key&#39;), AES_ENCRYPT(&#39;明文_text3&#39;, &#39;key&#39;)); 
Query OK, 1 row affected (0.01 sec)
mysql> SELECT AES_DECRYPT(pass1, &#39;key&#39;), AES_DECRYPT(pass2, &#39;key&#39;), AES_DECRYPT(pass3, &#39;key&#39;) FROM t_passwd;
+---------------------------+---------------------------+---------------------------+
| AES_DECRYPT(pass1, &#39;key&#39;) | AES_DECRYPT(pass2, &#39;key&#39;) | AES_DECRYPT(pass3, &#39;key&#39;) |
+---------------------------+---------------------------+---------------------------+
| 明文1   | text2   | 明文_text3   |
+---------------------------+---------------------------+---------------------------+
1 row in set (0.00 sec)

Of course, the length in the attribute brackets depends on the length of the plaintext. The plaintext here is shorter, so only 16 is given.

Method 2:

Convert the ciphertext to hexadecimal and then store it in the varchar/char column.

Here you need to use HEX() to deposit, and use UNHEX() to withdraw.

Create a field with a string attribute.

Encrypt 'hello world' with AES using the key 'key2', and then hexadecimalize the encrypted string through the HEX function.

Finally, take out the encrypted string through UNHEX, and then decrypt it through the AES key 'key2':

mysql> CREATE TABLE t_passwd_2(pass1 char(32));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t_passwd_2 VALUES (HEX(AES_ENCRYPT(&#39;hello world&#39;, &#39;key2&#39;)));
Query OK, 1 row affected (0.00 sec)
mysql> SELECT AES_DECRYPT(UNHEX(pass1), &#39;key2&#39;) FROM t_passwd_2; 
+-----------------------------------+
| AES_DECRYPT(UNHEX(pass1), &#39;key2&#39;) |
+-----------------------------------+
| hello world   |
+-----------------------------------+
1 row in set (0.00 sec)

Similarly, depending on the length of the plaintext, the AES_ENCRYPT encrypted string The string length will also change, so the string length after HEX will also change.
In actual use, a reasonable value needs to be evaluated based on the business.

Method ③:

is stored directly in varchar without hexadecimal conversion.

Going back to the beginning of the problem, it is not possible to store the encrypted string in the utf8 character set and the attribute is varchar.

In fact, just change the character set to latin1:

The warning will not be reported when inserting.

mysql> CREATE TABLE t_passwd_3(pass varchar(32)) CHARSET latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t_passwd_3 SELECT AES_ENCRYPT(&#39;text&#39;, &#39;key3&#39;);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> SELECT AES_DECRYPT(pass, &#39;key3&#39;) FROM t_passwd_3;
+---------------------------+
| AES_DECRYPT(pass, &#39;key3&#39;) |
+---------------------------+
| text   |
+---------------------------+
1 row in set (0.00 sec)

Although this method is beautiful, it only needs to set the field character set to latin1, but it may bring hidden dangers:

The document writes this sentence:

Many encryption and compression functions return strings for which the result might contain arbitrary byte values. If you want to store these results, use a column with a VARBINARY or BLOB binary string data type. This will avoid potential problems with trailing space removal or character set conversion that would change data values, such as may occur if you use a nonbinary string data type (CHAR, VARCHAR, TEXT).

The general idea is that if you use method ③ , directly storing the encrypted string into the char/varchar/text type, which may have potential effects when converting characters or when spaces are deleted.

So if it must be stored in char/varchar/text, then refer to method ② and hexadecimalize it.

Or like method ①, store it directly in the binary field.

Summarize

The above is the detailed content of Example of how MySQL uses AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn