当前位置:网站首页>对存储过程进行加密和解密(SQL 2008/SQL 2012)
对存储过程进行加密和解密(SQL 2008/SQL 2012)
2022-07-07 07:45:00 【蝈蝈(GuoGuo)】
开始:
在网络上,看到有SQL Server 2000和SQL Server 2005 的存储过程加密和解密的方法,后来分析了其中的代码,发现它们的原理都是一样的。后来自己根据实际的应用环境,编写了两个存储过程,一个加密存储过程(sp_EncryptObject),和一个解密存储过程(sp_EncryptObject),它们可以应用于SQL Server中的储过程,函数,视图,以及触发器。
感觉这两个存储过程蛮有意思的,拿来与大家分享;如果你看过类似的,就当作重温一下也好。
用于加密的存储过程 (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):


Use master
Go
if object_ID('[sp_DecryptObject]') is not null
Drop Procedure [sp_DecryptObject]
Go
create procedure sp_DecryptObject
(
@Object sysname, --要解密的对象名:函数,存储过程,视图或触发器
@MaxLength int=4000 --评估内容的长度
)
as
set nocount on
/* 1. 解密 */
if not exists(select 1 from sys.objects a where a.object_id=object_id(@Object) And a.type in('P','V','TR','FN','IF','TF'))
begin
--SQL Server 2008
raiserror 50001 N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。'
--SQL Server 2012
--throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1
return
end
if exists(select 1 from sys.sql_modules a where a.object_id=object_id(@Object) and a.definition is not null)
begin
--SQL Server 2008
raiserror 50001 N'对象没有加密!'
--SQL Server 2012
--throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1
return
end
declare @sql nvarchar(max) --解密出来的SQL语句
,@imageval nvarchar(max) --加密字符串
,@tmpStr nvarchar(max) --临时SQL语句
,@tmpStr_imageval nvarchar(max) --临时SQL语句(加密后)
,@type char(2) --对象类型('P','V','TR','FN','IF','TF')
,@objectID int --对象ID
,@i int --While循环使用
,@Oject1 nvarchar(1000)
set @objectID=object_id(@Object)
set @type=(select a.type from sys.objects a where [email protected])
declare @Space4000 nchar(4000)
set @Space4000=replicate('-',4000)
/*
@tmpStr 会构造下面的SQL语句
-------------------------------------------------------------------------------
alter trigger Tr_Name on Table_Name with encryption for update as return /**/
alter proc Proc_Name with encryption as select 1 as col /**/
alter view View_Name with encryption as select 1 as col /**/
alter function Fn_Name() returns int with encryption as begin return(0) end/**/
*/
set @Oject1=quotename(object_schema_name(@objectID))+'.'+quotename(@Object)
set @tmpStr=
case
when @type ='P ' then N'Alter Procedure '[email protected]+' with encryption as select 1 as column1 '
when @type ='V ' then N'Alter View '[email protected]+' with encryption as select 1 as column1 '
when @type ='FN' then N'Alter Function '[email protected]+'() returns int with encryption as begin return(0) end '
when @type ='IF' then N'Alter Function '[email protected]+'() returns table with encryption as return(Select a.name from sys.types a) '
when @type ='TF' then N'Alter Function '[email protected]+'() returns @t table(name nvarchar(50)) with encryption as begin return end '
else 'Alter Trigger '[email protected]+'on '+quotename(object_schema_name(@objectID))+'.'+(select Top(1) quotename(object_name(parent_id)) from sys.triggers a where [email protected])+' with encryption for update as return '
end
set @[email protected]+'/*'[email protected]
set @i=0
while @i < (ceiling(@MaxLength*1.0/4000)-1)
begin
set @[email protected]+ @Space4000
Set @[email protected]+1
end
set @[email protected]+'*/'
------------
set @imageval =(select top(1) a.imageval from sys.sysobjvalues a where [email protected] and a.valclass=1)
begin tran
exec(@tmpStr)
set @tmpStr_imageval =(select top(1) a.imageval from sys.sysobjvalues a where [email protected] and a.valclass=1)
rollback tran
-------------
set @tmpStr=stuff(@tmpStr,1,5,'create')
set @sql=''
set @i=1
while @i<= (datalength(@imageval)/2)
begin
set @[email protected]+isnull(nchar(unicode(substring(@tmpStr,@i,1)) ^ unicode(substring(@tmpStr_imageval,@i,1))^unicode(substring(@imageval,@i,1)) ),'')
Set @i+=1
end
/* 2. 列印 */
declare @patindex int
while @sql>''
begin
set @patindex=patindex('%'+char(13)+char(10)+'%',@sql)
if @patindex >0
begin
print substring(@sql,1,@patindex-1)
set @sql=stuff(@sql,1,@patindex+1,'')
end
else
begin
set @patindex=patindex('%'+char(13)+'%',@sql)
if @patindex >0
begin
print substring(@sql,1,@patindex-1)
set @sql=stuff(@sql,1,@patindex,'')
end
else
begin
set @patindex=patindex('%'+char(10)+'%',@sql)
if @patindex >0
begin
print substring(@sql,1,@patindex-1)
set @sql=stuff(@sql,1,@patindex,'')
end
else
begin
print @sql
set @sql=''
end
end
end
end
Go
exec sp_ms_marksystemobject 'sp_DecryptObject' --标识为系统对象
go
如果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:

... ...

小结:
虽然,上面的脚本,我已经在SQL Server 2008 R2 和SQL Server 2012测试过,但无法避免一些未知错误 。如果你自己在测试上面的脚本,请不要在生产环境上。如果你在应用过程,碰到有什么问题或有什么意见和建议可以发email联系我或跟帖,在此非常感谢!
边栏推荐
- Gauss elimination
- Wallys/IPQ6010 (IPQ6018 FAMILY) EMBEDDED BOARD WITH ON-BOARD WIFI DUAL BAND DUAL CONCURRENT
- Integer inversion
- 虚数j的物理意义
- 终于可以一行代码也不用改了!ShardingSphere 原生驱动问世
- In addition to the objective reasons for overtime, what else is worth thinking about?
- 网上可以开炒股账户吗安全吗
- Delete a record in the table in pl/sql by mistake, and the recovery method
- 嵌入式背景知识-芯片
- STM32产品介绍
猜你喜欢

喜马拉雅网页版每次暂停后弹窗推荐下载客户端解决办法

Google Colab装载Google Drive(Google Colab中使用Google Drive)

Basic chapter: take you through notes

A wave of open source notebooks is coming

【学习笔记-李宏毅】GAN(生成对抗网络)全系列(一)

ORM -- grouping query, aggregation query, query set queryset object properties

Wallys/IPQ6010 (IPQ6018 FAMILY) EMBEDDED BOARD WITH ON-BOARD WIFI DUAL BAND DUAL CONCURRENT

Deep understanding of UDP, TCP

Postman interface test I

VS Code指定扩展安装位置
随机推荐
Parameter sniffing (1/2)
The landing practice of ByteDance kitex in SEMA e-commerce scene
Pit using BigDecimal
Agile course training
14th test
Win10 installation vs2015
ORM--分组查询,聚合查询,查询集QuerySet对象特性
Deconvolution popular detailed analysis and nn Convtranspose2d important parameter interpretation
Write it into the SR table in the way of flinksql. It is found that the data to be deleted has not been deleted. Refer to the document https://do
Introduction to uboot
conda离线创建虚拟环境
Hcip first day notes sorting
AI moves from perception to intelligent cognition
STM32中AHB总线_APB2总线_APB1总线这些是什么
The combination of over clause and aggregate function in SQL Server
CONDA creates virtual environment offline
flink. CDC sqlserver. You can write the DEM without connector in sqlserver again
Before joining the chain home, I made a competitive product analysis for myself
Some test points about coupon test
ORM -- query type, association query