在信息发达的当今,数据安全的重要性不言而喻。比如:身份证,银行卡,名字,电话号码,地址都是重要又敏感的信息。在数据库系统中通过数据加密,以保障数据的安全性。目前软件行业常用的加密算法:MD5、SHA1、SHA2,AES、DES、CAST、IDEA、RC2、RC5 等。这些加密算法的目的在于使别人无法查看加密的数据,并且在需要的时候还可以对数据进行解密来重新查看数据。
在数据库方面,加密不光是隐藏敏感信息,还同时保证存储数据紧凑,不浪费空间。 是一举二得的功能。
MySQL在这方面提供:
MySQL8.0提供的加密函数如下:
Name | Description |
---|---|
AES_ENCRYPT() | 使用AES加密 |
AES_DECRYPT() | 使用AES解密 |
MD5() | 计算MD5校验值 |
RANDOM_BYTES() | 返回随机字节量 |
SHA1(), SHA() | 计算SHA-1 160位校验值 |
SHA2() | 计算SHA-2校验值 |
STATEMENT_DIGEST() | 计算语句摘要哈希值 |
STATEMENT_DIGEST_TEXT() | 转换规范化语句摘要 |
MD5算法是一种哈希算法,也是常用的方式,但这一算法是不可逆的。也就是说,通过哈希算法得到的数据,无法经过任何算法还原回去。
底层处理方式是把数据转换成MD5或SHA1等,之后返回十六进制数字字符串的函数的值,则通过使用UNHEX将十六进制表示转换为二进制并将结果存储在binary(N)列中,可以获得更有效的存储和比较。
每对十六进制数字需要一个二进制形式的字节,因此需要十六进制字符串的长度。
使用场景方面: MD5最常用于加密用户密码,它可以将用户输入的明文密码转换成一个128位的散列值,这个散列值可以用来验证用户输入的密码是否正确,而不必将用户的密码明文存储在服务器上,从而保护用户的密码安全。此外,MD5密码还可以用于文件完整性检查,可以检查文件是否被篡改。
实例:
mysql> CREATE TABLE md5_tbl (md5_val_char CHAR(32),md5_val_bin BINARY(16));
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO md5_tbl (md5_val_char) VALUES(MD5('abcdef'));
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO md5_tbl (md5_val_bin ) VALUES(UNHEX(MD5('abcdef'))) ;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM md5_tbl;
+----------------------------------+------------------------------------+
| md5_val_char | md5_val_bin |
+----------------------------------+------------------------------------+
| e80b5017098950fc58aad83c8c14978e | NULL |
| NULL | 0xE80B5017098950FC58AAD83C8C14978E |
+----------------------------------+------------------------------------+
备注:
除非使用SSL连接,否则作为加密函数参数提供的密码或其他敏感值将以明文形式发送到MySQL服务器。此外,这些值会出现在所写入的任何MySQL日志。
MD5还是可以破解的。 可以把提交的MD5密码与lib库中的MD5密码进行比对,如果有相同的,就可以获取到正确的密码(穷举法)。目前最简单、常见的破解方式当属字典破解(Dictionary Attack)和暴力破解(Brute Force Attack)方式。这种方式非常耗时,效率比较低。还可以采用一种更高效的破解方式,查表法(Lookup Tables),逆向查表法(Reverse Lookup Tables)、彩虹表(Rainbow Tables)等
在MySQL里官方使用AES(高级加密标准)算法对数据进行解密。提供AES_ENCRYPT和AES_DECRYPT函数。通过使用默认128位密钥长度实现AES。可以使用196或256位的密钥长度。长度是性能和安全性之间的权衡。
mysql> show variables like '%block_encryption_mode%';
+-----------------------+-------------+
| Variable_name | Value |
+-----------------------+-------------+
| block_encryption_mode | aes-128-ecb |
+-----------------------+-------------+
1 row in set (0.00 sec)
#AES加密函数使用256位的密钥长度和CBC模式
mysql> SET GLOBAL block_encryption_mode='aes-256-cbc';
实例:
AES_DECRYPT(crypt_str,key_str[,init_vector][,kdf_name][,salt][,info | iterations])
AES_ENCRYPT(str,key_str[,init_vector][,kdf_name][,salt][,info | iterations])
实例:
mysql> CREATE TABLE aes_tbl (aes_val varchar(256)) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
Query OK, 0 rows affected (0.02 sec)
#加密插入
mysql> INSERT INTO aes_tbl VALUES(aes_encrypt('abcd','paw123456'));
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM aes_tbl;
+----------------------------+
| aes_val |
+----------------------------+
| ùpñU!㿧ҟWHƒôò |
+----------------------------+
1 row in set (0.00 sec)
#AES_DECRYPT解密,秘钥错误返回NULL
mysql> SELECT AES_DECRYPT(aes_val,'123456') FROM aes_tbl;
+-------------------------------+
| AES_DECRYPT(aes_val,'123456') |
+-------------------------------+
| NULL |
+-------------------------------+
1 row in set (0.00 sec)
mysql> SELECT AES_DECRYPT(aes_val,'paw123456') FROM aes_tbl;
+----------------------------------------------------------+
| AES_DECRYPT(aes_val,'test') |
+----------------------------------------------------------+
| 0x62 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
此函数返回使用SSL库的随机数生成器生成的len随机字节的二进制字符串。允许的len值范围为1到1024。对于超出该范围的值,将发生错误。如果len为NULL,则返回NULL。
组合使用方式【推荐这种用法】:
mysql> SET @init_vector = RANDOM_BYTES(16); -- 随机的salt
Query OK, 0 rows affected (0.00 sec)
mysql> SET @key = SHA2('secret key', 224);
Query OK, 0 rows affected (0.00 sec)
mysql> SET @crypto = AES_ENCRYPT('abcd', @key, @init_vector);
Query OK, 0 rows affected, 2 warnings (0.00 sec)
mysql> SELECT @crypto;
+------------------+
| @crypto |
+------------------+
| ?¯rZªտXPÝdG2 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT AES_DECRYPT(@crypto, @key, @init_vector);
+-----------------------------------+
| AES_DECRYPT(@crypto, @key, @salt) |
+-----------------------------------+
| abcd |
+-----------------------------------+
1 row in set, 1 warning (0.00 sec)
计算字符串的SHA-1 160位校验.SHA与SHA1一样。可以被视为与MD5在密码学上更安全的等价。
mysql> SELECT SHA1('abc');
+------------------------------------------+
| SHA1('abc') |
+------------------------------------------+
| a9993e364706816aba3e25717850c26c9cd0d89d |
+------------------------------------------+
1 row in set (0.00 sec)
计算SHA-2系列哈希函数(SHA-224、SHA-256、SHA-384和SHA-512)。
#1.这里第二个参数指示结果所需的比特长度,其值必须为224、256、384、512或0(相当于256)
mysql> SELECT SHA2('abc', 224);
+----------------------------------------------------------+
| SHA2('abc', 224) |
+----------------------------------------------------------+
| 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
#2.如果参数为NULL或哈希长度不是允许的值之一,则返回值为NULL。
mysql> SELECT SHA2('abc', NULL);
+-------------------+
| SHA2('abc', NULL) |
+-------------------+
| NULL |
+-------------------+
1 row in set, 1 warning (0.00 sec)
仅当MySQL配置了SSL支持时,此函数才起作用。SHA2可以被认为比MD5和SHA1更安全。
语句摘要转换功能。ps库的events_statements_summary_by_digest表就是通过这个函数实现的。
实例
mysql> SELECT STATEMENT_DIGEST("SELECT * FROM test WHERE ID=1;");
+------------------------------------------------------------------+
| STATEMENT_DIGEST("SELECT * FROM test WHERE ID=1;") |
+------------------------------------------------------------------+
| c4af45cba988541e319888c1bd5d79db763895a68320e5cce65e3b7e8547f919 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT STATEMENT_DIGEST("SELECT * FROM test WHERE ID=5;");
+------------------------------------------------------------------+
| STATEMENT_DIGEST("SELECT * FROM test WHERE ID=5;") |
+------------------------------------------------------------------+
| c4af45cba988541e319888c1bd5d79db763895a68320e5cce65e3b7e8547f919 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=5;");
+---------------------------------------------------------+
| STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=5;") |
+---------------------------------------------------------+
| SELECT * FROM `test` WHERE `ID` = ? ; |
+---------------------------------------------------------+
1 row in set (0.00 sec)
注意,这个STATEMENT_DIGEST_TEXT函数必须在任一个库里面执行,如果没有use切换到库里,会报错,如下:
[(none)]> select STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=5;");
ERROR 3676 (HY000): Could not parse argument to digest function: "No database selected".
这个函数有点意思,基本上和 pt-fingerprint 的功能类似了。(实际测试了下,单线程下还是pt-fingerprint更快些)
如果我们只要在外面套一层md5就可以提取到指纹。
mysql> select md5(STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=5;"));
+--------------------------------------------------------------+
| md5(STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=5;")) |
+--------------------------------------------------------------+
| 46fd7000ad7d8b43806424d56ea0bc5a |
+--------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select md5(STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=323;"));
+----------------------------------------------------------------+
| md5(STATEMENT_DIGEST_TEXT("SELECT * FROM test WHERE ID=323;")) |
+----------------------------------------------------------------+
| 46fd7000ad7d8b43806424d56ea0bc5a |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT STATEMENT_DIGEST('CALL abc()');
+------------------------------------------------------------------+
| STATEMENT_DIGEST('CALL abc()') |
+------------------------------------------------------------------+
| b356ecfb586e0a761b9794bcb6d2e4395d40416f3110e688084bd67e87d27ae9 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT STATEMENT_DIGEST('SELECT abc()');
+------------------------------------------------------------------+
| STATEMENT_DIGEST('SELECT abc()') |
+------------------------------------------------------------------+
| 0af0d93da64f52e740489a7bcd409469011ba78238c29facf60763264b64727e |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT STATEMENT_DIGEST('SELECT NOW()');
+------------------------------------------------------------------+
| STATEMENT_DIGEST('SELECT NOW()') |
+------------------------------------------------------------------+
| 2fad55a506c3342fe82629447a3412f5dfb1aaaa20b13be45f1b9c42175da923 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
网络时代,是信息极为丰富的时代,也是信息泡沫的泛滥,安全极度匮乏。数据库安全加密解密机制,不可缺少。除此之外,加密解密也是消耗一定的性能的,起码aes加解密性能损失大约10%~25%。 合理使用,才是DBA运营之道。
https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。