Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  General-Purpose Keyring Key-Management Functions

8.4.4.12 通用密钥环密钥管理功能

MySQL Server 支持一个密钥环服务,允许内部组件和插件安全地存储敏感信息,以便后续检索。

MySQL Server 还包括了 SQL 接口来管理密钥环密钥,这个接口实现为一组通用函数,它们访问由内部密钥环服务提供的功能。这些函数包含在一个插件库文件中,该文件还包含一个keyring_udf插件,需要在函数调用前启用该插件。为了使用这些函数,需要启用一个密钥环插件,如keyring_okv

以下描述的函数是通用的,旨在与任何密钥环插件一起使用。某个密钥环插件可能具有自己特定的函数,旨在与该插件一起使用;见第8.4.4.13节,“Plugin- Specific Keyring Key-Management Functions”

以下部分提供了密钥环函数的安装说明和示例,用于演示如何使用它们。关于这些函数所调用的密钥环服务函数,请见第7.6.9.2节,“The Keyring Service”。关于通用密钥环信息,请见第8.4.4节,“The MySQL Keyring”

本节描述了如何安装或卸载密钥环函数,这些函数在一个插件库文件中实现,该文件还包含keyring_udf插件。关于安装或卸载插件和可加载函数的通用信息,请见第7.6.1节,“安装和卸载插件”,和第7.7.1节,“安装和卸载可加载函数”

密钥环函数启用了密钥环密钥管理操作,但是keyring_udf插件也必须安装,因为函数在没有它时不能正确工作。尝试使用函数而不安装keyring_udf插件将导致错误。

为了使插件库文件可由服务器使用,该文件必须位于MySQL插件目录中(由plugin_ dir系统变量指定的目录)。如果必要,可以在服务器启动时配置插件目录位置 bằng 设置plugin_ dir值。

插件库文件的基本名称是 keyring_udf。文件名后缀因平台而异(例如,.so 在 Unix 和 Unix 类似系统上,.dll 在 Windows 上)。

要安装 keyring_udf 插件和密钥库函数,请使用 INSTALL PLUGINCREATE FUNCTION 语句,根据您的平台调整 .so 后缀为必要:

INSTALL PLUGIN keyring_udf SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_generate RETURNS INTEGER
  SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_fetch RETURNS STRING
  SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_length_fetch RETURNS INTEGER
  SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_type_fetch RETURNS STRING
  SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_store RETURNS INTEGER
  SONAME 'keyring_udf.so';
CREATE FUNCTION keyring_key_remove RETURNS INTEGER
  SONAME 'keyring_udf.so';

如果插件和函数在源复制服务器上使用,请在所有副本上安装它们,以避免复制问题。

一旦按照前面所述安装,插件和函数将保持安装状态直到卸载。要删除它们,请使用 UNINSTALL PLUGINDROP FUNCTION 语句:

UNINSTALL PLUGIN keyring_udf;
DROP FUNCTION keyring_key_generate;
DROP FUNCTION keyring_key_fetch;
DROP FUNCTION keyring_key_length_fetch;
DROP FUNCTION keyring_key_type_fetch;
DROP FUNCTION keyring_key_store;
DROP FUNCTION keyring_key_remove;

在使用通用密钥库函数之前,请按照安装或卸载通用密钥库函数中的说明进行安装。

密钥库函数受以下约束:

  • 要使用任何密钥库函数,必须启用 keyring_udf 插件。否则,将出现错误:

    ERROR 1123 (HY000): Can't initialize function 'keyring_key_generate';
    This function requires keyring_udf plugin which is not installed.
    Please install

    要安装keyring_udf插件,请参阅通用密钥环函数的安装或卸载

  • 密钥环函数调用密钥环服务函数(请参阅第7.6.9.2节,“密钥环服务”)。这些服务函数然后使用安装的密钥环插件(例如keyring_okv)。因此,为了使用任何密钥环函数,某个基础密钥环插件必须被启用。否则,将发生错误:

    ERROR 3188 (HY000): Function 'keyring_key_generate' failed because
    underlying keyring service returned an error. Please check if a
    keyring plugin is installed and that provided arguments are valid
    for the keyring you are using.

    要安装密钥环插件,请参阅第8.4.4.3节,“密钥环插件安装”

  • 用户必须拥有全局EXECUTE特权,以使用任何密钥环函数。否则,将发生错误:

    ERROR 1123 (HY000): Can't initialize function 'keyring_key_generate';
    The user is not privileged to execute this function. User needs to
    have EXECUTE

    要授予全局EXECUTE特权给用户,请使用以下语句:

    GRANT EXECUTE ON *.* TO user;

    或者,如果您prefer避免授予全局EXECUTE特权,同时仍然允许用户访问特定的密钥管理操作,可以定义wrapper存储程序(后续在本节中描述的技术)。

  • 在给定用户存储的密钥可以后续由同一用户进行操作。也就是说,在操作密钥时CURRENT_USER()函数的值必须与密钥被存储到密钥ring时的值相同。这意味着不能使用密钥ring函数来操作实例范围的密钥,例如由InnoDB创建的用于支持表空间加密的密钥。

    要使多个用户能够对同一个密钥进行操作,可以定义“wrapper”存储程序(后续在本节中将描述这种技术).

  • 密钥ring函数支持由 underlying keyring 插件支持的密钥类型和长度。关于特定keyring插件的密钥信息,请见第8.4.4.10节,“Supported Keyring Key Types and Lengths”.

要创建一个新的随机密钥并将其存储到密钥ring中,请调用keyring_key_generate(),传递给它密钥的ID、加密方法和字节长度。以下示例创建了一个名为MyKey的2048位DSA加密密钥:

mysql> SELECT keyring_key_generate('MyKey', 'DSA', 256);
+-------------------------------------------+
| keyring_key_generate('MyKey', 'DSA', 256) |
+-------------------------------------------+
|                                         1 |
+-------------------------------------------+

返回值为1表示成功。如果密钥不能被创建,返回值为NULL并且发生错误。可能的原因是 underlying keyring 插件不支持指定的密钥类型和长度;见第8.4.4.10节,“Supported Keyring Key Types and Lengths”.

为了无论是否发生错误都能检查返回类型,请使用SELECT ... INTO @var_name并测试变量值:

mysql> SELECT keyring_key_generate('', '', -1) INTO @x;
ERROR 3188 (HY000): Function 'keyring_key_generate' failed because
underlying keyring service returned an error. Please check if a
keyring plugin is installed and that provided arguments are valid
for the keyring you are using.
mysql> SELECT @x;
+------+
| @x   |
+------+
| NULL |
+------+
mysql> SELECT keyring_key_generate('x', 'AES', 16) INTO @x;
mysql> SELECT @x;
+------+
| @x   |
+------+
|    1 |
+------+

这项技术也适用于其他密钥ring函数,它们在失败时返回一个值和错误。

传递给keyring_key_generate()的ID提供了将来函数调用中引用密钥的一种方式。例如,可以使用密钥ID检索其类型作为字符串或长度为整数的字节:

mysql> SELECT keyring_key_type_fetch('MyKey');
+---------------------------------+
| keyring_key_type_fetch('MyKey') |
+---------------------------------+
| DSA                             |
+---------------------------------+
mysql> SELECT keyring_key_length_fetch('MyKey');
+-----------------------------------+
| keyring_key_length_fetch('MyKey') |
+-----------------------------------+
|                               256 |
+-----------------------------------+

要检索密钥值,请将密钥ID传递给keyring_key_fetch()。以下示例使用HEX()来显示密钥值,因为它可能包含不可打印的字符。该示例也使用了短密钥,以简洁,但请注意更长的密钥提供更好的安全性:

mysql> SELECT keyring_key_generate('MyShortKey', 'DSA', 8);
+----------------------------------------------+
| keyring_key_generate('MyShortKey', 'DSA', 8) |
+----------------------------------------------+
|                                            1 |
+----------------------------------------------+
mysql> SELECT HEX(keyring_key_fetch('MyShortKey'));
+--------------------------------------+
| HEX(keyring_key_fetch('MyShortKey')) |
+--------------------------------------+
| 1DB3B0FC3328A24C                     |
+--------------------------------------+

密钥ring函数将密钥ID、类型和值视为二进制字符串,因此比较是区分大小写的。例如,IDs MyKeymykey 指向不同的密钥。

要删除密钥,请将密钥ID传递给keyring_key_remove()

mysql> SELECT keyring_key_remove('MyKey');
+-----------------------------+
| keyring_key_remove('MyKey') |
+-----------------------------+
|                           1 |
+-----------------------------+

要混淆并存储您提供的密钥,请将密钥ID、类型和值传递给keyring_key_store()

mysql> SELECT keyring_key_store('AES_key', 'AES', 'Secret string');
+------------------------------------------------------+
| keyring_key_store('AES_key', 'AES', 'Secret string') |
+------------------------------------------------------+
|                                                    1 |
+------------------------------------------------------+

如前所述,用户必须拥有全局EXECUTE权限来调用密钥ring函数,并且存储密钥到密钥ring的初始用户必须是后续对密钥进行操作的同一个用户,这个用户将根据每个函数调用的CURRENT_USER()值确定。为了允许非全局EXECUTE权限用户或不是密钥所有者的用户执行密钥操作,可以使用以下技术:

  1. 定义wrapper存储程序,封装所需的密钥操作,并将其DEFINER值设置为密钥所有者。

  2. 授予特定存储程序的EXECUTE权限给那些应该能够调用它们的个体用户。

  3. 如果wrapper存储程序实现的操作不包括密钥创建,使用在存储程序定义中指定的账户名称提前创建任何必要的密钥。

这种技术使得密钥可以被共享,并为DBA提供了更细粒度的控制权,以便控制谁可以对密钥进行操作,而不需要授予全局权限。

以下示例展示了如何设置一个名为SharedKey的共享密钥,该密钥由DBA所有,并创建一个名为get_shared_key()的存储函数,以便访问当前密钥值。该值可以由具有EXECUTE特权的用户检索,该函数在key_schema架构中创建。

从MySQL管理账户('root'@'localhost'在本例中)创建管理架构和存储函数以访问密钥:

mysql> CREATE SCHEMA key_schema;

mysql> CREATE DEFINER = 'root'@'localhost'
       FUNCTION key_schema.get_shared_key()
       RETURNS BLOB READS SQL DATA
       RETURN keyring_key_fetch('SharedKey');

从管理账户确保共享密钥存在:

mysql> SELECT keyring_key_generate('SharedKey', 'DSA', 8);
+---------------------------------------------+
| keyring_key_generate('SharedKey', 'DSA', 8) |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+

从管理账户创建一个普通用户账户,以授予对密钥的访问权限:

mysql> CREATE USER 'key_user'@'localhost'
       IDENTIFIED BY 'key_user_pwd';

key_user账户验证,未获得适当EXECUTE特权,该新账户无法访问共享密钥:

mysql> SELECT HEX(key_schema.get_shared_key());
ERROR 1370 (42000): execute command denied to user 'key_user'@'localhost'
for routine 'key_schema.get_shared_key'

从管理账户授予key_user对存储函数的EXECUTE特权:

mysql> GRANT EXECUTE ON FUNCTION key_schema.get_shared_key
       TO 'key_user'@'localhost';

key_user账户验证,密钥现在可访问:

mysql> SELECT HEX(key_schema.get_shared_key());
+----------------------------------+
| HEX(key_schema.get_shared_key()) |
+----------------------------------+
| 9BAFB9E75CEEB013                 |
+----------------------------------+

对于每个通用密钥ring函数,这一节描述了其目的、调用序列和返回值。有关这些函数可以被调用的条件,请见使用通用密钥ring函数

  • 丽参迮(<em class="replaceable"><code>参迮)

    根据密钥 ID,去除混淆并返回密钥值。

    参数:

    • 参迮: 指定密钥 ID 的字符串。

    返回值:

    成功时返回密钥值的字符串,否则返回 NULL 或错误信息。

    Note

    使用 丽参迮() 获取的密钥值受一般密钥函数限制,见 第8.4.4.10节,“系丽分和隟度”。可以使用密钥服务函数存储长密钥(见 第7.6.9.2节,“分密钥服务”),但使用 丽参迮() 时将被截断到一般密钥函数限制。

    示例:

    mysql> SELECT keyring_key_generate('RSA_key', 'RSA', 16);
    +--------------------------------------------+
    | keyring_key_generate('RSA_key', 'RSA', 16) |
    +--------------------------------------------+
    |                                          1 |
    +--------------------------------------------+
    mysql> SELECT HEX(keyring_key_fetch('RSA_key'));
    +-----------------------------------+
    | HEX(keyring_key_fetch('RSA_key')) |
    +-----------------------------------+
    | 91C2253B696064D3556984B6630F891A  |
    +-----------------------------------+
    mysql> SELECT keyring_key_type_fetch('RSA_key');
    +-----------------------------------+
    | keyring_key_type_fetch('RSA_key') |
    +-----------------------------------+
    | RSA                               |
    +-----------------------------------+
    mysql> SELECT keyring_key_length_fetch('RSA_key');
    +-------------------------------------+
    | keyring_key_length_fetch('RSA_key') |
    +-------------------------------------+
    |                                  16 |
    +-------------------------------------+

    示例使用 HEX() 显示密钥值,因为它可能包含不可打印字符。示例也使用短密钥,但请注意长密钥提供更好的安全性。

  • keyring_key_generate(key_id, key_type, key_length)

    生成一个新的随机密钥,具有给定的ID、类型和长度,并将其存储在密钥环中。类型和长度值必须与 underlying keyring 插件支持的值一致。请参阅第8.4.4.10节,“Supported Keyring Key Types and Lengths”

    参数:

    • key_id: 一个字符串,指定密钥ID。

    • key_type: 一个字符串,指定密钥类型。

    • key_length: 一个整数,指定密钥长度(以字节为单位)。

    返回值:

    成功时返回1,失败时返回NULL和错误信息。

    示例:

    mysql> SELECT keyring_key_generate('RSA_key', 'RSA', 384);
    +---------------------------------------------+
    | keyring_key_generate('RSA_key', 'RSA', 384) |
    +---------------------------------------------+
    |                                           1 |
    +---------------------------------------------+
  • keyring_key_length_fetch(key_id)

    给定密钥ID,返回密钥长度。

    参数:

    • key_id: 一个字符串,指定密钥ID。

    返回值:

    成功时返回密钥长度(以字节为单位)作为整数,密钥不存在时返回NULL,失败时返回NULL和错误信息。

    示例:

    请查看keyring_key_fetch()的描述。

  • keyring_key_remove(key_id)

    从密钥环中删除指定ID的密钥。

    参数:

    • key_id: 指定密钥ID的字符串。

    返回值:

    成功时返回1,失败时返回NULL

    示例:

    mysql> SELECT keyring_key_remove('AES_key');
    +-------------------------------+
    | keyring_key_remove('AES_key') |
    +-------------------------------+
    |                             1 |
    +-------------------------------+
  • keyring_key_store(key_id, key_type, key)

    将密钥存储在密钥环中,并对其进行隐藏。

    参数:

    • key_id: 指定密钥ID的字符串。

    • key_type: 指定密钥类型的字符串。

    • key: 指定密钥值的字符串。

    返回值:

    成功时返回1,失败时返回NULL和错误信息。

    示例:

    mysql> SELECT keyring_key_store('new key', 'DSA', 'My key value');
    +-----------------------------------------------------+
    | keyring_key_store('new key', 'DSA', 'My key value') |
    +-----------------------------------------------------+
    |                                                   1 |
    +-----------------------------------------------------+
  • keyring_key_type_fetch(key_id)

    根据密钥ID返回密钥类型。

    参数:

    • key_id: 指定密钥 ID 的字符串。

    返回值:

    成功时返回密钥类型的字符串,否则返回NULL(如果密钥不存在)或NULL和错误信息。

    示例:

    请参阅keyring_ key_fetch()的描述。