对存储过程进行加密和解密(SQL 2008/SQL 2012)

用于加密的存储过程 (sp_EncryptObject) :


 存储过程(sp_EncryptObject)加密的方法是在存储过程,函数,视图的“As”位置前加上“with encryption”;如果是触发器,就在“for”位置前加“with encryption”。

如果触发器是{ AFTER | INSTEAD OF} 需要修改下面代码"For"位置:

if objectproperty(object_id(@Object),'ExecIsAfterTrigger')=0 set @Replace='As' ; else set @Replace='For ';

存储过程完成代码:

View Code

如果SQL Server 2012,请修改下面两个位置的代码。在SQL Server 2012,建议在使用throw来代替raiserror。

 

 

 

解密方法:


 解密过程,最重要采用异或方法:

[字符1]经过函数 fn_x(x)加密变成[加密后字符1],如果我们已知[加密后字符1],反过来查[字符1],可以这样:

[字符1]  =  [字符2]  ^  fn_x([字符2])  ^  [加密后字符1]

 

这里我列举一个简单的例子:

复制代码
--创建加密函数(fn_x)
if object_id('fn_x') is not null drop function fn_x
go
create function fn_x
(
    @x nchar(1)
)returns nchar(1)
as
begin
return(nchar((65535-unicode(@x))))
end
go
declare @nchar_1_encrypt nchar(1),@nchar_2 nchar(1)


--对字符'A'进行加密,存入变量@nchar_1_encrypt
set @nchar_1_encrypt=dbo.fn_x(N'A') 


--參考的字符@nchar_2
set @nchar_2='x' 

--算出@nchar_1_encrypt 加密前的字符
select nchar(unicode(@nchar_2)^unicode(dbo.fn_x(@nchar_2))^unicode(@nchar_1_encrypt)) as [@nchar_1]

/*
@nchar_1
--------------------
A
*/
复制代码

 

[注]:  从SQL Server 2000至 SQL Server 2012 采用异或方法都可以解密

 

用于解密的存储过程(sp_DecryptObject):


 

View Code

 如果SQL Server 2012,请修改下面两个位置的代码。方法类似于前面的加密过程:

 

 

 

搭建测试环境:


在一个测试环境中(DB: Test),先执行上面的加密存储过程(sp_EncryptObject)和解密存储过程(sp_EncryptObject);再创建两个表:TableA & TableB

复制代码
use test
go
--创建表: TableA & TableB
if object_id('myTableA') is not null drop table myTableA
if object_id('myTableB') is not null drop table myTableB
go
create table myTableA (ID int identity,data nvarchar(50),constraint PK_myTableA primary key(ID))
create table myTableB (ID int ,data nvarchar(50),constraint PK_myTableB primary key(ID))
go
复制代码

接下来,我们要创建6个未加密的对象(对象类型包含 'P','V','TR','FN','IF','TF'):

 1.视图(myView):

View Code

2.触发器(MyTrigger):

View Code

3.存储过程(MyProc):

View Code

4.用户定义表值函数(TF)(MyFunction_TF):

View Code

5.内联表值函数(IF) (MyFunction_IF):

View Code

6.标量函数(FN)(MyFunction_FN):

View Code

 

 当执行完了上面的1-6步骤的脚本,我们通过查询系统视图sys.sql_modules,可以看到未加密前的定义信息:

select b.name as object,b.type,a.definition
    from sys.sql_modules a 
        inner join sys.objects b on b.object_id=a.object_id
        where b.create_date>=convert(date,getdate())
        order by b.object_id

 

加密测试:


 

下面我就通过调用加密存储过程(sp_EncryptObject),一次性对它们进行加密:

use test
go
exec sp_EncryptObject 'all'
go

当我们再查回系统视图sys.sql_modules,会发现definition列返回的是null值,说明定义内容已经给加密:

 

 解密测试:


 

解密过程,必须在DAC连接SQL Server,我们这里例子是从 SSMS(SQL Server Management Studio) 查询编辑器启动 DAC,如图:

 

解密存储过程(sp_DecryptObject),只能一次对一个存储过程、函数、视图或触发器,进行解密:

use test
go
exec sp_DecryptObject MyTrigger
go

 

当定义内容长度超过4000,我们可以指定@MaxLength的值,如:

exec sp_DecryptObject fn_My,20000
go

这里(fn_My)是一个函数,定义内容超过了8000:

... ...

posted @ 2015-07-21 14:06  倾城风云  阅读(430)  评论(0编辑  收藏  举报