zoukankan      html  css  js  c++  java
  • 存储过程的加密解密

    加密:CREATE PROCEDURE encrypt_this 
             WITH ENCRYPTION  
             AS

    解密:

    CREATE PROCEDURE [dbo].[sp__windbi$decrypt]
    (
    @procedure SYSNAME = NULL ,
    @revfl INT = 1
    )
    AS /*
    王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
    目前这个存储过程只能解密存储过程,至于解密函数、触发器、视图的存储过程本网站会进一步关注,调用形式为:
    exec dbo.sp__windbi$decrypt @procedure,0
    如果第二个参数使用1的话,会给出该存储过程的一些提示。
    --版本2.0
    */
    SET NOCOUNT ON
    IF @revfl = 1
    BEGIN
    PRINT '警告:该存储过程会删除并重建原始的存储过程。'
    PRINT ' 在运行该存储过程之前确保你的数据库有一个备份。'
    PRINT ' 该存储过程通常应该运行在产品环境的一个备份的非产品环境下。'
    PRINT ' 为了运行这个存储过程,将参数@refl的值更改为0。'
    RETURN 0
    END
    DECLARE @intProcSpace BIGINT ,
    @t BIGINT ,
    @maxColID SMALLINT ,
    @intEncrypted TINYINT ,
    @procNameLength INT
    SELECT @maxColID = MAX(subobjid) ,
    @intEncrypted = imageval
    FROM sys.sysobjvalues
    WHERE objid = OBJECT_ID(@procedure)
    GROUP BY imageval
    --select @maxColID as 'Rows in sys.sysobjvalues'
    SELECT @procNameLength = DATALENGTH(@procedure) + 29
    DECLARE @real_01 NVARCHAR(MAX)
    DECLARE @fake_01 NVARCHAR(MAX)
    DECLARE @fake_encrypt_01 NVARCHAR(MAX)
    DECLARE @real_decrypt_01 NVARCHAR(MAX) ,
    @real_decrypt_01a NVARCHAR(MAX)
    DECLARE @objtype VARCHAR(2) ,
    @ParentName NVARCHAR(MAX)
    SELECT @real_decrypt_01a = ''
    --提取对象的类型如是存储过程还是函数,如果是触发器,还要得到其父对象的名称
    SELECT @objtype = type ,
    @parentname = OBJECT_NAME(parent_object_id)
    FROM sys.objects
    WHERE [object_id] = OBJECT_ID(@procedure)
    -- 从sys.sysobjvalues里提出加密的imageval记录
    SET @real_01 = ( SELECT TOP 1
    imageval
    FROM sys.sysobjvalues
    WHERE objid = OBJECT_ID(@procedure)
    AND valclass = 1
    ORDER BY subobjid
    )
    --创建一个临时表
    CREATE TABLE #output
    (
    [ident] [int] IDENTITY(1, 1)
    NOT NULL ,
    [real_decrypt] NVARCHAR(MAX)
    )
    --开始一个事务,稍后回滚
    BEGIN TRAN
    --更改原始的存储过程,用短横线替换
    IF @objtype = 'P'
    SET @fake_01 = 'ALTER PROCEDURE ' + @procedure + ' WITH ENCRYPTION AS
    ' + REPLICATE('-', 40003 - @procNameLength)
    ELSE
    IF @objtype = 'FN'
    SET @fake_01 = 'ALTER FUNCTION ' + @procedure
    + '() RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/ END'
    ELSE
    IF @objtype = 'V'
    SET @fake_01 = 'ALTER view ' + @procedure
    + ' WITH ENCRYPTION AS select 1 as col
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/'
    ELSE
    IF @objtype = 'TR'
    SET @fake_01 = 'ALTER trigger ' + @procedure + ' ON '
    + @parentname
    + ' WITH ENCRYPTION AFTER INSERT AS RAISERROR (''N'',16,10)
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/'
    EXECUTE (@fake_01)
    --从sys.sysobjvalues里提出加密的假的
    SET @fake_encrypt_01 = ( SELECT TOP 1
    imageval
    FROM sys.sysobjvalues
    WHERE objid = OBJECT_ID(@procedure)
    AND valclass = 1
    ORDER BY subobjid
    )
    IF @objtype = 'P'
    SET @fake_01 = 'Create PROCEDURE ' + @procedure
    + ' WITH ENCRYPTION AS
    ' + REPLICATE('-', 40003 - @procNameLength)
    ELSE
    IF @objtype = 'FN'
    SET @fake_01 = 'CREATE FUNCTION ' + @procedure
    + '() RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/ END'
    ELSE
    IF @objtype = 'V'
    SET @fake_01 = 'Create view ' + @procedure
    + ' WITH ENCRYPTION AS select 1 as col
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/'
    ELSE
    IF @objtype = 'TR'
    SET @fake_01 = 'Create trigger ' + @procedure + ' ON '
    + @parentname
    + ' WITH ENCRYPTION AFTER INSERT AS RAISERROR (''N'',16,10)
    /*' + REPLICATE('*', DATALENGTH(@real_01) / 2 - @procNameLength) + '*/'
    --开始计数
    SET @intProcSpace = 1
    --使用字符填充临时变量
    SET @real_decrypt_01 = REPLICATE(N'A', ( DATALENGTH(@real_01) / 2 ))
    --循环设置每一个变量,创建真正的变量
    --每次一个字节
    SET @intProcSpace = 1
    --如有必要,遍历每个@real_xx变量并解密
    WHILE @intProcSpace <= ( DATALENGTH(@real_01) / 2 )
    BEGIN
    --真的和假的和加密的假的进行异或处理
    SET @real_decrypt_01 = STUFF(@real_decrypt_01, @intProcSpace, 1,
    NCHAR(UNICODE(SUBSTRING(@real_01,
    @intProcSpace, 1))
    ^ ( UNICODE(SUBSTRING(@fake_01,
    @intProcSpace, 1))
    ^ UNICODE(SUBSTRING(@fake_encrypt_01,
    @intProcSpace, 1)) )))
    SET @intProcSpace = @intProcSpace + 1
    END
    --通过sp_helptext逻辑向表#output里插入变量
    INSERT #output
    ( real_decrypt )
    SELECT @real_decrypt_01
    -- select real_decrypt AS '#output chek' from #output --测试
    -- -------------------------------------
    --开始从sp_helptext提取
    -- -------------------------------------
    DECLARE @dbname SYSNAME ,
    @BlankSpaceAdded INT ,
    @BasePos INT ,
    @CurrentPos INT ,
    @TextLength INT ,
    @LineId INT ,
    @AddOnLen INT ,
    @LFCR INT --回车换行的长度
    ,
    @DefinedLength INT ,
    @SyscomText NVARCHAR(4000) ,
    @Line NVARCHAR(255)
    SELECT @DefinedLength = 255
    SELECT @BlankSpaceAdded = 0 --跟踪行结束的空格。注意Len函数忽略了多余的空格
    CREATE TABLE #CommentText
    (
    LineId INT ,
    Text NVARCHAR(255) COLLATE database_default
    )
    --使用#output代替sys.sysobjvalues
    DECLARE ms_crs_syscom CURSOR LOCAL
    FOR
    SELECT real_decrypt
    FROM #output
    ORDER BY ident FOR READ ONLY
    --获取文本
    SELECT @LFCR = 2
    SELECT @LineId = 1
    OPEN ms_crs_syscom
    FETCH NEXT FROM ms_crs_syscom INTO @SyscomText
    WHILE @@fetch_status >= 0
    BEGIN
    SELECT @BasePos = 1
    SELECT @CurrentPos = 1
    SELECT @TextLength = LEN(@SyscomText)
    WHILE @CurrentPos != 0
    BEGIN
    --通过回车查找行的结束
    SELECT @CurrentPos = CHARINDEX(CHAR(13) + CHAR(10),
    @SyscomText, @BasePos)
    --如果找到回车
    IF @CurrentPos != 0
    BEGIN
    --如果@Lines的长度的新值比设置的大就插入@Lines目前的内容并继续
    WHILE ( ISNULL(LEN(@Line), 0) + @BlankSpaceAdded
    + @CurrentPos - @BasePos + @LFCR ) > @DefinedLength
    BEGIN
    SELECT @AddOnLen = @DefinedLength
    - ( ISNULL(LEN(@Line), 0)
    + @BlankSpaceAdded )
    INSERT #CommentText
    VALUES ( @LineId,
    ISNULL(@Line, N'')
    + ISNULL(SUBSTRING(@SyscomText,
    @BasePos,
    @AddOnLen), N'') )
    SELECT @Line = NULL ,
    @LineId = @LineId + 1 ,
    @BasePos = @BasePos + @AddOnLen ,
    @BlankSpaceAdded = 0
    END
    SELECT @Line = ISNULL(@Line, N'')
    + ISNULL(SUBSTRING(@SyscomText, @BasePos,
    @CurrentPos - @BasePos
    + @LFCR), N'')
    SELECT @BasePos = @CurrentPos + 2
    INSERT #CommentText
    VALUES ( @LineId, @Line )
    SELECT @LineId = @LineId + 1
    SELECT @Line = NULL
    END
    ELSE
    --如果回车没找到
    BEGIN
    IF @BasePos <= @TextLength
    BEGIN
    --如果@Lines长度的新值大于定义的长度
    WHILE ( ISNULL(LEN(@Line), 0)
    + @BlankSpaceAdded + @TextLength
    - @BasePos + 1 ) > @DefinedLength
    BEGIN
    SELECT @AddOnLen = @DefinedLength
    - ( ISNULL(LEN(@Line), 0)
    + @BlankSpaceAdded )
    INSERT #CommentText
    VALUES ( @LineId,
    ISNULL(@Line, N'')
    + ISNULL(SUBSTRING(@SyscomText,
    @BasePos,
    @AddOnLen), N'') )
    SELECT @Line = NULL ,
    @LineId = @LineId + 1 ,
    @BasePos = @BasePos
    + @AddOnLen ,
    @BlankSpaceAdded = 0
    END
    SELECT @Line = ISNULL(@Line, N'')
    + ISNULL(SUBSTRING(@SyscomText,
    @BasePos,
    @TextLength
    - @BasePos + 1),
    N'')
    IF LEN(@Line) < @DefinedLength
    AND CHARINDEX(' ', @SyscomText,
    @TextLength + 1) > 0
    BEGIN
    SELECT @Line = @Line + ' ' ,
    @BlankSpaceAdded = 1
    END
    END
    END
    END
    FETCH NEXT FROM ms_crs_syscom INTO @SyscomText
    END
    IF @Line IS NOT NULL
    INSERT #CommentText
    VALUES ( @LineId, @Line )
    SELECT Text
    FROM #CommentText
    ORDER BY LineId
    CLOSE ms_crs_syscom
    DEALLOCATE ms_crs_syscom
    DROP TABLE #CommentText
    -- -------------------------------------
    --结束从sp_helptext提取
    -- -------------------------------------
    --删除用短横线创建的存储过程并重建原始的存储过程
    ROLLBACK TRAN
    DROP TABLE #output














    执行上面的存储过程方法为:
    exec sp_windbi$Decrypt '你要解密的存储过程名',0

    在执行上面的语句后出现错误:
    对象名'sys.sysobjvalues'无效

    主要原因是我们没有用DAC模式登陆,下面是解决办法:
    第一步:允许DAC模式
    (1)如果是在本地服务器做DAC的话用:sqlcmd -A (A一定要大写,要不然不好用哦) 用这个命令就可以很轻松的连接上,连接上以后在里面写语句就可以,语句写玩了要运行GO这个命令。
    (2)如果要做远程连接DAC的话需要用: sqlcmd -S 服务器名 -U sa(一个是sysadmin角色的登陆帐户就可以了)-P(密码)-A就可以了

    启用远程DAC登录选项:
    操作步骤:'程序'->'Sql Server2005'-> '配置工具'-> 'Sql Server 外围应用配置器'-> '功能的外围应用配置器'-> 'DataBase Engine'-> 'DAC' -> '启用远程DAC'

    这样DAC模式就启用成功了,接下来是使用DAC模式登陆。

    第二步:使用DAC模式登陆(关键就在这个地方)
    1,DAC只支持一个窗口
    2,DAC只支持查询窗口, 不支持Object Explorer. 如果你想在SQL Server Management Studio中用DAC连, 你应该用个正常的连接, 然后用DAC打开查询窗口.

    下面是操作步骤:
    1,先用有sysadmin角色的用户登陆SQL Server Management Studio,随便sa就可以了;
    2,新建数据库引擎查询,在弹出的连接对话框中,服务器名称改为 ADMIN:服务器名称;然后,选项->连接属性->连接到数据库 改为加密存储过程所在的数据库->连接即可.
    3,最后执行上面的存储过程方法;

    以上是解决办法,希望对大家有用,上面转载的有些不知道出处,如果侵犯了您的权益请及时联系,我将在第一时间更新...

  • 相关阅读:
    [bbk2342] 第47集 Chapter 09Optimizing Sore Perations(02)
    [bbk2345] 第50集 Chapter 12Optimizing Sore Perations(05)
    [bbk2343] 第48集 Chapter 12Optimizing Sore Perations(03)
    [bbk2863] 第54集 Chapter 14Using Oracle Dasta Storage Structures Efficiently(00)
    [bbk2515] 第51集 Chapter 13Using Oracle Blokcs Efficeintly[00]
    [bbk2341] 第46集 Chapter 09Optimizing Sore Perations(01)
    [bbk2863] 第54集 Chapter 13Using Oracle Blokcs Efficeintly[03]
    [bbk2668] 第53集 Chapter 13Using Oracle Blokcs Efficeintly[02]
    [bbk2344] 第49集 Chapter 12Optimizing Sore Perations(04)
    QT 中的模态和非模态对话框
  • 原文地址:https://www.cnblogs.com/wenghaowen/p/3240585.html
Copyright © 2011-2022 走看看