sqlserver 启用安全 Enclave 的 Always Encrypted

SQL Server 2016 新引入的 Always Encrypted 由于加密功能受到严格限制,对加密列仅支持相等比较(且仅适用于确定性加密),不支持所有其他操作。而 SQL Server 2019 及更高版本以及 Azure SQL 提供了具有安全 enclave 的 Always Encrypted,它可以在服务器端对安全 enclave 内的纯文本数据进行某些计算,从而解决这些限制(支持LIKE、范围查询、排序、JOIN等)。安全 Enclave 是数据库引擎过程中受保护的内存区域,它可以安全地访问明文中的加密密钥和敏感数据,而不会破坏数据的保密性。

配置 Enclave 原地在线加密(推荐生产)

  • SQL Server 2019+ 提供安全 Enclave,支持原地加密、不导出数据、支持 ONLINE=ON(最小锁表、业务影响小),尤其适合生产环境使用。

注:[离线方案]无安全 Enclave 时,不能直接 ALTER COLUMN 原地加密,全量数据需要拉取到客户端再加密后回写。若有大表则耗时久且全程持有表排他锁,必须选择停机执行。

  • Always Encrypted 支持两种 Enclave 技术,但在 SQL Server 2019 及更高版本中,仅支持 VBS enclave。而在 Azure SQL 数据库中,可以使用 Intel SGX enclave(一种基于硬件的受信任执行环境技术)或 VBS enclave,具体取决于运行的硬件

启用 VBS 支持

  • 第1步,确认满足以下系统要求,示例 Windows Server 2019 Datacenter + SQL Server 2019 Enterprise
SQL:SQL Server 2019 / 2022 / 2025
OS:Windows Server 2019+ / Win11 24H2+
虚拟机:需开启 CPU 虚拟化 Intel VT-x / AMD-V,若未开启则不支持VBS
  • 第2步,启用 CPU 虚拟化,示例为 VMWare 虚拟机启用虚拟化(需关机状态调整)

  • 第3步,开机后,打开 PowerShell 启用基于虚拟化的安全性 (VBS)
#.启用基于虚拟化的安全性(VBS)
Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard -Name EnableVirtualizationBasedSecurity -Value 1

#.关闭强制硬件安全校验
Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard -Name RequirePlatformSecurityFeatures -Value 0

#.重启服务器生效
Restart-Computer -Force

#.重启后确认VBS状态为2 (0未启用/1已启用但内核未加载VBS/2正常启用)
(Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard -ClassName Win32_DeviceGuard).VirtualizationBasedSecurityStatus
  • 第4步,重启后,确认已启用 CPU 虚拟化

  • 第5步,打开 SSM 启用安全 enclave 功能
--.使用SSMS在不启用AlwaysEncrypted的情况下,将安全enclave类型设置为基于虚拟化的安全性(VBS)
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
EXEC sp_configure 'column encryption enclave type', 1;
RECONFIGURE;
GO
  • 第6步,打开 PowerShell 重启 SQLServer 服务
Restart-Service -Force MSSQLSERVER
  • 第7步,确认已启用 Enclave
--.查看Enclave配置,若 value_in_use=1 表示已启用
SELECT name, value, value_in_use 
FROM sys.configurations 
WHERE name = 'column encryption enclave type'

--.验证Enclave是否正常运行,若无数据则表示未启用或硬件不支持(比如未开启CPU虚拟化)
SELECT * FROM sys.dm_column_encryption_enclave

创建 CMK + CEK

  • 第8步,创建测试数据库并调整排序规则,示例 ae_demo

注:中文环境推荐 Chinese_PRC_BIN2(区分大小写和重音),英文环境推荐 Latin1_General_BIN2

USE master
IF DB_ID('ae_demo') IS NULL
CREATE DATABASE ae_demo
GO

--.修改排序规则
ALTER DATABASE ae_demo COLLATE Chinese_PRC_BIN2

--.初始化数据表
USE ae_demo
IF OBJECT_ID('dbo.Employees', 'U') IS NOT NULL
DROP TABLE dbo.Employees
GO

--.创建测试表
CREATE TABLE dbo.Employees (
  id bigint IDENTITY(1000,1) NOT NULL PRIMARY KEY,
  UserName nvarchar(100),
  iPhone varchar(18),
  Salary money
)

--.插入测试数据
INSERT INTO Employees (UserName, iPhone, Salary) VALUES ('tom', '13012345678', 6000)
INSERT INTO Employees (UserName, iPhone, Salary) VALUES ('sam', '13112345678', 8000)
INSERT INTO Employees (UserName, iPhone, Salary) VALUES ('joy', '13212345678', 5000)

--.查看数据
SELECT * FROM Employees
  • 第9步,创建支持 Enclave 的列主密钥(核心操作,普通 CMK 无法原地加密),示例 AE_ColumnMasterKey

注:若虚拟机未启用 CPU 虚拟化,则这里没有“允许 enclave 计算”这个选项

  • 第10步,创建 列加密密钥(Column Encryption Key, 简称CEK),示例 AE_ColumnEncryptionKey

注:这里要关联上一步创建的列主密钥(AE_ColumnMasterKey)

证书的导出与导入

  • 第11步,在数据库服务器上运行 certlm.msc 打开“证书-本地计算机”控制台,依次选择“个人 → 证书”选中证书右键“所有任务 → 导出”

注:建议导出私钥选择“是,导出私钥”,导出文件格式选择“个人信息交换(.PFX)”,安全密码:Ae2026,文件名:c:\ae2026.pfx

  • 第12步,在第三方SSMS客户端或应用程序服务器上运行 certlm.msc 打开“证书-本地计算机”控制台,然后导入证书文件

通过 SSMS 客户端测试

  • 第13步,打开 SSMS 连接到实例的时候,在“始终加密”标签页勾选“启用 Always Encrypted (列加密)”和“启用安全 enclave”

  • 第14步,先打开一个查询窗口,然后依次选择“查询 -> 查询选项”,在新打开的窗口勾选“启用 Always Encrypted 参数化”并确定

  • 第15步,对老表的字段进行原地加密(Enclave 独有能力,不用停机、不用导出数据、支持 ONLINE=ON),尤其适合生产环境
USE ae_demo
GO 

--.针对老表,原地加密
ALTER TABLE Employees
ALTER COLUMN iPhone varchar(18) COLLATE Chinese_PRC_BIN2 
ENCRYPTED WITH (
    COLUMN_ENCRYPTION_KEY = AE_ColumnEncryptionKey,
    ENCRYPTION_TYPE = DETERMINISTIC,
    ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
) WITH (ONLINE = ON)   --在线模式,仅短时间架构锁,不阻塞DML

--.数值类型无需指定排序规则
ALTER TABLE Employees
ALTER COLUMN Salary money 
ENCRYPTED WITH (
    COLUMN_ENCRYPTION_KEY = AE_ColumnEncryptionKey,
    ENCRYPTION_TYPE = RANDOMIZED,
    ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
) WITH (ONLINE = ON)   --在线模式,仅短时间架构锁,不阻塞DML

--.清除数据库的查询计划缓存
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE

--.查看数据
SELECT * FROM Employees
  • 第16步,在启用了 Always Encrypted 参数化的查询窗口,可以查看明文数据,而在未启用的查询窗口只能看到密文数据

通过 APP 应用程序测试

  • 第1步,登录到应用程序服务器,将数据库服务器的证书导入本机,过程可参考上面的章节
  • 第2步,在应用程序的代码中,修改连接字符串,添加 Column Encryption Setting = Enabled;Attestation Protocol=None;(否则读取密文)即可支持 Always Encrypted
#.NET连接字符串
"Data Source=192.168.31.101;Initial Catalog=ae_demo;Integrated Security=True;Column Encryption Setting=Enabled;Attestation Protocol=None"

#.JDBC连接字符串
"jdbc:sqlserver://192.168.31.101:1433;databaseName=ae_demo;integratedSecurity=true;columnEncryptionSetting=Enabled;enclaveAttestationProtocol=NONE;"

附录

限制条件

  • 基于 SQL Server 2019 环境,启用 Enclave 与 无Enclave 的 Always Encrypted 加密功能变化(优先使用随机加密而不是确定性加密):

注:SQL Server 2022 开始支持对加密列 JOIN、GROUP BY 和 ORDER BY

比较项 确定性加密 随机加密
SELECT查询
(全部支持)
--.支持
SELECT UserName,iPhone FROM Employees
--.支持
SELECT UserName,Salary FROM Employees
等值查询
(全部支持)
--.支持
DECLARE @iPhone varchar(18) = '13012345678'
SELECT * FROM Employees where iPhone = @iPhone
--.不支持->支持
DECLARE @Salary money = 6000
SELECT * FROM Employees where Salary = @Salary
IN
(全部支持)
--.支持
DECLARE @num1 varchar(18) = '13012345678'
DECLARE @num2 varchar(18) = '13212345678'
SELECT * FROM Employees where iPhone IN(@num1,@num2)
--.不支持->支持
DECLARE @num1 money = 5000
DECLARE @num2 money = 6000
SELECT * FROM Employees where Salary IN(@num1,@num2)
GROUP BY --.支持
SELECT iPhone,COUNT(iPhone) FROM Employees GROUP BY iPhone
--.不支持sum但支持count
SELECT Salary,SUM(Salary) FROM Employees GROUP BY Salary
SELECT Salary,COUNT(Salary) FROM Employees GROUP BY Salary
DISTINCT --.支持
SELECT DISTINCT iPhone FROM Employees
--.不支持(sql2022支持)
SELECT DISTINCT Salary FROM Employees
创建索引
(全部支持)
--.支持
CREATE INDEX idx_iPhone ON Employees(iPhone)
--.不支持->支持
CREATE INDEX idx_Salary ON Employees(Salary)
> <
(部分支持)
--.不支持
DECLARE @iPhone varchar(18) = '13012345678'
SELECT * FROM Employees where iPhone > @iPhone
--.不支持->支持
DECLARE @Salary money = 5000
SELECT * FROM Employees where Salary > @Salary
BETWEEN
(部分支持)
--.不支持
DECLARE @beg varchar(18) = '13012345678'
DECLARE @end varchar(18) = '13212345678'
SELECT * FROM Employees WHERE iPhone BETWEEN @beg AND @end
--.不支持->支持
DECLARE @beg money = 5000
DECLARE @end money = 7000
SELECT * FROM Employees WHERE Salary BETWEEN @beg AND @end
LIKE
(全不支持)
--.不支持
DECLARE @iPhone varchar(18) = '130%'
SELECT * FROM Employees where iPhone like @iPhone
--.不支持
DECLARE @Salary money = 5000
SELECT * FROM Employees where Salary like @Salary
ORDER BY
(全不支持)
--.不支持
SELECT * FROM Employees ORDER BY iPhone DESC
--.不支持(sql2022支持)
SELECT * FROM Employees ORDER BY Salary DESC
适用场景 需要where查询就用确定性加密
比如:身份证号/手机号
只需展示就用随机化加密
比如:薪资/余额
Copyright © www.sqlfans.cn 2021 - 2026 All Right Reserved更新时间: 2026-09-08 14:40:52

results matching ""

    No results matching ""