Always Encrypted

适用于: SQL Server(所有受支持的版本) Azure SQL 数据库 Azure SQL 托管实例

Always Encrypted图。

Always Encrypted是一项旨在保护敏感数据的功能,例如信用卡号或国民身份证号 (,例如存储在 Azure SQL 数据库、Azure SQL 托管实例和SQL Server数据库中的美国社会安全号码) 。 Always Encrypted允许客户端加密客户端应用程序内的敏感数据,并且从不向数据库引擎透露加密密钥。 这在拥有数据并可以查看数据的人员与管理数据但不应具有访问权限的用户(本地数据库管理员、云数据库操作员或其他高特权未经授权的用户)之间实现了分离。 因此,Always Encrypted使客户能够自信地将其敏感数据存储在云中,并降低恶意内部人员窃取数据的可能性。

Always Encrypted可以配置为支持对加密数据的有限机密查询,即涉及相等比较的查询。 例如,点查找搜索或相等联接。 此类查询利用 确定性加密

注意

安全 enclave 通过模式匹配、其他比较运算符和就地加密扩展了Always Encrypted的机密计算功能。 有关详细信息,请参阅具有安全 enclave 的 Always Encrypted

始终加密使向加密对应用程序透明。 安装在客户端计算机上的启用始终加密的驱动程序通过在客户端应用程序中对敏感数据进行加密和解密来实现此目标。 该驱动程序先对敏感列中的数据进行加密,然后再将该数据传递到 数据库引擎,并且自动重写查询以便保留应用程序的语义。 同样,该驱动程序透明地解密存储在查询结果中包含的加密数据库列中的数据。

配置 Always Encrypted

本部分概述了如何设置Always Encrypted。 有关详细信息和入门,请参阅教程:Always Encrypted入门

若要在数据库中设置Always Encrypted,需要:

  1. 预配加密密钥以保护数据。 Always Encrypted 使用两种类型的密钥:

    • 列加密密钥。
    • 列主密钥。

    列加密密钥用于对加密列中的数据进行加密。 列主密钥是对一个或多个列加密密钥进行加密的密钥保护密钥。

    需要将列主密钥存储在数据库系统外部的受信任密钥存储中,例如 Azure 密钥保管库Windows 证书存储或硬件安全模块。

    然后,需要预配列加密密钥,并使用列主密钥对每个密钥进行加密。

    最后,需要在数据库中存储有关密钥的元数据。

    • 列主密钥元数据捕获列主密钥的位置。
    • 列加密密钥元数据包含列加密密钥的加密值。 数据库引擎绝不会以纯文本形式存储或使用任一类型的键。

    有关管理Always Encrypted密钥的详细信息,请参阅Always Encrypted的密钥管理概述

  2. 为包含要保护的敏感数据的选定数据库列配置加密。 这可能需要创建包含加密列的新表,或者加密现有数据库列和现有数据。 为列设置加密时,请指定有关加密算法的信息、用于保护列中数据的列加密密钥以及加密类型。 Always Encrypted支持两种加密类型:

    • 确定性加密 始终为给定的纯文本值生成相同的加密值。 使用确定性加密允许对加密列进行点查找、等值联结、分组和建立索引。 但也可能允许未经授权的用户通过检查加密列中的模式来猜测有关加密值的信息,尤其是存在一个规模较小的可能加密值集合时,如 True/False 或 North/South/East/West 等区域。

    • 随机加密 使用一种以更不可预测地方式加密数据的方法。 随机加密更加安全,但不支持对加密列进行搜索、分组、索引和联接。

    针对要用作搜索参数或分组参数的列使用确定性加密。 例如,政府 ID 号。 针对不会与其他记录分组在一起且不会用来联接表的数据(例如机密的调查注解)使用随机加密。

有关 Always Encrypted 加密算法的详细信息,请参阅 Always Encrypted 加密

可以使用 SQL 工具执行上述步骤:

为了确保Always Encrypted密钥和受保护的敏感数据永远不会以纯文本形式泄露给数据库环境,数据库引擎不能参与密钥预配和数据加密或解密操作。 因此,Transact-SQL (T-SQL) 不支持密钥预配或加密操作。 出于同一原因,需要使用其他加密类型或列加密密钥 (对现有数据进行加密或重新加密,) 需要在数据库外部执行 (SQL 工具可以自动执行该) 。

注意

具有安全 enclave 的Always Encrypted允许使用 T-SQL 对现有数据执行加密操作,从而解除了上述一些限制,并且无需将数据移出数据库。

针对加密列的查询的工作原理

若要对加密的数据库列运行查询、将数据插入加密列、从加密列中检索纯文本值或执行支持的操作 (例如,使用确定性加密对列) 点查找搜索,发出查询的用户或应用程序必须满足以下先决条件:

  • 有权访问保护数据的列主密钥。 除了数据库级权限之外,还需要密钥访问,例如 SELECT 对包含数据的表。
  • 在数据库连接中启用Always Encrypted连接到数据库。 大多数 SQL 工具和 SQL 客户端驱动程序都支持为数据库连接启用Always Encrypted。

注意

如果用户具有读取数据所需的数据库权限,但无法访问保护数据的密钥,则用户仍可以通过连接到数据库来检索 cyphertext (加密) 数据,而无需在数据库连接中启用Always Encrypted。

下面是对加密列的查询的工作原理:

  1. 当应用程序发出参数化查询时,应用程序中的 SQL 客户端驱动程序通过调用 sp_describe_parameter_encryption (Transact-SQL ) ,以透明方式联系数据库引擎 (,以确定哪些参数面向加密列并且应加密。 对于需要加密的每个参数,驱动程序将接收加密算法、加密类型和密钥元数据,包括加密列加密密钥及其相应列主密钥的位置。
  2. 驱动程序调用包含列主密钥的密钥存储区,以便解密加密的列加密密钥值。 缓存生成的纯文本列加密密钥,以减少后续使用同一列加密密钥时到密钥存储的往返次数。
  3. 驱动程序使用获取的纯文本列加密密钥来加密与加密列对应的查询参数。
  4. 驱动程序将面向加密列的参数的纯文本值替换为其加密值,并将查询发送到数据库引擎进行处理。
  5. 数据库引擎执行查询,这可能涉及使用确定性加密对列的相等性比较。
  6. 如果查询结果包括来自加密列的数据,则数据库引擎会将每个列的加密元数据(包括有关加密算法、加密类型和密钥元数据的信息)附加到结果集。
  7. 数据库引擎将结果集发送到客户端应用程序。
  8. 对于接收的结果集中的每个加密列,驱动程序首先尝试在本地缓存中查找纯文本列加密密钥,并且仅在缓存中找不到列主密钥时,才往返到保存列主密钥的密钥存储。
  9. 驱动程序解密结果并将纯文本值返回给应用程序。

客户端驱动程序使用列主密钥存储提供程序与包含列主密钥的密钥存储进行交互,列主密钥存储提供程序是一个客户端软件组件,用于封装包含列主密钥的密钥存储。 常见类型的密钥存储的提供程序在 Microsoft 的客户端驱动程序库中提供,或作为独立下载提供。 你也可以实现自己的提供程序。 Always Encrypted 功能(包括内置的列主密钥存储提供程序)因驱动程序库及其版本而异。

有关支持Always Encrypted的客户端驱动程序列表以及如何开发查询加密列的应用程序的信息,请参阅使用 Always Encrypted 开发应用程序。

还可以使用 SQL 工具(例如 Azure Data StudioSSMS)查询加密列。

限制

以下限制适用于对加密列的查询:

  • 确定性加密支持涉及相等比较的以下操作 - 不允许其他操作。

  • 不允许对使用随机加密加密的列进行计算。

    注意

    具有安全 enclave 的Always Encrypted允许使用随机加密对列进行模式匹配、比较运算符、排序和索引,从而放宽了上述限制。

  • 不允许触发涉及纯文本和加密数据的计算的查询语句。 例如:

    • 将加密列与纯文本列或文本进行比较。
    • 将数据从纯文本列复制到加密列 (或) UPDATEBULK INSERTSELECT INTOINSERT.SELECT
    • 将文本插入加密列。

    此类语句会导致操作数冲突错误,如下所示:

    Msg 206, Level 16, State 2, Line 89
        Operand type clash: char(11) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'CEK_1', column_encryption_key_database_name = 'ssn') collation_name = 'Latin1_General_BIN2' is incompatible with char
    
  • 应用程序必须使用查询参数传递与加密列对应的值。 例如,将数据插入加密列或按加密列进行筛选时, (使用确定性加密) 。 不支持传递与加密列对应的文本或 T-SQL 变量。 有关正在使用的客户端驱动程序的详细信息,请参阅使用 Always Encrypted 开发应用程序

  • 必须使用 Azure Data StudioSSMS 中Always Encrypted变量的参数化来发出查询,这些查询传递与这些工具中的加密列对应的值。 例如,将数据插入加密列或按加密列进行筛选时, (使用确定性加密) 。

  • 不支持以加密列为目标的表值参数

  • 不支持使用以下子句的查询:

  • 更改加密列的定义后,执行sp_refresh_parameter_encryption以更新对象的Always Encrypted元数据。

  • 具有以下特征的列不支持Always Encrypted:

    重要

    SQL Server 2022 (16.x) 中已弃用 Stretch Database。 后续版本的 Microsoft SQL Server 将删除该功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。

    • 外部 (PolyBase) 表中的列(注意:支持在同一查询中使用外部表和列已加密的表)。
  • 以下功能对加密的列不起作用:

Always Encrypted Transact-SQL 参考

Always Encrypted使用以下 Transact-SQL 语句、系统目录视图、系统存储过程和权限。

语句

系统目录视图和存储过程

另请参阅 sys.columns (Transact-SQL) ,了解有关为每个列存储的加密元数据的信息。

数据库权限

Always Encrypted有四个数据库权限:

  • ALTER ANY COLUMN MASTER KEY - 创建和删除列主密钥元数据所必需的。

  • ALTER ANY COLUMN ENCRYPTION KEY - 创建和删除列加密密钥元数据所必需的。

  • 查看任意列主密钥定义 - 访问和读取列主密钥元数据所必需的,这是查询加密列所必需的。

  • 查看任意列加密密钥定义 - 访问和读取列主密钥元数据所必需的,这是查询加密列所必需的。

下表总结了常见的操作所需的权限。

场景 ALTER ANY COLUMN MASTER KEY ALTER ANY COLUMN ENCRYPTION KEY VIEW ANY COLUMN MASTER KEY DEFINITION VIEW ANY COLUMN ENCRYPTION KEY DEFINITION
密钥管理(创建/更改/检查数据库中的密钥元数据) X x x X
查询加密列 X x

重要注意事项

  • 选择加密列时,需要“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限,即使用户无权访问列主密钥 (其密钥存储) ,保护列并且不访问纯文本尝试。

  • 在SQL Server中,默认情况下,“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限都授予公共固定数据库角色。 数据库管理员可以选择撤销 (或拒绝) 公共 角色的权限,并将其授予特定角色或用户以实现更受限的控制。

  • 在SQL 数据库中,默认情况下,不会向公共固定数据库角色授予“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限。 这使某些现有的旧工具 (使用较旧版本的 DacFx) 可以正常工作。 因此,若要使用加密列 (即使不解密它们) 数据库管理员也必须显式授予 VIEW ANY COLUMN MASTER KEY DEFINITIONVIEW ANY COLUMN ENCRYPTION KEY DEFINITION 权限。

后续步骤

请参阅