当前位置:网站首页>对存储过程进行加密和解密(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联系我或跟帖,在此非常感谢!
边栏推荐
- Bit operation ==c language 2
- Or in SQL, what scenarios will lead to full table scanning
- Web3.0 series distributed storage IPFs
- Memory ==c language 1
- Fiddler simulates the interface test
- 单片机(MCU)最强科普(万字总结,值得收藏)
- Why does the starting service report an error when installing MySQL? (operating system Windows)
- VS Code指定扩展安装位置
- Fiddler break point
- The new activity of "the arrival of twelve constellations and goddesses" was launched
猜你喜欢
Memory ==c language 1
ArcGIS operation: converting DWG data to SHP data
官媒关注!国内数字藏品平台百强榜发布,行业加速合规健康发展
Postman interface test VI
SolidWorks工程图中添加中心线和中心符号线的办法
request对象对请求体,请求头参数的解析
The Himalaya web version will pop up after each pause. It is recommended to download the client solution
ORM--逻辑关系与&或;排序操作,更新记录操作,删除记录操作
The method of word automatically generating directory
Agile course training
随机推荐
Why are social portals rarely provided in real estate o2o applications?
Applet sliding, clicking and switching simple UI
Postman interface test II
Bean 作⽤域和⽣命周期
ES类和对象、原型
The landing practice of ByteDance kitex in SEMA e-commerce scene
Analyze Android event distribution mechanism according to popular interview questions (II) -- event conflict analysis and handling
Advanced function learning in ES6
Introduction to automated testing framework
Deep understanding of UDP, TCP
Win10安装VS2015
ORM模型--数据记录的创建操作,查询操作
ORM模型--关联字段,抽象模型类
ORM model -- creation and query of data records
Or in SQL, what scenarios will lead to full table scanning
The combination of over clause and aggregate function in SQL Server
ORM -- query type, association query
STM32产品介绍
Wallys/IPQ6010 (IPQ6018 FAMILY) EMBEDDED BOARD WITH ON-BOARD WIFI DUAL BAND DUAL CONCURRENT
Word自动生成目录的方法