扩展 MySQL 8.0  / 第 4 章 MySQL 插件 API  / 4.4 编写插件  / 4.4.9 编写认证插件  /  6.4.1.4 SHA-256 可插入认证

6.4.1.4 SHA-256 可插入认证

MySQL 提供了一个身份验证插件,它为用户帐户密码实现 SHA-256 散列。

重要的

要使用通过插件进行身份验证的帐户连接到服务器sha256_password,您必须使用 TLS 连接或支持使用 RSA 密钥对交换密码的未加密连接,如本节后面所述。无论哪种方式,使用该 sha256_password插件都要求 MySQL 具有 SSL 功能。请参阅 第 6.3 节,“使用加密连接”

下表显示了服务器端和客户端的插件名称。

表 6.10 用于 SHA-256 身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件 sha256_password
客户端插件 sha256_password
库文件 无(内置插件)

以下部分提供特定于 SHA-256 可插入身份验证的安装和使用信息:

有关 MySQL 中可插入身份验证的一般信息,请参阅第 6.2.11 节,“可插入身份验证”

安装 SHA-256 可插拔身份验证

sha256_password插件以服务器和客户端形式存在:

  • 服务器端插件内置于服务器中,无需显式加载,也无法通过卸载来禁用。

  • 客户端插件内置于 libmysqlclient客户端库中,可用于链接到 libmysqlclient.

使用 SHA-256 可插拔身份验证

要设置使用 sha256_password插件进行 SHA-256 密码散列的帐户,请使用以下过程。

  1. 创建帐户并指定它使用sha256_password插件进行身份验证:

    CREATE USER 'sha256user'@'localhost' IDENTIFIED WITH sha256_password;
  2. old_passwords 系统变量设置为 2,使 PASSWORD()函数使用密码字符串的 SHA-256 哈希,然后设置帐户密码:

    SET old_passwords = 2;
    SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('password');

服务器将sha256_password 插件分配给帐户并使用它使用 SHA-256 加密密码,将这些值存储 在系统表 的pluginauthentication_string列中 。mysql.user

前面的说明并不假定这 sha256_password是默认的身份验证插件。如果sha256_password 是默认身份验证插件, CREATE USER则可以使用更简单的语法。

要将默认身份验证插件设置为启动服务器sha256_password,请将这些行放在服务器选项文件中:

[mysqld]
default-authentication-plugin=sha256_password

这会导致该sha256_password插件默认用于新帐户。因此,可以在不显式命名插件的情况下创建帐户并设置其密码:

CREATE USER 'sha256user'@'localhost' IDENTIFIED BY 'password';

default-authentication-plugin 设置为的 另一个结果 是,要使用一些其他插件来创建帐户,您必须在语句中 sha256_password明确指定该插件,然后在使用设置帐户密码之前为该插件适当设置。例如,要使用该插件,请执行以下操作: CREATE USERold_passwordsSET PASSWORDmysql_native_password

CREATE USER 'nativeuser'@'localhost' IDENTIFIED WITH mysql_native_password;
SET old_passwords = 0;
SET PASSWORD FOR 'nativeuser'@'localhost' = PASSWORD('N@tivePa33');

要为使用该插件进行身份验证的任何帐户设置或更改密码sha256_password ,请确保 old_passwords在使用之前 的值为 2 SET PASSWORD。如果 old_passwords值为 2 以外的值,则尝试设置密码时会发生错误:

mysql> SET old_passwords = 0;
mysql> SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('password');
ERROR 1827 (HY000): The password hash doesn't have the expected format.
Check if the correct password algorithm is being used with the
PASSWORD() function.

有关 old_passwords和 的更多信息PASSWORD(),请参阅 第 5.1.7 节,“服务器系统变量”第 12.14 节,“加密和压缩函数”

可以使用 OpenSSL 或 yaSSL 编译 MySQL(请参阅 第 6.3.4 节,“SSL 库相关功能”)。该 sha256_password插件适用于使用任一包编译的发行版,但如果 MySQL 是使用 OpenSSL 编译的,则sha256_password 支持使用 RSA 加密。(要启用此功能,您必须遵循本节后面给出的 RSA 配置过程。)

笔记

仅在 MySQL 5.6.46 之前,可以使用 yaSSL 作为 OpenSSL 的替代方案来编译 MySQL。从 MySQL 5.6.46 开始,删除了对 yaSSL 的支持,所有 MySQL 构建都使用 OpenSSL。

RSA 支持具有以下特征:

  • 在服务器端,两个系统变量命名 RSA 私钥和公钥对文件: sha256_password_private_key_pathsha256_password_public_key_path. 如果要使用的密钥文件的名称与系统变量默认值不同,则数据库管理员必须在服务器启动时设置这些变量。

  • 状态变量显示身份验证插件 使用 的Rsa_public_key RSA 公钥值。sha256_password

  • 拥有 RSA 公钥的客户端可以在连接过程中与服务器进行基于 RSA 密钥对的密码交换,如后所述。

  • 对于使用基于 RSA 公钥对的密码交换进行身份验证的帐户的连接 sha256_password,服务器会根据需要将 RSA 公钥发送到客户端。但是,如果客户端主机上有公钥副本,则客户端可以使用它来保存客户端/服务器协议中的往返:

    • 对于这些命令行客户端,使用 --server-public-key-path 选项指定 RSA 公钥文件: mysqlmysqltest

    • 对于使用 C API 的程序,调用 以通过传递选项和文件名 mysql_options()来指定 RSA 公钥 文件。MYSQL_SERVER_PUBLIC_KEY

    • 对于副本,基于 RSA 密钥对的密码交换不能用于连接到使用 sha256_password插件进行身份验证的帐户的源服务器。对于此类帐户,只能使用安全连接。

对于使用该sha256_password 插件的客户端,在连接到服务器时,密码永远不会以明文形式公开。密码传输的方式取决于是否使用安全连接或 RSA 加密:

  • 如果连接是安全的,则不需要 RSA 密钥对,也不会使用它。这适用于使用 TLS 加密的连接。密码以明文形式发送,但不能被窥探,因为连接是安全的。

    笔记

    sha256_password不将共享内存连接视为安全的,即使默认情况下共享内存传输是安全的。

  • 如果连接不安全,并且有 RSA 密钥对可用,连接将保持未加密状态。这适用于未使用 TLS 加密的连接。RSA 仅用于客户端和服务器之间的密码交换,以防止密码窥探。当服务器收到加密的密码时,它会对其进行解密。在加密中使用加扰来防止重复攻击。

  • 如果未使用安全连接且 RSA 加密不可用,则连接尝试会失败,因为如果不以明文形式公开密码,则无法发送密码。

如前所述,只有在使用 OpenSSL 编译 MySQL 时,RSA 密码加密才可用。使用 yaSSL 编译的 MySQL 发行版的含义是,要使用 SHA-256 密码,客户端必须使用加密连接来访问服务器。请参阅 第 6.3.1 节,“配置 MySQL 以使用加密连接”

笔记

要使用 RSA 密码加密 sha256_password,客户端和服务器都必须使用 OpenSSL 进行编译,而不仅仅是其中之一。

假设 MySQL 是使用 OpenSSL 编译的,使用以下过程可以在客户端连接过程中使用 RSA 密钥对进行密码交换:

  1. 使用第 6.3.3 节“创建 SSL 和 RSA 证书和密钥” 中的说明创建 RSA 私钥和公钥对文件。

  2. 如果私钥文件和公钥文件位于数据目录中,并命名为 private_key.pemand public_key.pemsha256_password_private_key_pathsha256_password_public_key_path 系统变量的默认值),服务器会在启动时自动使用它们。

    否则,要显式命名密钥文件,请将系统变量设置为服务器选项文件中的密钥文件名。如果文件位于服务器数据目录中,则无需指定它们的完整路径名:

    [mysqld]
    sha256_password_private_key_path=myprivkey.pem
    sha256_password_public_key_path=mypubkey.pem

    如果密钥文件不在数据目录中,或者要使其在系统变量值中的位置明确,请使用完整路径名:

    [mysqld]
    sha256_password_private_key_path=/usr/local/mysql/myprivkey.pem
    sha256_password_public_key_path=/usr/local/mysql/mypubkey.pem
  3. 重新启动服务器,然后连接到它并检查 Rsa_public_key状态变量值。该值与此处显示的不同,但应该是非空的:

    mysql> SHOW STATUS LIKE 'Rsa_public_key'\G
    *************************** 1. row ***************************
    Variable_name: Rsa_public_key
            Value: -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6
    MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa
    aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ
    g8aV7EtKwyhHb0c30QIDAQAB
    -----END PUBLIC KEY-----

    如果该值为空,则服务器发现密钥文件存在问题。检查错误日志以获取诊断信息。

使用 RSA 密钥文件配置服务器后,使用插件进行身份验证的帐户可以 sha256_password选择使用这些密钥文件连接到服务器。如前所述,此类帐户可以使用安全连接(在这种情况下不使用 RSA)或使用 RSA 执行密码交换的未加密连接。假设使用未加密的连接。例如:

$> mysql --ssl-mode=DISABLED -u sha256user -p
Enter password: password

对于 的这次连接尝试sha256user,服务器确定它sha256_password 是适当的身份验证插件并调用它(因为那是当时指定的插件 CREATE USER)。该插件发现连接未加密,因此要求使用 RSA 加密传输密码。在这种情况下,插件将 RSA 公钥发送给客户端,客户端使用它来加密密码并将结果返回给服务器。插件使用服务器端的RSA私钥解密密码,根据密码是否正确接受或拒绝连接。

服务器根据需要将 RSA 公钥发送给客户端。但是,如果客户端有一个文件包含服务器所需的 RSA 公钥的本地副本,它可以使用以下 --server-public-key-path选项指定该文件:

$> mysql --ssl-mode=DISABLED -u sha256user -p --server-public-key-path=file_name
Enter password: password

选项命名的文件中 的公钥值应与 系统变量--server-public-key-path命名的服务器端文件中的密钥值相同 。sha256_password_public_key_path如果密钥文件包含有效的公钥值但该值不正确,则会发生拒绝访问错误。如果密钥文件不包含有效的公钥,则客户端程序无法使用它。在这种情况下, sha256_password插件将公钥发送给客户端,就好像没有 --server-public-key-path指定任何选项一样。

客户端用户可以通过两种方式获取RSA公钥:

  • 数据库管理员可以提供公钥文件的副本。

  • 可以通过其他方式连接到服务器的客户端用户可以使用SHOW STATUS LIKE 'Rsa_public_key'语句并将返回的键值保存在文件中。