本篇文章是SQL Server安全系列的第八篇,详细内容请参考原文


Relational databases are used in an amazing variety of applications with connections from a dizzying array of clients over widely distributed networks,特别是互联网,使得数据几乎向任何人,任何地方开放。数据库可以包含相当大部分的人类知识,包括高度敏感的个人信息和关键数据。
数据库的这些特性使得有人想要窃取数据或通过篡改以损害它的主人。确保你的数据是安全的是一个关键部分来配置SQL Server和开发应用程序存储数据。这一系列将探索SQL Server 2012安全基础,那样你可以保护你的数据和服务器资源,getting as granular as you need to be to protect against the unique security threats that can affect your data.大部分的功能适用于早期版本的SQL Server,但我也会讨论只适用于SQL Server 2012和以后版本的功能。
一个重要的安全概念是纵深防御,这意味着最好的安全性是分层的,而不是依赖于一个单一的保护层。在你的网络、服务器、SQL Server实例、数据库安全后,可以通过加密敏感数据来添加数据保护的最后一个强大保护层。这一篇将会探索通过加密保护数据,你将了解加密密钥层次结构和各种可用于加密数据的密钥,以及如何管理密钥或让SQL Server为你做这件事。
数据加密
目前为止在这一系列中你已经学习了SQL Server中的很多安全特性来保护你的数据及数据库对象。当你结合网络安全,比如防火墙,用户帐户最小特权,以及其他工具,你的数据就十分安全吗?
不,尽管SQL Server 2012和2014是目前最安全的版本,而且假设你很明智并高效的使用上所有安全特性——被成功攻击还是有可能的。黑客都是极其聪明的人,因此非常有可能某人、某时能攻击到你的数据库服务器并访问你的数据。即使你有百分百的自信认为这样的攻击是不可能的,you might find yourself on the receiving end of an insider attack—a trusted employee gone bad.
一个安全原理是纵深防御——能够帮助你明白如何让你的数据或其他需要保护的资源达到最高级别的安全。纵深防御意味着你不能依赖一个单一的安全措施保护有价值的事物。你应该在不同的安全类型中增加保护层,那样攻击者必须先攻破复杂、困难的障碍才能获取到你的数据。
这也是许多中世纪的城堡有护城河作为第一道防线的原因。下一保护层是一个加强版几米厚的橡木门和石头墙。往往在外墙的里面还会有其他又厚又坚固的墙。就这样一层一层的保护里面人民和宝藏。
类似的方法,SQL Server有许多安全层和工具用于创建维护它们。但是当你的数据极度有价值时,你应该增加最后一道防御:加密。
自从SQL Server2005开始支持数据加密,之后的版本逐一提升功能。你可以使用多种加密类型,同时有多种密钥将数据转换为不可读的(无意义的)数据,除非用户有解密用的密钥。SQL Server支持多种加密算法。而且最棒的是,你可以让SQL Server来管理密钥和保密,这一直是加密中最难的部分。
提示:加密是一个处理器密集型(processor-intensive)操作,因为它需要复杂的计算。一个不合理的查询需要巨大的预读/开销,可能把服务器弄瘫痪。使用加密来保护那些值得加密的数据。
加密密钥
SQL Server可以让你使用任何三种加密密钥。加密密钥是数据的小块,当插入算法,将数据转换成乱码,没有正确的解密密钥几乎是不可能的转换回未加密的值。
->非对称密钥:该类型的加密使用公共/私有密钥对。一个密钥加密数据,另一个密钥进行解密。你可以与任何人分享的公共密钥,以便对任何它们加密数据,只有你可以通过使用私钥解密。SQL Server使用512、1024、2048位的Rivest-Shamir-Adelman(RSA)加密算法。你可以在Wikipedia's RSA page学习更多的RSA算法。
->对称密钥:在这种类型的加密,加密密钥和解密密钥是一样的。有时被称为一个共享的秘密,因为共享数据的双方必须有相同的密钥。在某些情况下,使用对称密钥是很困难的,因为从一方传递秘密到另一方是一个问题。对称密钥是数据库中使用的理想选择,因为它们永远不会离开数据库。SQL Server支持RC4、RC2、DES、AES算法。你可以在Symmetric Encryption查看这些算法。
->证书:证书是非对称密钥加密的一部分,用于公钥加密的数字包装器。SQL Server可以创建供你使用的证书,或者你可以从第三方认证机构获得。SQL Server uses the Internet Engineering Task Force's X.509 specifications.
SQL Server使用加密密钥层次结构,如图8.1所示,加密和保护你在数据库中存储的密钥

图8.1 加密密钥层次结构
在服务器级别,每个数据库实例有一个Service Master Key用于加密低层次的密钥。这个密钥是在SQL Server实例安装时创建。你可以备份和还原它,甚至重新生成,but for the most part you'll leave it alone.SQL Server为你管理,而且你从来不会明确使用它。Service Master Key是存储和保护在Windows,使用Windows Data protection API,or DPAPA.
Service Master Key有一些内部使用,但在这里对于我们而言SQL Server使用它来加密和保护你创建的Database Master Key。在任何你想加密数据的数据库中都需要一个Database Master Key.它是一个对称密钥用于加密和保护任何你创建密钥。你必须显式地在数据库环境中创建它,如代码8.1所示:

-- Set up sample encryption database
USE master;
GO
-- Set up a login
IF SUSER_SID('User1') IS NOT NULL DROP LOGIN User1;
CREATE LOGIN User1 WITH password = '3f@$fWDY3QvP&K0';
GO
IF DB_ID('EncryptionDB') IS NOT NULL DROP DATABASE EncryptionDB;
CREATE DATABASE EncryptionDB;
GO
USE EncryptionDB;
GO
CREATE USER User1 FOR LOGIN User1;
GO USE EncryptionDB;
GO
-- Databases do not have a master key by default, so you must create it before you can use it:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'gK#3hbQKDFQY0oF';
GO

代码8.1 在EncryptionDB库中创建Database Master Key
Database Master Key存储两次:它首先被Service Master Key加密存储,然后被你提供的密码再次加密。你可以删除两者中的一个,但不能全删除。通常情况下不会操作它们。
作为对称密钥,Database Master Key在你使用前必须打开它。打开一个密钥加载到内存然后解密,然后就可以使用。因为服务器级的Service Master Key加密了Database Master Key,数据库能自动为你打开密钥,很少需要你显示的去打开。类似Service Master Key,你可以备份、还原、修改Database Master Key.
你将使用图8.1中的其他密钥来加密数据。箭头指示使用哪一个密钥来加密和保护其他的密钥。例如,你可以使用Database Master Key来加密证书或非对称密钥。证书和非对称密钥只能保护对称密钥。对称密钥可以通过证书、非对称密钥或其他对称密钥来保护。
密钥管理
图8.1显示了加密密钥的另一个方面:你可以使用另一个密钥或一个密码来创建密钥。这就是所谓的密钥管理,这是SQL Server能为你管理的一个主要服务。
Key management is the single hardest thing to get right about encryption。历史上充满了各种国家的秘密,当密钥被截取时/泄露。第二次世界大战期间,美国、英国和其他盟国把大量的资源投入到德国和日本使用的加密密钥,以使他们能够拦截和读取高度敏感的信息。在最近的一次,许多高安全的应用程序被攻破,因为攻击者能够找到在应用程序或在计算机上嵌入的密钥。分享秘密是很困难的。
如果选择使用密码你可以自己管理SQL Server加密密钥,然后你肩负着保管密钥的责任。大多数人不想这样做,因为它需要高度专业化的技术技能。但是,如果你想承担这个任务,只要你创建一个密钥时使用密码选项。密码基本上是密钥,你必须确保你可以将密钥保存在安全的位置,并在需要时将其安全传输。
但是你不需要处理这些细节,因为SQL Server将为你照顾密钥管理。它将为你加密新的密钥,使用你所指定的任何方法,并将数据存储为安全地存储任何其他敏感信息。
你有权管理钥匙,但没有一个很好的理由你不应该这样做。
加密数据
现在来看一个SQL Server中加密数据的例子。在这个场景,Customer表通常具有客户的常规信息。客户名称和所在城市,不是敏感数据,不需要加密;但是信用卡类型、帐号可能包含个人敏感信息,应该进行加密。
你将使用一个对称密钥来加密表中的数据,记住一个对称密钥需要一个证书或非对称密钥在数据库中保护。因此,首先使用代码8.2创建一个非对称密钥来保护对称密钥:

-- Create an asymmetric key to protect the new symmetric key
CREATE ASYMMETRIC KEY User1AsymmetricKey
AUTHORIZATION User1
WITH ALGORITHM = RSA_2048;

代码8.2 创建一个非对称密钥
这个非对称密钥叫做User1AsymmetricKey,被User1用户拥有。这个密钥使用2048位的RSA加密,这是非常强/复杂的加密算法。这类数据肯定是非常非常重要!
接着,使用代码8.3创建一个对称密钥User1SymmetricKey.本例中使用TRIPLE_DES算法,并且被刚才创建的非对称密钥保护:

-- Create a symmetric key, protected by the asymmetric key
CREATE SYMMETRIC KEY User1SymmetricKey
WITH ALGORITHM = TRIPLE_DES
ENCRYPTION BY ASYMMETRIC KEY User1AsymmetricKey;

代码8.3 创建一个对称密钥
如果你想罗列数据库下的对称加密密钥,你可以使用sys.symmetric_keys目录视图来查看。代码8.4执行结果如图8.2所示。注意,因为Database Master Key是一个对称密钥,它也会出现在结果中。

-- List the symmetric keys in the database
SELECT * FROM sys.symmetric_keys;

代码8.4 罗列数据库下的对称密钥

图8.2 sys.symmetric_keys目录视图返回结果
代码8.5是EncryptionDB数据库下Customer表的结构:

USE EncryptionDB;
GO
CREATE TABLE Customer (
CustId int,
Name nvarchar(30),
City varchar(20),
CreditCardType varbinary(1000),
CreditCardNumber varbinary(1000),
Notes varbinary(4000));
GO
-- Grant access on the table to user
GRANT SELECT, INSERT ON Customer to User1;

代码8.5 创建Customer表
注意,因为最后三列将会保存加密后的binary类型数据而不是原始的string数据,因此列的类型设置成varbinary。列的长度依赖数据的大小以及算法。数据库有一个User1用户,对Customer表有SELECT和INSERT权限。
是时候加密一些数据并插入到数据库中。第一步使用代码8.6打开对称密钥,这一步引起SQL Server在内部存储查找密钥,确保用户有权限使用密钥,然后解密密钥到内存以准备使用:

OPEN SYMMETRIC KEY User1SymmetricKey
DECRYPTION BY ASYMMETRIC KEY User1AsymmetricKey;

代码8.6 打开对称密钥
数据加密使用T-SQL语句EncryptByKey函数,使用唯一的GUID区分密钥。你可以使用Key_GUID函数检索GUID而不是直接传送数值。否则,代码8.7是一个普通的T-SQL插入语句:

INSERT INTO Customer VALUES (1, 'Sally Roe', 'Chatinika',
EncryptByKey(Key_GUID('User1SymmetricKey'), 'Visa'),
EncryptByKey(Key_GUID('User1SymmetricKey'), '1234-5678-9009-8765'),
EncryptByKey(Key_GUID('User1SymmetricKey'),
'One of our best customers. Treat like royalty.'));

代码8.7 插入加密数据
最后一步使用代码8.8关闭对称密钥。它会从内存中移除密钥并释放资源。只要你不需要加密了就应该尽快关闭密钥,因为把它留在内存可能会被攻击者利用。

CLOSE SYMMETRIC KEY User1SymmetricKey;

代码8.8 关闭对称密钥
提示:如果你要使用密钥在一个单独批处理中加密或解密大量的数据,可以它先打开着。打开和关闭密钥需要处理时间的。但是当你完成的时候,别忘了把它关上!
现在运行一个查询语句查看表中的数据,如图8.3所示。你可以看到在CustId、Name、City列数据没有加密,但是在加密列文本是随机binary数据。你的数据是安全的!

图8.3 表中存储的加密数据
表中的数据是没有价值的,除非有一个方法来检索它。本例中你需要使用一个常规查询语句,并且使用DecryptByKey函数来解密数据。这个函数返回varbinary数据,因为加密数据可能是任何数据类型。因此要检索原始文本需要你对DecryptByKey函数结果进行转换。

OPEN SYMMETRIC KEY User1SymmetricKey
DECRYPTION BY ASYMMETRIC KEY User1AsymmetricKey;
SELECT CustID, Name, City,
CONVERT(VARCHAR, DecryptByKey(CreditCardType)) AS CardType,
CONVERT(VARCHAR, DecryptByKey(CreditCardNumber)) AS CardNumber,
CONVERT(VARCHAR, DecryptByKey(Notes)) AS Notes
FROM Customer;
CLOSE SYMMETRIC KEY User1SymmetricKey;

代码8.9 打开密钥然后执行查询语句

图8.4 解密数据结果

-- *** Encryption Catalog Views ***
-- ********************************
-- Existing keys
SELECT * FROM sys.certificates;
SELECT * FROM sys.asymmetric_keys;
SELECT * FROM sys.symmetric_keys;
SELECT * FROM sys.database_principals;
SELECT * FROM sys.key_encryptions;
SELECT * FROM sys.crypt_properties;
-- Information about keys
-- Returns a row for each symmetric key encryption specified using the ENCRYPTION BY clause of the CREATE SYMMETRIC KEY statement.
SELECT * FROM sys.key_encryptions;
-- Returns one row for each cryptographic property associated with a securable
SELECT * FROM sys.crypt_properties; -- *** Clean up ***
-- ****************
USE master;
GO
IF SUSER_SID('User1') IS NOT NULL DROP LOGIN User1;
IF DB_ID('EncryptionDB') IS NOT NULL DROP DATABASE EncryptionDB;
GO

总结
SQL Server的数据加密功能为你的数据提供额外的保护层,让你在深度防御。SQL Server攻击者必须攻破网络安全、服务器安全、SQL Server实例的安全性、以及数据库的安全来获得你的数据。然后,与胜利如此接近,他们必须处理强加密的数据才能为其所用。结合强大的数据库安全性,充分利用细粒度的权限以对主体需要访问的数据提供最小特权,你可以为最敏感的数据建立强大的保护。

第八篇 SQL Server安全数据加密的更多相关文章

  1. 【译】第八篇 SQL Server安全数据加密

    本篇文章是SQL Server安全系列的第八篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...

  2. 第八篇 SQL Server代理使用外部程序

    本篇文章是SQL Server代理系列的第八篇,详细内容请参考原文 在这一系列的上一篇,学习了如何用SQL Server代理作业活动监视器监控作业活动和查看作业历史记录.在实时监控和管理SQL Ser ...

  3. 【译】第八篇 SQL Server代理使用外部程序

    本篇文章是SQL Server代理系列的第八篇,详细内容请参考原文 在这一系列的上一篇,学习了如何用SQL Server代理作业活动监视器监控作业活动和查看作业历史记录.在实时监控和管理SQL Ser ...

  4. 第十篇 SQL Server代理使用代理帐户

    本篇文章是SQL Server代理系列的第十篇,详细内容请参考原文 在这一系列的上一篇,你查看了msdb库下用于授权访问SQL Server代理的安全角色.这些角色包括SQLAgentUserRole ...

  5. 第九篇 SQL Server代理了解作业和安全

    本篇文章是SQL Server代理系列的第九篇,详细内容请参考原文 在这一系列的上一篇,学习了如何在SQL Server代理作业步骤启动外部程序.你可以使用过时的ActiveX系统,运行批处理命令脚本 ...

  6. 第七篇 SQL Server代理作业活动监视器

    本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...

  7. 第六篇 SQL Server代理深入作业步骤工作流

    本篇文章是SQL Server代理系列的第六篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.每个作业步骤在技术 ...

  8. 第五篇 SQL Server代理理解代理错误日志

    本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...

  9. SQL Server的数据加密简介

    防止开发人员获取到敏感数据(SQL Server的数据加密简介) 背景 有时候,我们还真的会碰到这样的需求:防止开发人员获取到敏感数据.也许你觉得很简单,把开发和运营分开不就可以了吗?是的,如果公司有 ...

随机推荐

  1. POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25904   Accepted: 7682 Descr ...

  2. ContentType Office

    Office对应ContentType 当从浏览器返回一个文件时,需要指定ContentType,以下是Office2007对应的值: "application/vnd.openxmlfor ...

  3. 一个比较轻巧好用的js分页插件,可ajax可url

    var pageNav = pageNav || {}; pageNav.fn = null; pageNav.pre = "pre"; pageNav.next = " ...

  4. 【转】Unity3D的输入(Input)——键盘和鼠标

    http://blog.csdn.net/lingyun_blog/article/details/41451565 Unity3D使用input类控制用户的输入,输入包括了用户键盘,鼠标,触摸,重力 ...

  5. Jetbrains phpstorm pycharm 免费授权注册码

    通过授权服务器授权 jetbrains是一家专门做IDE的软件公司,软件也非常好用,但是授权特别贵,下面就说说免费的方式,就是使用授权服务器,地址:http://idea.qinxi1992.cn 自 ...

  6. 设置MyEclipse开发项目时使用的JDK

    安装好MyEclipse之后,在MyEclipse中开发项目时,默认使用的是MyEclipse是自带的JDK,如下图所示: 如果我们需要使用自己安装好的JDK,那么就需要在MyEclipse中重新设置 ...

  7. JS获取Cookie值

    function GetLoginCookie() { var userCookie = getCookie("mycookie"); var loginname = userCo ...

  8. nrf51822-主从通信分析1

    建议看该教程前,先看一下  简单扫描器实现  教程 讲解基于sdk目录下central中的两个例子. 关于主机的程序框架其实和从机都是一样的,都是基于事件驱动的框架. Main函数中完成初始化, 从机 ...

  9. zepto源码--$.map,$.each,$.grep--学习笔记

    从相对比较简单的说起: 1.$.grep  获取一个新数组,新数组只包含回调函数中返回 true 的数组项. 调用javascript中数组原生函数filter,对elements进行过滤,保留回调函 ...

  10. .Net程序员安卓学习之路2:访问网络API

    做应用型的APP肯定是要和网络交互的,那么本节就来实战一把Android访问网络API,还是使用上节的DEMO: 一.准备API: 一般都采用Json作为数据交换格式,目前各种语言均能输出Json串. ...