前面讲到的很多内容都是对数据加密和权限控制,这些主要在SQL Server内部,但是还有一种情况就是文件的安全性,除了在操作系统层面对文件进行访问控制之外,还要确保服务器被攻击之后文件被窃取的情况。为了避免文件被窃取后通过特权方式获得数据,有必要对文件也进行数据安全加密,在SQL Server中提供了一种叫透明数据加密(Transparent Data Encryption,TDE)的功能。
TDE可以防止数据库的文件(mdf/ndf/ldf)被非授权附加到别的服务器或者使用TDE功能的备份文件被轻易还原到别的服务器上,从而进一步加强了数据的安全性。
TDE通过对数据页和日志文件进行加密来实现这种安全性。其加密方式使用叫做“数据库加密密钥(database encryption key)”的非对称密钥加密。密钥存储在数据库的启动记录(boot record)中,并使用master库的一个服务器证书进行加密。也就是说,如果数据库文件(mdf、ndf、ldf或bak)被窃取,由于没有完整的解密密钥,数据库不可使用。不过如果连master库或者这个服务器证书也一并被窃取,那么还是可以解密的。
当启用数据库的TDE功能之后,数据和日志会在写入磁盘前被加密。然后在加载进内存时解密。这个过程对于用户、应用程序都是透明的。也就是不需要额外修改代码。
除了透明之外,TDE还有其他好处:
反复强调,不管是SQL Server还是其他DBMS,没有绝对的好的功能和绝对的坏的功能,都有适用场景,对于TDE来说,你可以对使用In-Memory的数据库进行TDE加密,但是对In-Memory文件组则无法加密。不过In-Memory相关的日志记录是可以加密的。同理,对使用了Filestream的库而言,可以加密但Filestream文件组不能加密。 如果数据库使用了复制(Replication),需要手动在订阅端进行TDE加密。因为在复制中不传递TDE操作。对于原生的TempDB,如果实例中的某个或某些库启用了TDE,那么TempDB自动启用TDE加密。从而避免攻击者通过临时数据获取信息。
另外,TDE和即时文件初始化不兼容。所以对于已使用TDE的库,使用不到即时文件初始化的好处。最后,在缓存中的数据也不能被TDE加密,如果需要加密这些数据,需要使用操作系统级别的加密工具。
下面来简单演示一下TDE,启用TDE包括以下步骤:
在启用TDE之后,会有一个后台进程对每个数据文件的每个页进行遍历并加密。这个操作不会导致数据库不可用。但是会加锁阻止以下的维护操作:
下面对AdventureWorks2016库进行TDE演示。使用CREATE DATABASE ENCRYPTION KEY命令来创建密钥。
USE Master
GO
--创建数据库主密钥,存在则可以忽略
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pa$$w0rd';
GO
--创建服务器证书
CREATE CERTIFICATE TDECert WITH SUBJECT = 'Certificate For TDE';
GO
USE AdventureWorks2016
GO
--创建数据库加密密钥
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_128
ENCRYPTION BY SERVER CERTIFICATE TDECert ;
GO
执行之后会有一个比较人性化的提醒:
--启用TDE
ALTER DATABASE AdventureWorks2016
SET ENCRYPTION ON ;
GO
到现在,TDE已经对AdventureWorks2016库及TempDB启用完毕。接下来我们看看如何去管理TDE功能,因为这个功能很危险,一旦出问题,你的库就废了。
正如Step3中的提示,你还未备份证书,如果证书丢失或者损坏,库将等同无效文件。所以首先必须要备份证书。备份证书很容易,使用下面命令备份即可,但是注意要做好真正的备份,以免证书彻底丢失:
BACKUP CERTIFICATE TDECert
TO FILE = 'C:\certificates\TDECert'
WITH PRIVATE KEY (file='C:\certificates\TDECertKey',
ENCRYPTION BY PASSWORD='Pa$$w0rd') ;
备份之后,我们要考虑一个问题,TDE正式为了避免文件被窃取破解,那么这个操作如果是合理合法的话,就不能被影响。也就是说,如果已经被TDE加密的库因为某些原因必须迁移到别的服务器,要进行下面步骤:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Pa$$w0rd' ;
GO
CREATE CERTIFICATE TDECert
FROM FILE = 'C:\Certificates\TDECert'
WITH PRIVATE KEY
(
FILE = 'C:\Certificates\TDECertKey',
DECRYPTION BY PASSWORD = 'Pa$$w0rd'
) ;
准备工作完成之后,就可以还原数据库了。
另外要注意,操作过程要确保使用的帐号具有足够的权限,如果连操作系统文件操作权限都没有的话,那一切白搭。