# 12.14 加密和压缩函数

表 12.18 加密函数

姓名 描述
AES_DECRYPT() 使用 AES 解密
AES_ENCRYPT() 使用 AES 加密
压缩() 以二进制字符串形式返回结果
MD5() 计算 MD5 校验和
随机字节() 返回一个随机字节向量
SHA1(), 沙() 计算 SHA-1 160 位校验和
SHA2() 计算 SHA-2 校验和
STATEMENT_DIGEST() 计算语句摘要哈希值
STATEMENT_DIGEST_TEXT() 计算规范化语句摘要
解压() 解压缩压缩的字符串
UNCOMPRESSED_LENGTH() 返回压缩前字符串的长度
VALIDATE_PASSWORD_STRENGTH() 确定密码强度

许多加密和压缩函数返回结果可能包含任意字节值的字符串。如果要存储这些结果,请使用带有变量要么斑点二进制字符串数据类型。这避免了尾随空格删除或字符集转换可能会更改数据值的潜在问题,例如,如果您使用非二进制字符串数据类型 (字符,VARCHAR,文本)。

一些加密函数返回 ASCII 字符串:MD5(),沙(),SHA1(),SHA2(),STATEMENT_DIGEST(),STATEMENT_DIGEST_TEXT().它们的返回值是一个字符串,其字符集和排序规则由字符集连接collat​​ion_connection系统变量。这是一个非二进制字符串,除非字符集是二进制.

如果应用程序存储来自函数的值,例如MD5()要么SHA1()返回一串十六进制数字,可以通过使用将十六进制表示转换为二进制来获得更有效的存储和比较十六进制()并将结果存储在二进制(*ñ*)柱子。每对十六进制数字需要一个二进制形式的字节,因此*ñ取决于十六进制字符串的长度。ñ是 16MD5()值和 20 为SHA1()价值。为了SHA2(),ñ*范围从 28 到 32,具体取决于指定结果所需位长的参数。

将十六进制字符串存储在字符如果值存储在使用utf8字符集(每个字符使用 4 个字节)。由于值较大并且需要考虑字符集排序规则,存储字符串还会导致比较慢。

假设一个应用程序存储MD5()a中的字符串值字符(32)柱子:

CREATE TABLE md5_tbl (md5_val CHAR(32), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(MD5('abcdef'), ...);

要将十六进制字符串转换为更紧凑的形式,请修改应用程序以使用十六进制()二进制(16)而是如下:

CREATE TABLE md5_tbl (md5_val BINARY(16), ...);
INSERT INTO md5_tbl (md5_val, ...) VALUES(UNHEX(MD5('abcdef')), ...);

应用程序应该准备好处理非常罕见的情况,即散列函数为两个不同的输入值生成相同的值。使冲突可检测的一种方法是使散列列成为主键。

笔记

MD5 和 SHA-1 算法的漏洞利用已广为人知。您可能希望考虑使用本节中描述的另一种单向加密函数,例如SHA2().

警告

除非使用 SSL 连接,否则作为加密函数参数提供的密码或其他敏感值以明文形式发送到 MySQL 服务器。此外,这些值会出现在它们写入的任何 MySQL 日志中。为了避免这些类型的暴露,应用程序可以在将敏感值发送到服务器之前在客户端加密它们。同样的考虑也适用于加密密钥。为了避免暴露这些,应用程序可以使用存储过程在服务器端加密和解密值。

  • AES_DECRYPT(*crypt_str*,*key_str*[,*初始化向量*])

    此函数使用官方 AES(高级加密标准)算法解密数据。有关详细信息,请参阅AES_ENCRYPT().

    使用的语句AES_DECRYPT()对于基于语句的复制不安全。

  • AES_加密(*str*,*基尤街*[,*初始向量*])

    AES_ENCRYPT()AES_DECRYPT()使用官方AES(高级加密标准)算法(以前称为“Rijndael”)对数据进行加密和解密AES标准允许不同的密钥长度。默认情况下,这些函数使用128位密钥长度实现AES。如下文所述,可以使用196或256位的密钥长度。密钥长度是性能和安全性之间的权衡。

    AES_ENCRYPT()加密字符串*str使用键字符串基尤街并返回包含加密输出的二进制字符串。AES_DECRYPT()解密加密的字符串crypt_街使用键字符串基尤街*并返回原始的纯文本字符串。如果其中一个函数参数为无效的,函数返回无效的.

    这个*strcrypt_街参数可以是任意长度,填充将自动添加到str因此,它是基于块的算法(如AES)所要求的块的倍数。此填充由AES_DECRYPT()作用长度crypt_街*可以使用以下公式计算:

    16 * (trunc(string_length / 16) + 1)
    

    对于128位的密钥长度,将密钥传递给*基尤街*参数是创建一个真正随机的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_街*先把它炒了。本文档以前的版本建议使用前一种方法,但不再推荐使用前一种方法,因为此处显示的示例更安全。

    如果AES_DECRYPT()如果检测到无效数据或不正确的填充,则返回无效的.然而,有可能AES_DECRYPT()退票-无效的值(可能是垃圾),如果输入数据或密钥无效。

    AES_ENCRYPT()AES_DECRYPT()允许控制块加密模式,并采取可选的*初始向量*初始化向量参数:

    • 这个块加密模式系统变量控制基于块的加密算法的模式。其默认值为aes-128-ecb,表示使用128位密钥长度和ECB模式进行加密。有关此变量允许值的说明,请参阅第5.1.8节“服务器系统变量”.

    • 可选的*初始向量*参数为需要它的块加密模式提供初始化向量。

      对于需要可选*初始向量参数,它必须为16字节或更长(超过16字节的字节将被忽略)。如果初始向量*不见了。

      对于不需要*初始向量*,如果指定了,则会忽略它并生成警告。

      可以通过调用随机字节(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                                          |
    +-----------------------------------------------+
    

    下表列出了每个允许的块加密模式,以及是否需要初始化向量参数。

    块加密模式 需要初始化向量
    欧洲央行
    CBC
    CFB1
    CFB8
    CFB128
    OFB

    使用AES_ENCRYPT()AES_DECRYPT()对于基于语句的复制不安全。

    如果AES_ENCRYPT()mysql客户端,二进制字符串使用十六进制表示法显示,具体取决于--二进制为十六进制。有关该选项的更多信息,请参阅第4.5.1节,“mysql——mysql命令行客户端”.

  • 压缩(*字符串压缩*)

    压缩字符串并将结果作为二进制字符串返回。此函数要求MySQL使用压缩库进行编译,例如兹利布。否则,返回值总是无效的。压缩的字符串可以用解压.

    mysql> SELECT LENGTH(COMPRESS(REPEAT('a',1000)));
            -> 21
    mysql> SELECT LENGTH(COMPRESS(''));
            -> 0
    mysql> SELECT LENGTH(COMPRESS('a'));
            -> 13
    mysql> SELECT LENGTH(COMPRESS(REPEAT('a',16)));
            -> 15
    

    压缩字符串内容的存储方式如下:

  • MD5(*str*)

    计算字符串的MD5 128位校验和。该值以32位十六进制数字的字符串形式返回,或无效的如果争论是无效的。例如,返回值可以用作哈希键。请参阅本节开头有关高效存储哈希值的说明。

    返回值是连接字符集中的字符串。

    如果启用FIPS模式,MD5()返回无效的看见第6.8节,“FIPS支持”.

    mysql> SELECT MD5('testing');
            -> 'ae2b1fca515949e5d54fb22b8ed95575'
    

    这是“RSA Data Security,Inc.MD5消息摘要算法”

    请参阅本节开头有关MD5算法的说明。

  • 随机字节(*伦恩*)

    此函数返回一个二进制字符串*伦恩使用SSL库的随机数生成器生成的随机字节。允许值伦恩*范围从1到1024。对于超出该范围的值,将发生错误。

    随机字节()可用于为AES_DECRYPT()AES_ENCRYPT()功能。在这种情况下使用,*伦恩*必须至少16岁。允许使用更大的值,但超过16的字节将被忽略。

    随机字节()生成一个随机值,使其结果不确定性。因此,使用此函数的语句对于基于语句的复制是不安全的。

    如果随机字节()mysql客户端,二进制字符串使用十六进制表示法显示,具体取决于--二进制为十六进制。有关该选项的更多信息,请参阅第4.5.1节,“mysql——mysql命令行客户端”.

  • 沙1(*str*), 沙(*str*)

    计算字符串的SHA-1 160位校验和,如RFC 3174(安全哈希算法)中所述。该值以40个十六进制数字的字符串形式返回,或无效的如果争论是无效的。此函数的一个可能用途是用作哈希键。请参阅本节开头有关高效存储哈希值的说明。SHA()是同义词SHA1().

    返回值是连接字符集中的字符串。

    mysql> SELECT SHA1('abc');
            -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
    

    SHA1()可以被认为是加密技术上更安全的MD5().但是,请参阅本节开头有关MD5和SHA-1算法的说明。

  • 沙2(*str*, *散列长度*)

    计算SHA-2系列散列函数(SHA-224、SHA-256、SHA-384和SHA-512)。第一个参数是要散列的明文字符串。第二个参数表示结果的所需位长度,其值必须为224、256、384、512或0(相当于256)。如果其中一个论点是无效的或者哈希长度不是允许的值之一,则返回值为无效的。否则,函数结果是包含所需位数的哈希值。请参阅本节开头有关高效存储哈希值的说明。

    返回值是连接字符集中的字符串。

    mysql> SELECT SHA2('abc', 224);
            -> '23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7'
    

    只有在MySQL配置了SSL支持的情况下,此功能才起作用。看见第6.3节,“使用加密连接”.

    SHA2()可以被认为比MD5()SHA1().

  • 声明摘要(*陈述*)

    将SQL语句作为字符串,将语句摘要哈希值作为连接字符集中的字符串返回,或无效的如果论点是正确的无效的.相关的声明_摘要_文本()函数返回规范化的语句摘要。有关语句摘要的信息,请参阅第27.10节,“绩效模式声明摘要和抽样”.

    这两个函数都使用MySQL解析器来解析语句。如果解析失败,则会发生错误。只有当语句作为文本字符串提供时,错误消息才会包含解析错误。

    这个最大长度系统变量确定这些函数可用于计算规范化语句摘要的最大字节数。

    mysql> SET @stmt = 'SELECT * FROM mytable WHERE cola = 10 AND colb = 20';
    mysql> SELECT STATEMENT_DIGEST(@stmt);
    +------------------------------------------------------------------+
    | STATEMENT_DIGEST(@stmt)                                          |
    +------------------------------------------------------------------+
    | 3bb95eeade896657c4526e74ff2a2862039d0a0fe8a9e7155b5fe492cbd78387 |
    +------------------------------------------------------------------+
    mysql> SELECT STATEMENT_DIGEST_TEXT(@stmt);
    +----------------------------------------------------------+
    | STATEMENT_DIGEST_TEXT(@stmt)                             |
    +----------------------------------------------------------+
    | SELECT * FROM `mytable` WHERE `cola` = ? AND `colb` = ?  |
    +----------------------------------------------------------+
    
  • 声明摘要文本(*陈述*)

    将SQL语句作为字符串给定,将规范化语句摘要作为连接字符集中的字符串返回,或无效的如果论点是正确的无效的。有关更多讨论和示例,请参阅相关声明(摘要)作用

  • 解压(*string_to_uncompress*)

    Uncompresses a string compressed by theCOMPRESS()function. If the argument is not a compressed value, the result isNULL. This function requires MySQL to have been compiled with a compression library such aszlib. Otherwise, the return value is alwaysNULL.

    mysql> SELECT UNCOMPRESS(COMPRESS('any string'));
            -> 'any string'
    mysql> SELECT UNCOMPRESS('any string');
            -> NULL
    
  • UNCOMPRESSED_LENGTH(*compressed_string*)

    Returns the length that the compressed string had before being compressed.

    mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30)));
            -> 30
    
  • VALIDATE_PASSWORD_STRENGTH(*str*)

    Given an argument representing a plaintext password, this function returns an integer to indicate how strong the password is. The return value ranges from 0 (weak) to 100 (strong).

    Password assessment byVALIDATE_PASSWORD_STRENGTH()is done by thevalidate_passwordcomponent. If that component is not installed, the function always returns 0. For information about installingvalidate_password, seeSection 6.4.3, “The Password Validation Component”. To examine or configure the parameters that affect password testing, check or set the system variables implemented byvalidate_password看见第6.4.3.2节,“密码验证选项和变量”.

    密码将接受越来越严格的测试,返回值反映了哪些测试得到了满足,如下表所示。此外,如果验证密码。检查用户名称系统变量已启用,密码与用户名匹配,验证密码强度()返回0,无论其他验证密码系统变量已设置。

    密码测试 返回值
    长度\<4 0
    长≥ 4和\<验证密码。长 25
    满足政策1(低的) 50
    满足政策2(中等的) 75
    政策3(坚强的) 100