
Wallpaper Engine:山田凉(山田 リョウ)
前言
前不久遇到有人问我 M 怎么做加密处理,简单聊聊
加密解密函数
首先简单说说加密和解密函数。
AES_ENCRYPT(str,key_str[,init_vector][,kdf_name][,salt][,info | iterations])
具体参考:https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-encrypt
str:需要加密的内容 key_str:加密密钥
其他我们这里没用到不详细描述,都是 KDF 相关的
AES_DECRYPT 类似
AES_DECRYPT(crypt_str,key_str[,init_vector][,kdf_name][,salt][,info | iterations])
crypt_str 是加密后的加密串 key_str:加密密钥
具体参考:https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-decrypt
字段为 VARCHAR 类型
测试表
root@localhost [aes] 18:52:41 > create table encode_1(id int auto_increment primary key,text varchar(200));
Query OK, 0 rows affected (0.25 sec)
插入带密钥的加密数据
root@localhost [aes] 18:53:29 > insert into encode_1 values(2, TO_BASE64(AES_ENCRYPT('需要加密的内容','My KEY')));
Query OK, 1 row affected (0.08 sec)
注意:细心的小伙伴应该看到多了一个 TO_BASE64 函数,这个后面解释
查询时解密
root@localhost [aes] 18:53:37 > select CAST(AES_DECRYPT(FROM_BASE64(text),'My KEY') AS CHAR) from encode_1 where id = 2;
+-------------------------------------------------------+
| CAST(AES_DECRYPT(FROM_BASE64(text),'My KEY') AS CHAR) |
+-------------------------------------------------------+
| 需要加密的内容 |
+-------------------------------------------------------+
1 row in set (0.01 sec)
直接查是加密状态:
root@localhost [aes] 18:53:44 > select * from encode_1;
+----+----------------------------------------------+
| id | text |
+----+----------------------------------------------+
| 2 | WUYLkCqcxHGmlvPoH8xh/MORGcHWTbjcqxhnhi1BOaI= |
+----+----------------------------------------------+
1 row in set (0.00 sec)
给错密钥返回 NULL
root@localhost [aes] 18:53:52 > select CAST(AES_DECRYPT(FROM_BASE64(text),'Other KEY') AS CHAR) from encode_1 where id = 2;
+----------------------------------------------------------+
| CAST(AES_DECRYPT(FROM_BASE64(text),'Other KEY') AS CHAR) |
+----------------------------------------------------------+
| NULL |
+----------------------------------------------------------+
1 row in set (0.00 sec)
ERROR 1366 (HY000): Incorrect string value 解释
如果不用 TO_BASE64 函数会使插入报错以下内容:
root@localhost [aes] 19:09:25 > insert into encode_1 values(3, AES_ENCRYPT('需要加密的内容','My KEY'));
ERROR 1366 (HY000): Incorrect string value: '\x90*\x9C\xC4q\xA6...' for column 'text' at row 1
因为 AES_ENCRYPT()
返回的是二进制数据(VARBINARY),如果字段定义为 VARCHAR
或 CHAR
,MySQL 会尝试将二进制数据转换为字符串,导致字符集冲突产生警告。
我们这里将内容转为 BASE64 就可以存进去了,当然查的时候也要先解开 BASE64 再解密
字段为 VARBINARY 类型
测试表
root@localhost [aes] 19:09:26 > create table encode_2(id int auto_increment primary key,text VARBINARY(200));
Query OK, 0 rows affected (0.12 sec)
VARBINARY 类型就不需要转 BASE64 了,直接插入就可以了,BINARY 表示插入的是 BINARY 字符集串,当然用 CAST(xx as BINARY )
也是一样的
root@localhost [aes] 19:13:34 > insert into encode_2 values(1, BINARY AES_ENCRYPT('需要加密的内容','My KEY'));
Query OK, 1 row affected, 1 warning (0.03 sec)
查询:
root@localhost [aes] 19:13:47 > select CAST(AES_DECRYPT(text,'My KEY') AS CHAR) from encode_2 where id = 1;
+------------------------------------------+
| CAST(AES_DECRYPT(text,'My KEY') AS CHAR) |
+------------------------------------------+
| 需要加密的内容 |
+------------------------------------------+
1 row in set (0.00 sec)
使用其他密钥
root@localhost [aes] 19:14:09 > select CAST(AES_DECRYPT(text,'Other KEY') AS CHAR) from encode_2 where id = 1;
+---------------------------------------------+
| CAST(AES_DECRYPT(text,'Other KEY') AS CHAR) |
+---------------------------------------------+
| NULL |
+---------------------------------------------+
1 row in set (0.00 sec)
直接查询是加密串
root@localhost [aes] 19:14:04 > select text from encode_2 where id = 1;
+--------------------------------------------------------------------+
| text |
+--------------------------------------------------------------------+
| 0x59460B902A9CC471A696F3E81FCC61FCC39119C1D64DB8DCAB1867862D4139A2 |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)
看到字段有个 0x ,一般 0x 是十六进制,用 UNHEX 试一下:
root@localhost [aes] 19:14:13 > select UNHEX(text) from encode_2 where id = 1;
+--------------------------+
| UNHEX(text) |
+--------------------------+
| NULL |
+--------------------------+
1 row in set, 1 warning (0.00 sec)
root@localhost [aes] 19:14:29 > show warnings;
+---------+------+----------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------------------+
| Warning | 1411 | Incorrect string value: '`aes`.`encode_2`.`text`' for function unhex |
+---------+------+----------------------------------------------------------------------+
1 row in set (0.00 sec)
当然不行了
参考
https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-encrypt
https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-decrypt




