Always Encrypted
适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例
Always Encrypted 和“具有安全 Enclave 的 Always Encrypted”是旨在保护 Azure SQL 数据库、Azure SQL 托管实例和 SQL Server 数据库中的敏感信息(包括信用卡号以及国家或地区标识号,如美国社会安全号码)的功能。 它使客户端能够加密客户端应用程序内的敏感数据,确保加密密钥永远不会暴露给数据库引擎。 这在拥有并可以查看数据的人员与管理数据但不应具有访问权限的人员之间实现分隔:本地数据库管理员、云数据库操作员或其他高特权未经授权的用户。 因此,Always Encrypted 允许客户将其敏感数据安全地存储在云中,从而降低数据被恶意内部人员窃取的风险。
Always Encrypted 具有某些限制,例如无法对加密数据执行操作,包括排序、筛选(使用确定性加密的点查找除外)等。这意味着某些查询和应用程序可能与 Always Encrypted 不兼容,或者可能需要对应用程序逻辑进行重大更改。
为了解决这些限制,“具有安全 Enclave 的 Always Encrypted”使数据库引擎能够在称为“安全 enclave”的受保护内存区域内处理加密数据。 安全 enclave 通过支持模式匹配、各种比较运算符和就地加密增强了 Always Encrypted 的机密计算能力。
Always Encrypted 可确保应用程序无缝加密。 在客户端,启用 Always Encrypted 的驱动程序在将敏感数据发送到数据库引擎之前对其进行加密,并自动重写查询以维护应用程序语义。 它还会自动解密来自加密数据库列的查询结果。
配置 Always Encrypted
注意
对于需要对加密列执行模式匹配、使用比较运算符、排序和编制索引的应用程序,应实现“具有安全 Enclave 的 Always Encrypted”。
本部分概述了如何设置 Always Encrypted。 有关详细信息和入门指南,请参阅教程:Always Encrypted 入门。
若要在数据库中配置 Always Encrypted,请执行下面的步骤:
预配加密密钥以保护数据。 Always Encrypted 使用两种类型的密钥:
- 列加密密钥。
- 列主密钥。
列加密密钥用于对加密列中的数据进行加密。 列主密钥是对一个或多个列加密密钥进行加密的密钥保护密钥。
列主密钥必须存储在数据库系统之外受信任的密钥存储中,例如 Azure 密钥保管库、Windows 证书存储或硬件安全模块。 此后,应预配列加密密钥,并使用列主密钥对它们进行加密。
最后,请将有关密钥的元数据存储在数据库中。 列主密钥元数据包括列主密钥的位置。 列加密密钥元数据包含列加密密钥的加密值。 数据库引擎不以纯文本形式存储或使用任何密钥。
有关管理 Always Encrypted 密钥的详细信息,请参阅 Always Encrypted 密钥管理概述。
为包含敏感信息的特定数据库列设置加密,以确保保护。 这可能需要创建具有加密列的新表或加密现有列和数据。 为列配置加密时,需要指定有关加密算法、用于保护数据的列加密密钥以及加密类型的详细信息。 Always Encrypted 支持两种类型的加密:
对于任何给定的纯文本值,“确定性加密”始终生成相同的加密值。 使用确定性加密允许对加密列进行点查找、等值联结、分组和编制索引。 但也可能允许未经授权的用户通过检查加密列中的模式来猜测有关加密值的信息,尤其是存在一个规模较小的可能加密值集合时,如 True/False 或 North/South/East/West 等区域。
随机加密使用一种不可预测地加密数据的方法。 每个相同的纯文本输入都会产生不同的加密输出。 这提高了随机加密的安全性。
若要通过对加密列使用比较运算符、排序和索引来执行模式匹配,应该采用“具有安全 Enclave 的 Always Encrypted”并应用随机加密。 Always Encrypted(没有安全 enclave)随机加密不支持对加密列进行搜索、分组、编制索引或联接。 相反,对于用于搜索或分组目的的列,必须使用确定性加密。 这允许对加密列执行点查找、相等联接、分组和编制索引等操作。
由于数据库系统在设计上无法访问加密密钥,因此任何列加密都需要将数据移动到数据库之外并加密。 这意味着此加密过程可能需要很长时间,并且容易受到网络中断的影响。 此外,如果需要稍后重新加密列,例如轮换加密密钥或更改加密类型时,将再次遇到同样的困难。 使用“具有安全 Enclave 的 Always Encrypted”消除了将数据移出数据库的必要性。 由于 enclave 受信任,因此应用程序内的客户端驱动程序或 Azure Data Studio 或 SQL Server Management Studio (SSMS) 等工具可以在加密操作期间安全地与 enclave 共享密钥。 然后,enclave 可以就地加密或重新加密列,从而显著减少这些操作所需的时间。
有关 Always Encrypted 加密算法的详细信息,请参阅 Always Encrypted 加密。
可以使用 SQL 工具执行上述步骤:
- 使用 SQL Server Management Studio 预配 Always Encrypted 密钥
- 使用 PowerShell 配置“始终加密”功能
- sqlpackage - 自动执行安装过程
为确保始终不向数据库环境公开纯文本形式的 Always Encrypted 密钥和受保护敏感数据,因此数据库引擎不会参与密钥预配,也不会执行数据加密或解密操作。 因此,Transact-SQL (T-SQL) 不支持密钥预配或加密操作。 由于同样原因,加密现有数据或重新加密它(使用不同的加密类型或列加密密钥)需要在数据库外部执行(SQL 工具可以自动执行)。
更改加密列的定义之后,需执行 sp_refresh_parameter_encryption,以更新该对象的 Always Encrypted 元数据。
限制
对加密列的查询存在以下限制:
不允许对使用随机加密进行加密的列进行计算。 确定性加密支持以下涉及相等比较的操作 - 不允许其他操作。
注意
对于需要对加密列执行模式匹配、使用比较运算符、排序和编制索引的应用程序,应实现“具有安全 Enclave 的 Always Encrypted”。
不允许触发涉及纯文本和加密数据的计算的查询语句。 例如:
- 将加密列与纯文本列或文本进行比较。
- 使用 UPDATE、BULK INSERT、SELECT INTO 或 INSERT..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 Studio 或 SSMS 中,必须对 Always Encrypted 变量应用参数化来执行处理与加密列相关的值的查询。 这包括将数据插入加密列或对其应用筛选器等应用场景(如果使用确定性加密)。
不支持针对加密列的表值参数。
不支持使用下列子句的查询:
具有以下特征的列不支持 Always Encrypted:
- 使用以下任一数据类型的列:xml、timestamp、rowversion、image、ntext、text、sql_variant、hierarchyid、geography、geometry、别名、用户定义类型。
- FILESTREAM 列
- 具有 IDENTITY 属性的列。
- 具有 ROWGUIDCOL 属性的列。
- 使用确定性加密时,除二进制码位 (_BIN2) 排序规则以外的排序规则的字符串(varchar、char 等)列。
- 使用随机加密时用作聚集索引和非聚集索引的键的列(支持使用确定性加密在列上添加索引)。
- 全文检索中包含的列(Always Encrypted 不支持全文搜索)。
- 指定表中的计算列。
- 计算列引用的列(当表达式针对 Always Encrypted 执行不受支持的操作时)。
- 使用稀疏列。
- 使用随机加密时统计信息引用的列(支持确定性加密)。
- 分区列。
- 包含默认约束的列。
- 使用随机加密时 unique 约束引用的列(支持确定性加密)。
- 使用随机加密时的主键列(支持确定性加密)。
- 使用随机加密或确定性加密时引用外键约束中的列(如果被引用和引用列使用不同的键或算法)。
- check 约束引用的列。
- 使用更改数据捕获捕获/跟踪的列。
- 具有更改跟踪的表中的主键列。
- 屏蔽的列(使用动态数据掩码)。
- 延伸数据库表中的列。 (无法为延伸启用其列已使用始终加密加密的表。)
重要
SQL Server 2022 (16.x) 和 Azure SQL 数据库中已弃用 Stretch Database。 在数据库引擎的未来版本中将删除此功能。 请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。
- 外部 (PolyBase) 表中的列(注意:支持在同一查询中使用外部表和列已加密的表)。
以下功能对加密的列不起作用:
- SQL Server 复制(事务性复制、合并复制或快照复制)。 支持物理复制功能,包括 Always On 可用性组。
- 分布式查询(链接服务器、OPENROWSET (Transact-SQL)、OPENDATASOURCE (T-SQL))。
- 对从不同数据库加密的列执行联接的跨数据库查询。
Always Encrypted Transact-SQL 参考
Always Encrypted 使用以下 Transact-SQL 语句、系统目录视图、系统存储过程和权限。
语句
DDL 语句 | 描述 |
---|---|
CREATE COLUMN MASTER KEY | 在数据库中创建列主密钥元数据对象 |
DROP COLUMN MASTER KEY | 删除数据库中的列主密钥。 |
CREATE COLUMN ENCRYPTION KEY | 创建列加密密钥元数据对象。 |
ALTER COLUMN ENCRYPTION KEY | 在数据库中更改列加密密钥,添加或删除加密的值。 |
DROP COLUMN ENCRYPTION KEY | 删除数据库中的列加密密钥。 |
CREATE TABLE (ENCRYPTED WITH) | 指定加密列 |
系统目录视图和存储过程
系统目录视图和存储过程 | 描述 |
---|---|
sys.column_encryption_keys | 返回有关列加密密钥的信息 (CEK) |
sys.column_encryption_key_values | 返回有关列加密密钥 (CEK) 的加密值的信息 |
sys.column_master_keys | 为每个数据库主密钥返回一行 |
sp_refresh_parameter_encryption | 更新指定的非绑定到架构的存储过程、用户定义函数、视图、DML 触发器、数据库级 DDL 触发器或服务器级 DDL 触发器的参数的 Always Encrypted 元数据。 |
sp_describe_parameter_encryption | 分析指定的 Transact-SQL 语句及其参数,以确定哪些参数对应于使用 Always Encrypted 功能保护的数据库列。 |
另请参阅 sys.columns,以便了解有关为每个列存储的加密元数据的信息。
数据库权限
Always Encrypted 有四种数据库权限。
系统目录视图和存储过程 | 描述 |
---|---|
ALTER ANY COLUMN MASTER KEY | 创建和删除列主密钥元数据时需要。 |
ALTER ANY COLUMN ENCRYPTION KEY | 创建和删除列加密密钥元数据时需要。 |
VIEW ANY COLUMN MASTER KEY DEFINITION | 在访问和读取列主密钥元数据(查询加密列所需)时需要。 |
VIEW ANY COLUMN ENCRYPTION KEY DEFINITION | 在访问和读取列加密密钥元数据(查询加密列所需)时需要。 |
下表总结了常见的操作所需的权限。
场景 | 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 中,默认授予 public 固定数据库角色“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限。 数据库管理员可以选择撤销(或拒绝)public 角色的权限,并将该权限授予特定的角色或用户来实现更严格的控制。
在 SQL 数据库中,默认授予 public 固定数据库角色“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限。 这可以使某些现有的旧工具(使用旧版本的 DacFx)能够正常工作。 要使用加密列(即使不对其进行解密),数据库管理员必须显式授予“查看任意列主密钥定义”和“查看任意列加密密钥定义”权限。