【IT168 应用】昨日听到同事说,某知名网站600万用户的信息被黑客窃取,这其实并没有让我感到吃惊,真正让我感觉可悲的是,用户的密码竟然是明文存放在数据库中的,这太让用户寒心了。这么一个专业的网站,这事做的太不专业,大家纷纷去下载相应的数据库文件,当然,我也不例外!事故已经发生了,多说不益,关键是寻找应对的方法。治标的方法是,注册用户及时更改自己的密码!治本的方法是相关网站立即改变数据存放策略,使用数据库加密功能对密码等敏感信息加密,这个功能很多数据库都支持,不知道网站方面为什么就没用!这太要命了!这事也给其他网站一个警示,不要再愚弄用户了,数据库加密刻不容缓,在此我以SQL Server 2008为例,介绍一个SQL Server中的透明数据加密功能!
早在SQL SERVER 2005中就已经实现了完整的加密基础结构,不需要再借此其他工具就可以实现完整的加密,解密操作!而SQL SERVER2000的时候需要自己编写存储过程或是函数,而这些现在2005都已经内置了。
支持的加密类型:
对称加密: 算法简单,速度较快,占用资源较少
非对称加密:公钥/私钥对
混合加密:包含对称和非对称
而且这三种加密只需要使用T-SQL语句就可以实现,下面看一下数据库加密体系结构,也就是SQL SERVER的加密层次:

▲ SQL Server 透明加密体系结构
大家看一个图,大家乍一看这个图还是挺复杂的,但其实很简单,这个加密体系分为三个级别,
第一个级别是windows级别:主要使用的是Windows的DPAPI(数据保护API)使用的是用户的凭据,也就是使用用户的密码来对需要保护的对象进行加密的一种方法。在这里主要是使用WINDOWS级别的用户凭据对第二个级别也就是SQL SERVER服务器级别进行加密。
第二个级别:SQL SERVER的服务器实例级别:这一个层次有一个服务主密钥,但是这个服务主密钥必须使用DPAPI(也就是第一个级别的用户凭据)进行加密。而这个服务主密钥又用于对第三个级别:数据库主密钥进行加密。也就是说上层必须为下层服务。
第三个级别:数据库级别:存在一个数据库主密钥。它可以加密数据库中的其他对象(如非对称,证书进行保护,但不保护对称密钥),
对称密钥不使用数据库主密钥加密,我们从图中可以看出来,对称密钥使用证书,非对称密钥或是指定的密码加密
同时又被第二级别服务主密钥所保护。当数据库中有了数据库主密钥后就可以使用数据库主密钥来保护数据库中的证书和非对称密钥,再使用对称密钥来保护其他对称密钥和数据,当然也可以直接使用证书和非对称密钥来保护数据。
总结一下:数据库中的数据使用证书,对称,非对称密钥加密,而它们又由服务主密钥保护,而服务主密钥呢,则由系统级别的DPAPI保护。环环相扣。
下面咱们把这个图倒过来再分析一下:中间的逻辑关系有点复杂。

▲ SQL Server 透明加密体系
高高在上的指数据库中有一个对称密钥,这个对称密钥必须要保护起来,如果密钥要是被别人知道了,那也就不安全了。这里可以使用用户指定的口令的进行保护,也可以使用证书进行保护(用证书的公钥加密,私钥解开)或是其他密钥(如其他的对称密钥)保护,那么证书又由谁来进行保护呢,那么证书的公钥不需要进行保护,那么私钥由谁来进行保护呢,在此也可以指定一个密钥,或者是使用数据库主密钥来进行保护。而数据库主密钥又由谁进行保护呢,也可以指定一个密钥,或者是服务主密钥,那么服务主密钥又由谁来进行保护呢,又由DPAPI来进行保护。就是这么一个逻辑的关系。
下面咱们来逐个看一下各种密钥:
服务主密钥:在安装SQL SERVER时自动生成的一个密钥,是128BIT的3DES密钥。作用:直接或者是间接地保护体系中的其他密钥。
使用SQL Server 的配置管理器更改服务帐户,能够自动完成加密和解密的过程。服务主密钥是安装时自动生成的,所以我们不能创建,但是我们可备份和还原服务主密钥。
备份:
Backup service master key to file=’c:\bak\smk.bak’ encryption by password=’DUfei2008’
备份的时候必须使用一个强密码,因为如果要是没有密码保护的话,那么其他人很容易进行还原,得到你的服务主密钥。
还原:必须给定备份时的密码:
Restore service master key from file=’c:\bak\smk.bak’ decryption by password=’DUfei2008’
下面咱们来看一下数据库主密钥:
注意:
1 数据库主密钥不会自己生成,必须需要管理员手动创建
2 由密码保护和服务主密钥同时保护
3 是128bit的3DES密钥。
创建语法:
Create master key encryption by password=’DUfei2008’ --由指定的密码和服务主密钥保护。可以使用密码来解开,如分离后复制到另一个服务器上,因为使用不同的服务帐户,那么服务主密钥不同,所以就不能解密我使用服务主密钥加密的数据库主密钥, 那么这个时候可以使用加密时所提供的密码来解开数据库主密钥。
我们在创建数据库主密钥的时候,会自动使用服务主密钥进行保护,使用时会自动使用服务主密钥解开数据库主密钥,当然我们也可以删除服务主密钥对数据库主密钥的保护,那么在每一次打开的时候必须手动打开数据库主密钥,因为没有了服务主密钥那么就必须指定在加密时所指定的口令。
打开数据库主密钥语法:如果删除服务主解密的时候才需要手动打开
Open master key decryption by password=’DUfei2008’
使用完毕后关闭数据库主密钥:
Close master key
也可以修改数据库主密钥:重新生成数据库主密钥,这是很耗资源的一个工作,因为旧的数据库主密钥会解密现有数据,然后使用新的数据库主密钥进行加密。
下面看一下如何对数据库主密钥进行备份和还原:
可能通过目录视图来查看查看数据库主密钥状态,如下所示:
Sys.symmetric_keys 查看有关数据库主密钥的信息
Sys.databases 中 is_master_key_encrypted_by_server列指示是否使用服务主密钥对数据库主密钥进行保护。
备份数据库主密钥:
如:
Backup master key to file=’c:\bak\dmk.bak’ encryption by password=’DUfei2008’
还原数据库主密钥:
Restore master key from file=’c:\bak\dmk.bak’ decryption by password=’旧密码’ encryption by password=’新密码’
下面咱们来看一下使用数据库加密保护数据。要保护数据,必须有一个可以保护数据的密钥,这个密钥有三种,对称密钥,非对称密钥和证书(公钥加密,私钥解密),有了密钥才可能去对数据进行加密,所以我们还得先来看一下如何创建相应的密钥,也就是如何创建证书,创建对称密钥,创建非对称密钥,然后再利用这些密钥对数据进行加密。
咱们先看一下创建证书:
注意:创建自签名的证书(也可以使用现有的CA进行证书的颁发)
创建自签名证书语法:
私钥可以用数据库 主密钥保护也可以使用指定的口令加密
Create certificate 证书名 encryption by password=’密码’ with subject=’ 主题’,
Start_date=’起始日期’ expiry_data=’到期日期’
其中这个口令用于保护咱们的私钥,主题,就是一个描述信息(无所谓),有效期在这里不是很严格,需要结合程序或者存储过程来进行检查。
更改用于加密私钥的密码或者是删除私钥的情况如下:
第一种情况适合于口令泄露的情况,不安全
第二种情况适合于只加密不解密的情况,很常见如一些注册用户密码,不希望管理看到。看不到原文,但是用户一样可以使用。
--修改私钥的口令
alter certificate cert1 with private key (decryption by password='DUfei2008',encryption by password='DUfei2008')
备份证书(导出证书)
Backup certificate 证书名 to file=’c:\bak\mycert.cer’ with private key (decryption by password=’旧口令’,file=’c:\bak\mycertpvt’,encryption by password=’私钥的口令’)
还原(导入)
-- 还原证书 在此不用restore 而是create 导入
create certificate cert1 from file='c:\bak\mycert.cer' with
private key (file='c:\bak\mypvt' ,decryption by password='DUfei2008',encryption by password='DUfei2008'
)
删除证书的私钥:
Alter certificate 证书名 remove private key
--增加私钥
alter certificate cert1 with private key (file='c:\bak\mypvt',
decryption by password='DUfei2008',encryption by password='DUfei2008')
另外还要用到一些与证书相关的函数:
Encryptbycert(证书ID,加密文本) 加密
Decryptbycert( 证书ID,密文,加密口令) 解密
Cert_id(证书名) 得到证书ID,因为加密,解密使用的都是ID
非对称密钥和对称密钥的操作方法类似,不再细述。
下面咱们就看一下具体的实例:
咱们就以dufei数据库为例,如果对敏感数据进行加密。
服务主密钥:咱们前面已经介绍了,是不需要创建的,在安装SQL SERVER时就已经存在了。我们做的只能是备份和还原:
create database dufei --创建数据库
1)备份
backup service master key to file='c:\bak\smk.bak' encryption by password='DUfei2008'
2)还原:
restore service master key from file='c:\bak\smk.bak' decryption by password='DUfei2008'
3) 生成新的服务主密钥 适应于更改服务帐户的情况,一般推荐使用配置管理器更改服务帐户
alter service master key regenerate
数据库主密钥:
1) 为当前dufei数据库创建数据库主密钥
use dufei
create master key encryption by password='DUfei2008'
2)查看数据库加密状态
select * from sys.databases where name='dufei'
此时 is_master_key_encrypted_by_server 为1 使用服务主密钥加密
3) 查看数据库主密钥的信息
select * from sys.symmetric_keys
可以得知长度和算法
4)备份数据库主密钥
backup master key to file='c:\bak\dmk.bak' encryption by password='DUfei2008'
5)删除服务主密钥对数据库主密钥的保护
默认情况下,创建数据库主密钥会被服务主密钥所保护的,但有的时候我们不希望数据库主密钥使用服务主密钥保护,那么就可以删除服务主密钥对数据库主密钥的保护。
我们先不删除,我们来利用数据库主密钥创建非对称密钥,可以直接创建
Create asymmetric key asy_key1 with algorithm=RSA_1024 --成功
语法:
Alter master key drop encryption by service master key
再次查看数据库的加密状态
Select * from sys.databases where name=’dufei’
--主要是看 is_master_key_encrypted_by_server 已经是0了。说明不被服务主密钥保护了。
此时我们再创建一个非对称密钥,则不成功
Create asymmetric key asy_key2 with algorithm=RSA_1024 --失败了
因为这个时候数据库主密钥不会自动打开了,必须打开数据库主密钥再创建
Open master key decryption by password=’DUfei2008’
Select * from sys.openkeys 显示打开的数据库主密钥
然后再创建非对称密钥则可以成功,如下
Create asymmetric key asy_key2 with algorithm=RSA_1024 成功了
可以通过图形界面查看一下,非对称密钥中已经出现了我们所创建的密钥
这个实验是告诉大家,如果你删除了服务主密钥对数据库主密钥的保护,那么每次必须手动打开数据库主密钥,挺麻烦的,所以我们还可以恢复服务主密钥对数据训主密钥的保护
1) 恢复服务主密钥对数据库主密钥的保护
Alter master key add encryption by service master key
2) 关闭数据库主密钥
Close master key
下面咱们来看看使用证书对数据进行加密
-----------------证书对数据加密 ---------------
1)生成自签名证书
--使用指定口令保护私钥
create certificate cert1 encryption by password='DUfei2008'
with subject='test', start_date='01/01/2009',expiry_date='01/01/2010'
--使用数据库主密钥保护私钥
create certificate cert2
with subject='test',start_date='01/01/2009',expiry_date='01/01/2010'
2) 查看证书信息
select * from sys.certificates
3) 修改私钥的口令
alter certificate cert1 with private key (decryption by password='DUfei2008',encryption by password='DUfei2008')
4) 备份证书
backup certificate cert1 to file='c:\bak\mycert.cer' with private key
(decryption by password='DUfei2008',file='c:\bak\mypvt',encryption by password='DUfei2008')
5) 删除私钥
alter certificate cert1 remove private key
6 ) 增加私钥
alter certificate cert1 with private key (file='c:\bak\mypvt',
decryption by password='DUfei2008',encryption by password='DUfei2008')
7) 删除证书
drop certificate cert1
8) 还原证书 在此不用restore 而是create 导入
create certificate cert1 from file='c:\bak\mycert.cer' with
private key (file='c:\bak\mypvt' ,decryption by password='DUfei2008',encryption by password='DUfei2008'
)
declare @atext varchar(100),@acipher varbinary(max)
set @atext='dufei hao!'
set @acipher=encryptbycert(cert_id('cert1'),@atext)
select @acipher
select cast(decryptbycert(cert_id('cert1'),@acipher,N'DUfei2008')as varchar(200) )
注意:在此必须将@acipher 定义为varbinary 因为,已经是一个密文,不是普通字符了!
通过以上讲解,大家发现数据库加密也不是一件很难的事情,不仅SQL Server支持,其他数据库管理系统都支持,但实现方法各不相同。希望用户明文密码的事件不再发生,换回用户对网站的信任,数据库加密刻不容缓!