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

MySQL的函数和运算符 - 加密和压缩函数(1)

数据库杂货铺 2021-07-26
776
加密和压缩函数
 
名称
介绍
AES_DECRYPT()
使用 AES 解密
AES_ENCRYPT()
使用 AES 加密
COMPRESS()
以二进制字符串形式返回结果
MD5()
计算MD5校验和
RANDOM_BYTES()
返回随机字节向量
SHA1(),SHA()
计算 SHA-1 160 位校验和
SHA2()
计算 SHA-2 校验和
STATEMENT_DIGEST()
计算语句摘要哈希值
STATEMENT_DIGEST_TEXT()
计算规范化语句摘要
UNCOMPRESS()
解压压缩的字符串
UNCOMPRESSED_LENGTH()
返回压缩前字符串的长度
VALIDATE_PASSWORD_STRENGTH()
确定密码强度
 
许多加密和压缩函数返回的字符串的结果可能包含任意字节的值。如果希望存储这些结果,请使用 VARBINARY BLOB 二进制字符串数据类型的列。这避免了可能会改变数据值的尾随空格或字符集转换的潜在问题,比如使用非二进制字符串数据类型(CHARVARCHARTEXT)时可能发生的问题。
 
一些加密函数返回 ASCII 字符字符串:MD5()SHA()SHA1()SHA2()STATEMENT_DIGEST()STATEMENT_DIGEST_TEXT()。它们的返回值是一个字符串,该字符串具有由 character_set_connection collation_connection 系统变量决定的字符集和排序规则。这是非二进制字符串,除非字符集是 binary
 
如果应用程序存储 MD5() SHA1() 等返回十六进制数字字符串函数的值,可以通过使用 UNHEX() 将十六进制表示转换为二进制并将结果存储在 BINARY(N) 列中,从而获得更有效的存储和进行比较。每一对十六进制数字表示成二进制形式需要一个字节,所以 N 的值取决于十六进制字符串的长度。对于 MD5() 值,N  16,对于 SHA1() N  20。对于 SHA2()N 的范围是 28 32,具体取决于参数指定的对结果的期望位长。
 
CHAR 列中存储十六进制字符串的空间消耗至少为2倍,如果值存储在使用utf8字符集的列中(其中每个字符使用4个字节),则最多为8倍。存储字符串还会导致比较较缓慢,因为值较大,并且需要考虑字符集排序规则。
 
假设应用程序在 CHAR(32) 列中存储 MD5() 字符串值:
 
    CREATE TABLE md5_tbl (md5_val CHAR(32), ...);
    INSERT INTO md5_tbl (md5_val, ...) VALUES(MD5('abcdef'), ...);
     
    要将十六进制字符串转换为更紧凑的形式,请修改应用程序,使用 UNHEX() BINARY(16),如下所示:
     
      CREATE TABLE md5_tbl (md5_val BINARY(16), ...);
      INSERT INTO md5_tbl (md5_val, ...) VALUES(UNHEX(MD5('abcdef')), ...);
       
      应用程序应该准备好处理非常罕见的情况,即哈希函数为两个不同的输入值生成相同的值。一种检测冲突的方法是使哈希列成为主键。
       
      注意
       
      MD5SHA-1算法的利用已经为人所知。您可能希望考虑使用本节中描述的其他单向加密函数,例如 SHA2()
       
      当心
       
      除非使用SSL连接,否则作为参数提供给加密函数的密码或其他敏感值将以明文形式发送到 MySQL 服务器。同样,这些值也会出现在所写入的任何 MySQL 日志中。为了避免这类情况信息的暴露,应用程序可以在将敏感值发送到服务器之前在客户端加密它们。同样的考虑也适用于加密密钥。为了避免公开这些值,应用程序可以使用存储过程在服务器端对值进行加密和解密。
       
      ● AES_DECRYPT(crypt_str,key_str[,init_vector])
       
      该函数使用官方的 AES(高级加密标准)算法解密数据。
       
      使用 AES_DECRYPT() 的语句对于基于语句的复制是不安全的。
       
      ● 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')));
           
          可以通过哈希密码短语生成 AES 密钥。例如:
           
            INSERT INTO t
            VALUES (1,AES_ENCRYPT('text', UNHEX(SHA2('My secret passphrase',512))));
             
            不要直接将密码或密码短语传递给 crypt_str,先对其进行哈希求值。本文档的以前版本建议使用前一种方法,但现在不再推荐使用,因为这里显示的示例更安全。
             
            如果 AES_DECRYPT() 检测到无效数据或不正确的填充,它将返回 NULL。但是,如果输入数据或密钥无效,则 AES_DECRYPT() 可能返回一个非 NULL (可能是垃圾值)
             
            AES_ENCRYPT() AES_DECRYPT() 允许控制块加密模式,并接受一个可选的 init_vector 初始化向量参数:
             
            ■ block_encryption_mode 系统变量控制基于块的加密算法的模式。默认值为 aes-128-ecb,表示采用128位密钥长度的ECB模式加密。
             
            ■ 可选的 init_vector 参数为需要它的块加密模式提供了一个初始化向量。
             
            对于需要可选 init_vector 参数的模式,它必须为16字节或更长的字节(超过16的字节将被忽略)。如果缺少 init_vector,则会发生错误。
             
            对于不需要 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 |
              +-----------------------------------------------+
               
              下表列出了允许的块加密模式以及是否需要初始化向量参数。
               
              块加密模式
              是否需要初始向量
              ECB
              No
              CBC
              Yes
              CFB1
              Yes
              CFB8
              Yes
              CFB128
              Yes
              OFB
              Yes
               
              使用 AES_ENCRYPT() AES_DECRYPT() 的语句对于基于语句的复制是不安全的。
               
              如果从 mysql 客户端中调用 AES_ENCRYPT(),则二进制字符串将使用十六进制表示法显示,具体取决于 --binary-as-hex 的值。
               
               
               
               
               
              官方文档:
              https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html
              文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论