decode()和encode()官方描述
下面是官网对于decode()和encode()的描述:
DECODE(crypt_str,pass_str)
DECODE()
crypt_str使用pass_str密码解密加密的字符串。
crypt_str应该是从encode()返回的字符串
ENCODE()和DECODE()功能在MySQL 5.7已被取消,并且不应该再被使用。期望在将来的MySQL版本中将其删除。考虑使用AES_ENCRYPT()和
AES_DECRYPT()代替。
ENCODE(str,pass_str)
ENCODE()
ENCODE()将str使用pass_str作为密码进行加密。结果是长度与str相同的二进制字符串。要解密结果,请使用DECODE()
ENCODE()和DECODE()功能在MySQL 5.7已被取消,并且不应该再被使用。期望在将来的MySQL版本中将其删除。考虑使用AES_ENCRYPT()和
AES_DECRYPT()代替。
如果仍需要使用ENCODE(),则必须将其与盐值一起使用以降低风险。
例如:ENCODE(‘cleartext’, CONCAT(‘my_random_salt’,’my_secret_password’))
每当更新密码时,都必须使用新的随机盐值。
AES_ENCRYPT()和 AES_DECRYPT()官方描述
AES_DECRYPT(crypt_str,key_str[,init_vector])
此功能使用官方的AES(高级加密标准)算法解密数据。
使用AES_DECRYPT()的语句对于基于statement的复制是不安全的。
AES_ENCRYPT(str,key_str[,init_vector])
AES_ENCRYPT()和 AES_DECRYPT()实现加密,并使用官方AES(高级加密标准)算法,即以前称为数据的解密“Rijndael算法”。 AES标准允许各种密钥长度。默认情况下,这些功能使用128位密钥长度实现AES。可以使用196或256位的密钥长度,如下所述。密钥长度是性能和安全性之间的折衷。
AES_ENCRYPT()使用key_str对str进行加密,然后返回包含加密输出的二进制字符串。
AES_DECRYPT()使用key_str解密加密的crypt_str的字符串并返回原始的纯文本字符串。如果任一函数参数为NULL,则函数返回 NULL。
str和 crypt_str参数可以是任何长度,并且填充被自动添加到str,所以它是所要求的基于块的算法,如AES的块的倍数。该填充会由该AES_DECRYPT()函数自动删除 。crypt_str的长度可以使用以下公式计算:16 * (trunc(string_length / 16) + 1)
对于128位的密钥长度,将密钥传递给key_str参数的最安全的方法是创建一个真正随机的128位值并将其作为二进制值传递。例如:
INSERT INTO t VALUES (1,AES_ENCRYPT('text',UNHEX('F3229A0B371ED2D9441B830D21A390C3')));
不要将密码或密码直接传递给crypt_str,首先将其哈希
如果 AES_DECRYPT() 检测到无效数据或填充错误,则返回 NULL。但是,如果输入数据或键无效,则可能AES_DECRYPT()返回非NULL值(可能是垃圾)。
AES_ENCRYPT()并 AES_DECRYPT()允许控制块加密模式并采用可选的 init_vector初始化向量参数:
1.所述block_encryption_mode 系统变量控制用于基于块的加密算法的模式。其默认值为 aes-128-ecb,表示使用128位密钥长度和ECB模式进行加密。
2.可选init_vector 参数为需要它的块加密模式提供初始化向量。
对于需要可选init_vector参数的模式 ,它必须为16个字节或更长(超过16个字节的字节将被忽略)。如果init_vector丢失,则会发生错误。
对于不需要的模式 init_vector,将忽略它,并且如果指定了警告,则会生成警告。
可以通过调用生成用于初始化向量的随机字节字符串 RANDOM_BYTES(16)。对于需要初始化向量的加密模式,必须将相同的向量用于加密和解密。
mysql> SET block_encryption_mode = 'aes-256-cbc';
mysql> SET @key_str = SHA2('My secret passphrase',512);
mysql> SET @init_vector = RANDOM_BYTES(16);
mysql> SET @crypt_str = AES_ENCRYPT('text',@key_str,@init_vector);
mysql> SELECT AES_DECRYPT(@crypt_str,@key_str,@init_vector);
+-----------------------------------------------+
| AES_DECRYPT(@crypt_str,@key_str,@init_vector) |
+-----------------------------------------------+
| text |
+-----------------------------------------------+
下表列出了每种允许的块加密模式,支持该模式的SSL库以及是否需要初始化矢量参数。
块加密模式 支持模式的SSL库 需要初始化向量
欧洲央行 OpenSSL,yaSSL 没有
哥伦比亚广播公司 OpenSSL,yaSSL 是
CFB1 OpenSSL 是
CFB8 OpenSSL 是
CFB128 OpenSSL 是
银行 OpenSSL 是
对于基于语句的复制 使用 AES_ENCRYPT()或 AES_DECRYPT()不安全的语句,不能将其存储在查询缓存中。
测试DECODE()和ENCODE()
数据库版本Server version: 5.7.31
加密解密:
##############建表
create table users(
-> username varchar(128), # 用户昵称
-> password blob #密码
-> ) engine=innodb default charset=utf8;
###############插入数据
INSERT INTO users (username, password) VALUES ('john', ENCODE('guessme', 'salt'));
################简单的select * from users;
+----------+----------+
| username | password |
+----------+----------+
| john | ��
>�]� |
+----------+----------+
################解密
(root@localhost) [test] select username, DECODE(password,'salt') as password from users where username = 'john';
+----------+----------+
| username | password |
+----------+----------+
| john | guessme |
+----------+----------+
1 row in set, 1 warning (0.00 sec)
测试aes_encrypt()和aes_decrypt()
aes_encrypt()和aes_decrypt()比encode()和decode()安全性要高。MySQL5.7以上已经不再支持encode()和decode()
##############建表
同样适用decode()事例中的user表
###############插入数据
INSERT INTO users (username, password) VALUES ('steven', aes_encrypt('password', 'salt'));
################简单的select * from users;
+----------+------------------+
| username | password |
+----------+------------------+
| john | ��
>�]� |
| steven | $�b��*K4���H=S |
+----------+------------------+
################解密
select t.username, aes_decrypt(t.password,'salt') as password from users t where t.username = 'steven';
+----------+----------+
| username | password |
+----------+----------+
| steven | password |
+----------+----------+
1 row in set (0.00 sec)
##如果在MySQL workbench中尝试测试,也可以在查询结构的password值上,右键,'open value in viewer'。可以看到text TAB下的密码明文。
总结
ENCODE()和DECODE()是MySQL版本5.7版本之前可以使用,在MySQL8.0之后,MySQL仅支持使用aes_encrypt()和aes_decrypt(),也可以在本文中看出,一张表中是可以存在不同的加密算法。
测试部分的操作步骤来自博客:MySQL加密解密 - 迷失之路 - 博客园