摘要

在SQL Server安全系列专题的上两期月报分享中,我们分别分享了:如何使用对称密钥实现SQL Server列加密技术和使用非对称密钥加密方式实现SQL Server列加密。本期月报我们分享使用混合密钥加密方式实现SQL Server列加密技术,最大限度减少性能损失,最大程度保护用户数据安全。

场景引入

对称加密是指加密和解密过程使用同一个密钥的加密算法,非对称加密是指加密和解密过程使用不同的密钥进行的加密算法。因此,通常来说对称加密安全性较弱,非对象加密安全性相对较高。凡事都具有两面性,非对称密钥加密的安全性较好,但通常算法相比对称密钥复杂许多,因此会带来性能上的损失也更大。有没有一种方法既可以最大限度保证数据安全性,又能够最大限度的减少性能损失呢?这便是本期月报分享的价值所在:SQL Server使用混合密钥实现列加密技术。

具体实现

在SQL Server 2005及以后版本,在支持对称密钥实现列加密的同时,也同样支持非对称密钥实现列加密,以下是使用混合密钥加密用户手机号码的具体实现步骤以及详细过程,以此最大限度满足数据库安全性和减少加密解密过程的性能损失。

创建测试数据库

创建一个专门的测试数据库,名为:TestDb。

--Step 1 - Create MSSQL sample database
USE master
GO
IF DB_ID('TestDb') IS NOT NULLDROP DATABASE [TestDb];
GO
CREATE DATABASE [TestDb];
GO

创建测试表

在TestDb数据库下,创建一张专门的测试表,名为:CustomerInfo。

--Step 2 - Create Test Table, init data & verify
USE [TestDb]
GO
IF OBJECT_ID('dbo.CustomerInfo', 'U') IS NOT NULLDROP TABLE dbo.CustomerInfo
CREATE TABLE dbo.CustomerInfo
(
CustomerId      INT IDENTITY(10000,1)   NOT NULL PRIMARY KEY,
CustomerName    VARCHAR(100)            NOT NULL,
CustomerPhone   CHAR(11)                NOT NULL
);-- Init Table
INSERT INTO dbo.CustomerInfo
VALUES ('CustomerA','13402872514')
,('CustomerB','13880674722')
,('CustomerC','13487759293')
GO-- Verify data
SELECT *
FROM dbo.CustomerInfo
GO

原始数据中,用户的电话号码为明文存储,任何有权限查看表数据的用户,都可以清楚明了的获取到用户的电话号码信息,展示如下:

创建实例级别Master Key

在SQL Server数据库实例级别创建Master Key(在Master数据库下,使用CREATE MASTER KEY语句):

-- Step 3 - Create SQL Server Service Master Key
USE master;
GO
IF NOT EXISTS(SELECT *FROM sys.symmetric_keysWHERE name = '##MS_ServiceMasterKey##')
BEGINCREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MSSQLSerivceMasterKey'
END;
GO

创建数据库级别Master Key

在用户数据库TestDb数据库下,创建Master Key:

-- Step 4 - Create MSSQL Database level master key
USE [TestDb]
GO
IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE name LIKE '%MS_DatabaseMasterKey%')
BEGIN       CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'TestDbMasterKey@3*';
END
GO

创建非对称密钥

在用户数据库下,创建非对称密钥,并使用密码对非对称密钥进行加密:

-- Step 5 - Create MSSQL Asymmetric Key
USE [TestDb]
GO
IF NOT EXISTS (SELECT * FROM sys.asymmetric_keys WHERE name = 'AsymKey_TestDb')
BEGINCREATE ASYMMETRIC KEY AsymKey_TestDb WITH ALGORITHM = RSA_512 ENCRYPTION BY PASSWORD = 'Password4@Asy';
END
GOUSE [TestDb]
GO
SELECT *
FROM  sys.asymmetric_keys

查看非对称密钥

您可以使用如下查询语句查看非对称密钥:

USE [TestDb]
GO
SELECT *
FROM  sys.asymmetric_keys

结果展示如下:

当然,您也可以用SSMS图形界面来查看证书和非对称密钥对象,方法是在用户数据库下,打开Security => Certificates => Asymmetric Keys,如下图所示:

创建对称密钥

使用非对称密钥AsymKey_TestDb来加密对称密钥SymKey_TestDb,然后使用这个对称密钥SymKey_TestDb来加密用户数据。这样既可以利用非对称密钥的安全性来保护对称密钥,又能兼顾对称密钥加密数据的高效性,两全其美。这种使用非对称密钥加密对称密钥,然后使用对称密钥加密用户敏感数据的方式,我且称之为“混合密钥”加密,这一步是本篇文章的关键点,也是很多人没有关注到的点。

--Step 6 - Create Symmetric Key Encrypted by symmetic key
USE [TestDb]
GO
IF NOT EXISTS (SELECT * FROM sys.symmetric_keys WHERE name = 'SymKey_TestDb')
BEGINCREATE SYMMETRIC KEY SymKey_TestDb WITH ALGORITHM = AES_256 ENCRYPTION BY ASYMMETRIC KEY AsymKey_TestDb;  -- Asymmetric Key;
END
GOUSE [TestDb]
GO
SELECT *
FROM  sys.symmetric_keys

对称密钥展示如下:

修改表结构

接下来,我们需要修改表结构,添加一个数据类型为varbinary(max)的新列,假设列名为EncryptedCustomerPhone ,用于存储加密后的手机号码密文。

-- Step 7 - Change your table structure
USE [TestDb]
GO
ALTER TABLE CustomerInfo
ADD EncryptedCustomerPhone varbinary(MAX) NULL
GO

新列数据初始化

新列添加完毕后,我们将表中历史数据的用户手机号CustomerPhone,加密为密文,并存储在新字段EncryptedCustomerPhone中。方法是使用EncryptByKey函数加密CustomerPhone列,如下语句所示:

-- Step 8 - init the encrypted data into the newly column
USE [TestDb]
GO
-- Opens the symmetric key: SymKey_TestDb
OPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';
GO
UPDATE A
SET EncryptedCustomerPhone = EncryptByKey (Key_GUID('SymKey_TestDb'), CustomerPhone)
FROM dbo.CustomerInfo AS A;
GO
-- Closes the symmetric key: SymKey_TestDb
CLOSE SYMMETRIC KEY SymKey_TestDb;
GO
-- Double check the encrypted data of the new column
SELECT * FROM dbo.CustomerInfo

查看表中EncryptedCustomerPhone列的数据,已经变成CustomerPhone对称加密后的密文,如下展示:

查看加密数据

手机号被加密为密文后,我们需要使用DecryptByKey函数将其解密为明文(解密前,需要打开对称密钥),让我们尝试看看能否成功解密EncryptedCustomerPhone字段。

-- Step 9 - Reading the SQL Server Encrypted Data
USE [TestDb]
GO
-- Opens the symmetric key: SymKey_TestDb
OPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';
GO-- Now, it's time to list the original phone, encrypted phone and the descrypted phone.
SELECT *,DescryptedCustomerPhone = CONVERT(CHAR(11), DecryptByKey(EncryptedCustomerPhone))
FROM dbo.CustomerInfo;-- Close the symmetric key
CLOSE SYMMETRIC KEY SymKey_TestDb;
GO

查询语句执行结果如下,CustomerPhone和DescryptedCustomerPhone字段数据内容是一模一样的,因此加密和解密成功。

添加新数据

历史数据加密解密后的数据保持一致,然后,让我们看看新添加的数据:

-- Step 10 - What if we add new record to table.
USE [TestDb]
GO
OPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';
GO
-- Performs the update of the record
INSERT INTO dbo.CustomerInfo (CustomerName, CustomerPhone, EncryptedCustomerPhone)
VALUES ('CustomerD', '13880975623', EncryptByKey( Key_GUID('SymKey_TestDb'), '13880975623'));  -- Close the symmetric key
CLOSE SYMMETRIC KEY SymKey_TestDb;
GO

更新数据手机号

接下来,我们尝试更新用户手机号:

-- Step 11 - So, what if we upadate the phone
USE [TestDb]
GO
OPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';-- Performs the update of the record
UPDATE A
SET EncryptedCustomerPhone = EncryptByKey( Key_GUID('SymKey_TestDb'), '13880971234')
FROM dbo.CustomerInfo AS A
WHERE CONVERT(CHAR(11), DecryptByKey(EncryptedCustomerPhone)) = '13880975623'-- Close the symmetric key
CLOSE SYMMETRIC KEY SymKey_TestDb;
GO

删除手机号明文列

一切没有问题,我们可以将用户手机号明文列CustomerPhone删除:

-- Step 12 - Remove old column
USE [TestDb]
GO
ALTER TABLE CustomerInfo
DROP COLUMN CustomerPhone;
GO

再次查看加密数据

将用户手机号码的明文列删除后,我们再次查看解密用户手机号码明文列

--Step 13 - verify again
USE [TestDb]
GO
OPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';SELECT *,DescryptedCustomerPhone = CONVERT(CHAR(11), DecryptByKey(EncryptedCustomerPhone))
FROM dbo.CustomerInfoCLOSE SYMMETRIC KEY SymKey_TestDb;
GO

结果展示如下:

一切正常,历史数据、新添加的数据、更新的数据,都可以工作完美。按理,文章到这里也就结束。但是有一个问题我们是需要搞清楚的,那就是:如果我们新创建了用户,他能够访问这个表的数据吗?以及我们如何让新用户能够访问该表的数据呢?

添加新用户

模拟新添加一个用户EncryptedDbo:

-- Step 14 - Create a new user & access the encrypted data
USE [TestDb]
GO
IF EXISTS(SELECT TOP 1 *FROM sys.server_principalsWHERE name = 'EncryptedDbo'
)
BEGINDROP LOGIN EncryptedDbo;
END
GOCREATE LOGIN EncryptedDboWITH PASSWORD=N'EncryptedDbo@3*', CHECK_POLICY = OFF;GOCREATE USER EncryptedDbo FOR LOGIN EncryptedDbo;GRANT SELECT ON OBJECT::dbo.CustomerInfo TO EncryptedDbo;
GO

新用户查询数据

使用刚才创建的用户,在SSMS中新打开一个新连接,查询数据:

-- Step 15 -- OPEN a new connection query window using the new user and query data
USE [TestDb]
GOOPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';SELECT *,DescryptedCustomerPhone = CONVERT(CHAR(11), DecryptByKey(EncryptedCustomerPhone))
FROM dbo.CustomerInfoCLOSE SYMMETRIC KEY SymKey_TestDb;
GO

新用户也无法解密EncryptedCustomerPhone,解密后的DescryptedCustomerPhone 字段值为NULL,即新用户无法查看到用户手机号明文,避免了未知用户获取用户手机号等核心数据信息。

而且,还会因为权限的问题,OPEN SYMMETRIC KEY和CLOSE SYMMETRIC KEY报错,可以在Messages窗口中看到:

为新用户赋权限

新用户没有查看加密列数据的权限,如果需要赋予权限,这里需要授权对称密钥DEFINITION权限和非对称密钥CONTROL权限,方法如下:

--Step 16 - Grant permissions to EncryptedDbo
USE [TestDb]
GOGRANT VIEW DEFINITION ON SYMMETRIC KEY::[SymKey_TestDb] TO [EncryptedDbo];
GOGRANT CONTROL ON ASYMMETRIC KEY::[AsymKey_TestDb] TO [EncryptedDbo];
GO

新用户再次查询

赋权限完毕后,新用户再次执行“新用户查询数据”中的查询语句,已经可以正常获取到加密列的明文数据了。

-- Step 15 -- OPEN a new connection query window using the new user and query data
USE [TestDb]
GOOPEN SYMMETRIC KEY SymKey_TestDb
DECRYPTION BY ASYMMETRIC KEY AsymKey_TestDb WITH PASSWORD = 'Password4@Asy';SELECT *,DescryptedCustomerPhone = CONVERT(CHAR(11), DecryptByKey(EncryptedCustomerPhone))
FROM dbo.CustomerInfoCLOSE SYMMETRIC KEY SymKey_TestDb;
GO

再次查询结果展示如下:

最后总结

本篇月报分享了如何利用非对称密钥加密对称密钥,然后使用对称密钥加密用户数据,即混合密钥的方式实现SQL Server列加密技术,以此来最大限度保护用户核心数据信息安全的同时,又最大限度降低了加密解密对的性能损失。

MSSQL · 最佳实践 · 使用混合密钥实现列加密相关推荐

  1. MSSQL · 最佳实践 · SQL Server备份策略

    摘要 在上一期月报中我们分享了SQL Server三种常见的备份技术及工作方式,本期月报将分享如何充分利用三者的优点来制定SQL Server数据库的备份和还原策略以达到数据库快速灾难恢复能力. 上期 ...

  2. MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server

    title: MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server author: 风移 摘要 至今,我们完成了SQL Server备份还原专题系列七篇月报分 ...

  3. MSSQL - 最佳实践 - 如何打码隐私数据列

    摘要 在SQL Server安全系列专题月报分享中,我们已经分享了:如何使用对称密钥实现SQL Server列加密技术.使用非对称密钥加密方式实现SQL Server列加密.使用混合密钥实现SQL S ...

  4. MSSQL · 最佳实践 · 利用文件组实现冷热数据隔离备份方案

    摘要: 摘要 在SQL Server备份专题分享中,前四期我们分享了:三种常见的数据库备份.备份策略的制定.如何查找备份链以及数据库的三种恢复模式与备份之间的关系.本次月报我们分享SQL Server ...

  5. 使用MaxCompute LOAD命令批量导入OSS数据最佳实践—STS方式LOAD开启KMS加密OSS数据

    简介: MaxCompute使用load overwrite或load into命令将外部存储的数据(如:oss)导入到MaxCompute前的授权操作. MaxCompute使用load overw ...

  6. mysql如何打码隐私数据列_MSSQL - 最佳实践 - 如何打码隐私数据列

    摘要 在SQL Server安全系列专题月报分享中,我们已经分享了:如何使用对称密钥实现SQL Server列加密技术.使用非对称密钥加密方式实现SQL Server列加密.使用混合密钥实现SQL S ...

  7. 拔得头筹 | 阿里云混合云荣膺IPv6最佳实践奖

    简介:10月21日,由全球IPv6论坛及下一代互联网国家工程中心主办的"2021全球IPv6下一代互联网峰会"在广州南沙开幕.作为下一代互联网产业领域的全球性年度盛会,来自全球产业 ...

  8. 技术分享 | 混合云模式下SaaS端前端最佳实践

    导读:集成开放平台采用的是混合云部署架构,包含两个大的组件,管理控制台和引擎.管理控制台是SaaS的,部署在公有云,按租户隔离.引擎部署在客户私有云.一套SaaS版的管理控制台如何适配不同客户的引擎, ...

  9. 爱奇艺携手网心科技构建下一代混合CDN,入选IDC中国边缘云最佳实践

    近日,国际权威分析机构IDC正式发布<中国边缘云最佳实践,2022>(以下简称<报告>),爱奇艺携手网心科技"构建下一代混合分发传输网络(CDN),为互联网视频打造极 ...

最新文章

  1. 轨迹系列1——一种基于路网图层的GPS轨迹优化方案
  2. android启动流程之lk,Android系统之LK启动流程分析(一)
  3. 理工男有多香?一张桌子、一条视频,股价狂涨13.51%!网友:我看到了乔布斯!...
  4. Android安全加密:消息摘要Message Digest
  5. [云炬python3玩转机器学习] 6-4 在线性回归模型中使用梯度下降法
  6. bzoj1079: [SCOI2008]着色方案
  7. SpringSecurity权限控制之异常处理方式三
  8. 汇编语言编译器masm_计算机汇编语言和指令操作
  9. windows7计算机用户账户,win7系统删除用户账户的方法(图文)
  10. attodiskbenchmarks(磁盘传输速率检测)_硬盘坏了可以修复吗?电脑硬盘检测?
  11. 安卓端gis_通图采集手机版(GIS数据采集软件)V1.31 安卓版
  12. 怎么做Web应用压力测试?
  13. 百度问答怎么引流,百度知道引流技巧
  14. 联想用u盘重装系统步骤_联想u盘重装win10系统详细图文教程
  15. Java并发指南1:并发基础与Java多线程
  16. 程序员的算法趣题Q55: 平分蛋糕
  17. 《途客圈创业记:不疯魔,不成活》导读
  18. mybatis之(Oracle,MySql)批量更新
  19. EKS自动扩容-方式一:ASG负载检测自动扩容功能
  20. BZOJ 4808 二分图最大点独立集

热门文章

  1. 汇编语言--常见转移指令
  2. gets函数在使用上要注意什么问题
  3. python三十六:shelve模块
  4. POJ-1094 Sorting it All Out
  5. IOS的UI基础02
  6. Calendar的获取变化日期
  7. Dijkstra算法的另一种证明
  8. html+js浏览器检测
  9. php排字符串的高低位怎么区分,PHP-根据字符串和所用字体计算字符串所占宽高...
  10. spring cloud 学习之 服务注册和发现(Eureka)