暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL中的decode()、encode()、AES_ENCRYPT() AES_DECRYPT()

原创 徐佩怡 2020-12-31
7144

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加密解密 - 迷失之路 - 博客园

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论