作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
约瑟普Šaban的头像

强权统治下Š波斯历八月

拥有两个硕士学位,曾在斯洛文尼亚最大的企业工作, Josip是微软商业/数据库技术领域的资深人士.

工作经验

16

分享

数据是任何公司的关键资产, 特别是包含商业机密的交易数据,如财务或健康记录. 数据在存储它的服务器和请求它的客户机之间传输时最容易受到攻击.

确保安全性的标准方法是对服务器上的数据进行加密,并使用启用ssl的HTTPS协议来保护传输中的数据. 然而, 如果我们能进一步提高安全水平呢, 通过使用HTTPS并在通信线路上以加密格式发送数据, 只解密具有有效证书的客户端的数据? 这种方法将使传统的中间人(MITM)攻击变得更加困难.

SQL Server加密封面图片

微软对这个问题的解决方案是 总是加密, 一种通过管道发送加密数据并仅由具有有效证书访问权限的用户解密数据的方法. So, 即使攻击者得到了数据, 没有在客户端计算机上存储适当的证书, 数据将是无用的.

本文描述了如何设置和使用始终加密, 推荐通过公共通信线路发送重要数据的人阅读, 即使它们有SSL保护.

始终加密背后的概念

总是加密是微软在SQL Server 2016中引入的一项客户端加密技术. 总是加密使数据自动加密, 不仅仅是写出来的时候, 但当它被批准的应用程序读取时也是如此. 不像 透明数据加密, 哪种方式实时加密磁盘上的数据和日志文件,但允许任何查询数据的应用程序读取数据, 始终加密要求客户端应用程序使用始终加密启用的驱动程序与数据库通信. 通过使用这个驱动程序, 应用程序将加密的数据安全地传输到数据库,然后只有具有加密密钥访问权限的应用程序才能对数据库进行解密. 查询数据的任何其他应用程序也可以检索加密的值, 但是,如果没有加密密钥,该应用程序无法使用数据, 从而使数据变得无用. 因为这个加密体系结构, SQL Server实例永远不会看到数据的未加密版本.

此时,始终启用加密的驱动程序只有 .. NET Framework Data Provider for SQL Server,需要安装 .. NET框架版本4.6 在客户端计算机上,和 JDBC 6.0的司机. 这可能会随着时间的推移而改变, 但这些是2017年4月的官方始终加密要求.

但我们为什么需要这项技术? 有几个很好的理由为什么应该使用始终加密:

  • 安全 -数据总是需要安全的. 现在SSL正在受到威胁, 始终加密填补了另一层传输管道保护的空白.
  • 管理支持 -越来越多的行业法规需要对数据进行加密,防止DBA窥探数据, 主要在金融和电信行业. 这在 PII标准 (“个人身份信息”),说明信用卡号码等信息, 社会安全号码, 的名字, 地址必须受到保护, 否则,数据所有者将受到严厉惩罚.

如何使用始终加密

使用总是加密需要在存储加密表的数据库服务器中进行少量准备工作. 准备工作分为两步:

  • 创建列主键定义
  • 创建列加密密钥

列主键

列主键是什么?

SQL Server 2016的列主键

列主密钥是存储在 Windows证书存储 (在演示中用作证书存储选项),第三方 硬件安全模块 (用于安装、管理和使用证书的第三方解决方案的通用名称),或 Azure密钥库 (微软云证书管理解决方案).

对数据进行加密的应用程序使用列主密钥来保护处理数据库表列内数据加密的各种列加密密钥. 使用来自SQL Server的证书存储,有时称为 企业密钥管理器,需要使用SQL Server企业版.

在本文中, 我们描述了自签名证书的使用,该证书存储在Windows操作系统的微软证书存储库中. 虽然这种方法不是最佳配置, 它演示了始终加密的概念——但也需要说明这种方法是加密的 对于生产环境是不可接受的, 哪些地方的证书管理必须单独进行, 受保护的用户帐户和, 最好是, 在不同的服务器上.

可以通过使用SQL Server Management Studio (SSMS)中的图形界面或使用T-SQL创建列主键定义. 在地对地导弹, 连接到要使用总是加密保护数据库表的SQL Server 2016数据库实例.

创建和使用列主键

对象资源管理器, 首先导航到数据库, 然后是保安, 然后展开“始终加密密钥”文件夹以显示其两个子文件夹, 如下图所示:

在SSMS中创建密钥.

在SSMS中创建密钥.

打开一个新的列主密钥对话框.

打开一个新的列主密钥对话框

检查该密钥在Windows证书存储库中是否存在.

检查该密钥在Windows证书存储库中是否存在

要创建列主键,请右键单击 列主键 文件夹并选择 新列主键. 在 新列主键 对话框, 键入列主键的名称, 指定是将密钥存储在当前用户或本地计算机的证书存储中,还是存储在Azure密钥库中, 然后在列表中选择一个证书. 如果没有证书,或者希望使用新的自签名证书,请单击 生成证书 按钮,然后单击 OK. 此步骤创建一个自签名证书,并将其加载到运行SSMS的当前用户帐户的证书存储中.

注意: 您应该在受信任的机器上执行这些步骤, 但不是在托管SQL Server实例的计算机上. 这样,即使主机被入侵,数据仍然在SQL Server中受到保护.

So, 在创建证书并将其配置为列主密钥之后, 您必须将其导出并分发到托管需要访问数据的客户机的所有计算机. 如果客户端应用程序是基于web的,则必须在web服务器上加载证书. 如果它是安装在用户计算机上的应用程序, 然后必须将证书单独部署到每个用户的计算机上.

您可以在以下网址找到导出和导入操作系统证书的适用说明:

在使用加密和解密数据的应用程序将证书导入计算机上的证书存储时, 必须将证书导入计算机证书存储区或运行该应用程序的域帐户的证书存储区.

列加密密钥

创建列主密钥之后,就可以为特定列创建加密密钥了. SQL Server 2016 ADO.. NET驱动程序在将数据发送到SQL Server之前使用列加密密钥对数据进行加密, 并在从SQL Server 2016实例检索数据后解密数据. 与列主密钥一样,您可以使用T-SQL或SSMS创建列加密密钥. 而列主键更容易使用T-SQL创建, 使用SSMS更容易创建列加密密钥.

要创建列加密密钥,请使用 对象资源管理器 要连接到数据库实例,请导航到数据库,然后导航到 安全,并将 始终加密的密钥 文件夹. 右键单击 列加密密钥,然后选择 新列加密密钥. 在 新列加密密钥 对话框中,键入新加密密钥的名称,然后选择 列主键定义 在下拉列表中,然后单击 OK. 现在可以在新表的定义中使用列加密密钥.

创建列加密密钥

SQL加密:创建列加密密钥,映像1

SQL加密:创建列加密密钥,图像2

创建具有加密值的表

在创建列主密钥定义和列加密密钥之后, 您可以创建一个表来保存加密的值.

在你这么做之前, 您必须决定使用哪种类型的加密, 要加密哪些列, 以及是否可以对这些列进行索引. 与 总是加密 功能, 您通常定义列的大小, SQL Server会根据加密设置调整列的存储空间大小. 创建表之后, 您可能需要更改应用程序,以便使用 总是加密.

SQL Server 2016加密类型

在创建包含加密值的表之前, 您必须决定是否应该对每个列进行加密.

首先,该列是用于查找值还是仅仅返回这些值?

如果该列将用于查找,则该列必须使用 确定性加密类型,它允许进行相等运算. 但是,在搜索已使用加密的数据时存在限制 总是加密 功能. SQL Server 2016只支持相等操作,包括 等于, 不等于, 连接 (其中使用相等),并使用 集团 条款. 任何使用 就像 不支持. 此外,还可以使用 总是加密 必须在应用程序级别完成吗, 因为SQL Server将基于加密值而不是解密值进行排序.

如果列不打算用于定位记录, 然后该列应该使用随机化加密类型. 这种类型的加密更安全, 但它不支持搜索, 连接, 或者分组操作.

创建具有加密列的表

在创建表时,使用普通的 创建表 在列定义中使用一些附加参数的语法. 中使用了三个参数 加密与 的语法 创建表 声明.

第一个是 ENCRYPTION_TYPE 参数,该参数接受值 随机 or 确定的. 第二种是 算法 参数,该参数只接受的值 RAEAD_AES_256_CBC_HMAC_SHA_256. 第三个参数是 COLUMN_ENCRYPTION_KEY,这是用于加密值的加密密钥.

创建表[dbo].(客户)
(
 [CustomerId] [int] IDENTITY(1,1), 
 [TaxId] [varchar](11) COLLATE Latin1_General_BIN2 
 使用(encryption_type = deterministic, 
 算法= ' aead_aes_256_cbc_hmac_sha_256 ', 
 Column_encryption_key = your_column_encryption_key)不为空,
 [FirstName] [nvarchar](50) NULL,
 [LastName] [nvarchar](50) NULL, 
 [midlename] [nvarchar](50) NULL,
 [Address1] [nvarchar](50) NULL,
 [Address2] [nvarchar](50) NULL,
 [Address3] [nvarchar](50) NULL,
 [City] [nvarchar](50) NULL,
 [邮编][nvarchar](10) NULL,
 [State] [char](2) NULL,
 (出生年月日)(日期) 
 加密(encryption_type = r和omated, 
 算法= ' aead_aes_256_cbc_hmac_sha_256 ', 
 Column_encryption_key = your_column_encryption_key)不为空
 主键集群([CustomerId] ASC)在[PRIMARY]上;
 GO

始终加密索引

包含加密数据的列可以用作索引中的关键列, 方法对这些列进行加密 确定的 加密类型. 加密的列 随机 当尝试在这些列上创建索引时,加密类型返回错误消息. 使用任何一种加密类型加密的列都可以用作 包括 非聚集索引中的列.

因为加密的值可以是索引, 对于使用Always encrypted加密的值,除了通常执行的索引和调优之外,不需要额外的性能调优措施. 额外的网络带宽和更大的I/O是返回值大小增加所带来的唯一副作用.

始终加密的性能

性能始终是一个关键因素, 尤其是在这种情况下, 当我们在通常的数据库流量中增加加密开销时. 测试性能的最佳站点是 SQL性能,测试了不同场景下的查询执行和磁盘使用情况:

SQL Server始终加密性能结果测试.

SQL Server始终加密性能结果测试,映像1

SQL Server始终加密性能结果测试,映像2

因为有CPU和硬盘驱动器的工作,需要执行加密和解密进程, 这对使用的存储空间量和查询的持续时间有明显的影响. 因为这对您的环境(cpu)有影响, RAM和磁盘特性—您应该测试这是否会在生产中出现问题.

注意: 如果您想了解更多关于微软 SQL Sever性能优化的信息, 请查看我们之前的一篇文章, 如何调优微软 SQL Server的性能.

应用程序更改

要在遗留代码中正确实现始终加密,您必须做些什么?

SQL Server 2016的始终加密特性的一个好处是,已经在使用存储过程的应用程序, orm, 或参数化的T-SQL命令应该要求 没有应用程序更改 使用始终加密,除非已经使用了非相等操作. 在应用程序内将SQL语句构建为动态SQL并直接对数据库执行这些命令的应用程序需要进行修改,以使用查询的参数化, 推荐所有应用程序的安全最佳实践, 才能利用“始终加密”功能.

使始终加密工作所需的另一个更改是向连接到数据库的应用程序的连接字符串添加连接字符串属性: 列加密设置=启用.

将此设置添加到连接字符串后,ADO.. NET驱动程序询问SQL Server正在执行的命令是否包含任何加密列, 如果是这样的话, 哪些列是加密的. 适用于高负载应用, 使用此设置可能不是最佳实践, 特别是当大部分执行命令不包含加密值时.

因此, .. NET框架在SqlConnection对象上提供了一个名为 SqlComm和ColumnEncryptionSetting,它有三个可能的值:

  • 禁用 —没有总是加密列或参数用于使用此连接对象执行的查询.
  • 启用 —对于使用此连接对象执行的查询,总是使用加密列和/或参数.
  • 结果集 —没有“始终加密”参数. 然而, 使用此连接对象执行查询将返回使用Always encrypted加密的列.

注意: 请注意,使用此方法可能需要对应用程序代码进行大量更改. 另一种方法是重构应用程序以使用不同的连接.

为了SQL Server的最佳性能, 对于那些使用总是加密的查询,只请求关于总是加密的元数据是明智的. 这意味着在大部分查询使用始终加密的应用程序中, 应该启用连接字符串,并且应该指定应用程序中的特定查询 SqlComm和ColumnEncryptionSetting as 禁用. 对于大多数查询不使用始终加密值的应用程序, 不应该启用连接字符串, 和 SqlComm和ColumnEncryptionSetting 应该设置为 启用 or 结果集 对于那些使用始终加密列的查询. 在大多数情况下, 应用程序可以简单地启用连接字符串属性, 在使用加密数据时,应用程序的性能将保持不变.

总是加密值得吗?

简短的回答? 是的,肯定!

它不仅有助于防止许多潜在的安全问题和漏洞 SQL开发人员 具有附加的安全功能, 但它也使您的系统更兼容, 在多个行业中,哪个是至关重要的, 从电信到银行和保险. 同样重要的是要注意,鉴于文章中提到的技术先决条件, 始终加密可以通过对现有系统进行最小的应用程序更改来实现.

尽管您可以使用自定义解决方案来获得相同的效果, 该技术与新版本的SQL Server捆绑在一起, 并且可以开箱即用. 同样值得注意的是,由于这是一项新技术,仍然存在一些问题 限制 在它的使用上,它增加了一些额外的硬件需求.

然而, 除非它们会破坏你的环境, 并且你的应用程序是在公司内部网之外发布的, 实际上没有理由不使用始终加密.

就这一主题咨询作者或专家.
预约电话
约瑟普Šaban的头像
强权统治下Š波斯历八月

位于 奥地利的维也纳

成员自 2020年6月18日

作者简介

拥有两个硕士学位,曾在斯洛文尼亚最大的企业工作, Josip是微软商业/数据库技术领域的资深人士.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

工作经验

16

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

世界级的文章,每周发一次.

订阅意味着同意我们的 隐私政策

Toptal开发者

加入总冠军® 社区.