Home  >  Article  >  Database  >  How to correctly use AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption in MySQL

How to correctly use AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption in MySQL

小云云
小云云Original
2018-05-18 17:40:3717307browse

This article mainly introduces you to the correct method of encryption and decryption using AES_ENCRYPT() and AES_DECRYPT() in MySQL. The AES_ENCRYPT('password','key') function in MySQL can encrypt field values. AES_DECRYPT(table's Field name, 'key') function decryption processing, the article gives detailed sample code, friends in need can refer to it, I hope it can help everyone.

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 The error was a 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.

Related recommendations:

How to use OpenSSL instead of Mcrypt encryption and decryption in PHP?

WeChat applet development function introduction and encryption and decryption NODE-UUID introduction

Detailed explanation of PHP data compression, encryption and decryption (pack, unpack)

The above is the detailed content of How to correctly use AES_ENCRYPT() and AES_DECRYPT() for encryption and decryption in MySQL. 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