Oracle wrap 和 unwrap( 加密與解密) 說明

一. Wrap 說明

官網的說明如下:

A PL/SQL Source Text Wrapping

http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/wrap.htm#LNPLS1744


You can wrap the PL/SQL source text for any of these stored PL/SQL units, thereby preventing anyone from displaying or editing that text:

           (1)Package specification

           (2)Package body

           (3)Type specification

           (4)Type body

           (5)Function

           (6)Procedure


           A file containing wrapped PL/SQL source text is called a wrapped file. Awrapped file can be moved, backed up, or processed by SQL*Plus or the Importand Export utilities.

           To produce a wrapped file, use either the PL/SQL Wrapper utility or a DBMS_DDL subprogram.The PL/SQL Wrapper utility wraps the source text of every wrappable PL/SQL unitcreated by a specified SQL file. The DBMS_DDL subprograms wrap thesource text of single dynamically generated wrappable PL/SQL units.

           Both the PL/SQL Wrapper utility and DBMS_DDL subprograms detecttokenization errors (for example, runaway strings), but not syntax or semanticerrors (for example, nonexistent tables or views).

           Wrapped files are upward-compatible between Oracle Database releases. For example, youcan load files produced by the V8.1.5 PL/SQL Wrapper utility into a V8.1.6 OracleDatabase.


itpub上有篇文章提到了wrap 加密的原理:

           From:http://space.itpub.net/12932950/viewspace-619808


 Oracle加密的原理就是先對源碼進行lz壓縮lzstr,然後對壓縮數據進行SHA-1運算得到40位的加密串shstr,然後將加密串與壓縮串拼接得到shstr+lzstr,然後對拼接後的字符串進行Oracle雙字符轉換(轉換表)。最後將轉換後的字符串進行base64編碼,最終得到wrap的加密串。


   The default file extension for input_file is sql. The default nameof output_file is input_file.plb. Therefore, these commands are equivalent:

           wrapiname=/mydir/myfile

           wrapiname=/mydir/myfile.sql oname=/mydir/myfile.plb

Thisexample specifies a different file extension for input_file and adifferent name for output_file:

           wrapiname=/mydir/myfile.src oname=/yourdir/yourfile.out


wrap 的使用步驟如下:

(1)將我們要加密的sql 語句保存到一個sql文本里。

(2)用wrap 進行處理,指定輸入的sql,即我們第一步的問題,然後指定輸出的路徑和文件名,默認擴展名是plb。

(3)執行我們第二部進過wrap 處理的sql,即plb文件,創建我們的對象.



示例1:wrap funcation

--函數

CREATE OR REPLACE FUNCTION F_DAVE (

 n int

) RETURN string

IS

BEGIN

 IF n = 1 THEN                            

   RETURN 'Dave is DBA!';

 ELSIF n = 2 THEN

   RETURN 'Dave come from AnQing!';                          

 ELSE

   RETURN 'Dave come from HuaiNing!';

 END IF;

END;

/


SYS@dave2(db2)> select F_DAVE(4) fromdual;

F_DAVE(4)

--------------------------------------------------------------------------------

Dave come from HuaiNing!


BTW: 今天羣裏有人問我的blog的例子裏爲啥有安慶,因爲我是安慶懷寧人。


[oracle@db2 ~]$ pwd

/home/oracle

[oracle@db2 ~]$ cat dave.sql

CREATE OR REPLACE FUNCTION F_DAVE (

 n int

) RETURNstring

IS

BEGIN

 IF n = 1 THEN                            

   RETURN 'Dave is DBA!';

 ELSIF n = 2 THEN

   RETURN 'Dave come from AnQing!';                          

 ELSE

   RETURN 'Dave come from HuaiNing!';

 END IF;

END;

/


[oracle@db2 ~]$ wrap iname=dave.sql


PL/SQL Wrapper: Release 10.2.0.1.0-Production on Thu Aug 18 22:59:14 2011


Copyright (c) 1993, 2004, Oracle.  All rights reserved.


Processing dave.sql to dave.plb

[oracle@db2 ~]$ ls

bifile.bbd dave.plb  dave.sql  Desktop log.bbd


[oracle@db2 ~]$ cat dave.plb

CREATE OR REPLACE FUNCTION F_DAVE wrapped

a000000

1

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd

8

10d e7

S9NWrpt8q6tkKEMxCcfYJz2aLF4wgxDQLZ4VfC9AkE6OnV4ydypXGhveHcDg8UXy98WIg6xR

crtc/BRdQJjutbna/9+g0LlaSx87/znV+y926S1AeC0IRi/tjPJTyvJereDdk8mftMo8QMjV

fw0xXn0zVagAawwNVhSAiy/JPTMKkrBkC5ruMwQSTe6JQNq7Q2QtJV0hgQou0rYuet4/gJ5B

wAj75ph6EA==


/


SYS@dave2(db2)> @dave.plb


--再次調用函數,正常使用:

SYS@dave2(db2)> select F_DAVE(4) fromdual;


F_DAVE(4)

--------------------------------------------------------------------------------

Dave come from HuaiNing!


--查看函數源碼,已經加過密了:

SYS@dave2(db2)> select text fromdba_source where name='F_DAVE';


TEXT

--------------------------------------------------------------------------------

FUNCTION F_DAVE wrapped

a000000

1

abcd

abcd

abcd

abcd

abcd

abcd

abcd

abcd


TEXT

--------------------------------------------------------------------------------

abcd

abcd

abcd

abcd

abcd

abcd

abcd

8

10d e7

S9NWrpt8q6tkKEMxCcfYJz2aLF4wgxDQLZ4VfC9AkE6OnV4ydypXGhveHcDg8UXy98WIg6xR

crtc/BRdQJjutbna/9+g0LlaSx87/znV+y926S1AeC0IRi/tjPJTyvJereDdk8mftMo8QMjV


TEXT

--------------------------------------------------------------------------------

fw0xXn0zVagAawwNVhSAiy/JPTMKkrBkC5ruMwQSTe6JQNq7Q2QtJV0hgQou0rYuet4/gJ5B

wAj75ph6EA==



示例2:SYS.DBMS_DDL 函數

           the dbms_ddl package provides wrap functionsand create_wrapped procedures, each of whichwraps the pl/sql source text of a single dynamically generated wrappable pl/sqlunit.

           The DBMS_DDL packagealso provides the exception MALFORMED_WRAP_INPUT (ORA-24230),which is raised if the input to WRAP or CREATE_WRAPPED isnot a valid wrappable PL/SQL unit. (For the list of wrappable PL/SQL units, seethe introduction to "PL/SQLSource Text Wrapping".)


           Each WRAP functiontakes as input a single CREATE statement that creates a wrappablePL/SQL unit and returns an equivalent CREATE statement in which thePL/SQL source text is wrapped. For more information about the WRAP functions,see OracleDatabase PL/SQL Packages and Types Reference.


           Each CREATE_WRAPPED proceduredoes what its corresponding WRAP function does and then runs thereturned CREATE statement, creating the specified PL/SQL unit. Formore information about the CREATE_WRAPPED procedures。


該示例直接參考官方文檔:


DECLARE

package_text  VARCHAR2(32767); --text for creating package spec and body


FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS

BEGIN

  RETURN 'CREATE PACKAGE ' || pkgname || ' AUTHID DEFINER AS

    PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);

    PROCEDURE fire_employee (emp_id NUMBER);

    END ' || pkgname || ';';

 ENDgenerate_spec;


FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS

BEGIN

   RETURN'CREATE PACKAGE BODY ' || pkgname || ' AS

    PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) IS

    BEGIN

      UPDATE employees

        SET salary = salary + amount WHERE employee_id = emp_id;

    END raise_salary;

    PROCEDURE fire_employee (emp_id NUMBER) IS

    BEGIN

      DELETE FROM employees WHERE employee_id = emp_id;

    END fire_employee;

  END ' || pkgname || ';';

 ENDgenerate_body;


BEGIN

package_text := generate_spec('emp_actions');  -- Generate package spec

EXECUTE IMMEDIATE package_text;                -- Create package spec

package_text := generate_body('emp_actions');  -- Generate package body

 SYS.DBMS_DDL.CREATE_WRAPPED(package_text);     -- Create wrapped package body

END;

/


二. Unwrap 說明

   wrap的目的是爲了加密,所以Oracle並沒有提供unwrap 的方法。 itpub上的一些牛人研究了一下這個問題,寫了一些unwrap的代碼。 具體討論的過程,參考itpub的2個帖子:

http://www.itpub.net/thread-1154232-1-2.html

http://www.itpub.net/viewthread.php?tid=1175718&extra=page%3D1&frombbs=1


我這裏貼一下unwrap 的代碼:

/* Formatted on2011/8/18 12:59:54 (QP5 v5.163.1008.3004) */

CREATE OR REPLACE PACKAGE amosunwrapper

IS

  FUNCTION deflate (src IN VARCHAR2)

     RETURN RAW;


  FUNCTION deflate (src IN VARCHAR2, quality IN NUMBER)

     RETURN RAW;


  FUNCTION inflate (src IN RAW)

     RETURN VARCHAR2;

END;

/


CREATE OR REPLACE PACKAGE BODY amosunwrapper

IS

  FUNCTION deflate (src IN VARCHAR2)

     RETURN RAW

  IS

  BEGIN

     RETURN deflate (src, 6);

  END;


  FUNCTION deflate (src IN VARCHAR2, quality IN NUMBER)

     RETURN RAW

  AS

     LANGUAGE JAVA

     NAME 'UNWRAPPER.Deflate( java.lang.String, int ) returnbyte[]';


  FUNCTION inflate (src IN RAW)

     RETURN VARCHAR2

  AS

     LANGUAGE JAVA

     NAME 'UNWRAPPER.Inflate( byte[] ) returnjava.lang.String';

END;

/


/* Formatted on2011/8/18 13:00:16 (QP5 v5.163.1008.3004) */

CREATE OR REPLACE JAVA SOURCE NAMED UNWRAPPER

  AS import java.io.*;

import java.util.zip.*;

public class UNWRAPPER

{

public static String Inflate( byte[] src )

{

try

{

     ByteArrayInputStream bis = new ByteArrayInputStream( src );

     InflaterInputStream iis = newInflaterInputStream( bis );

     StringBuffer sb = newStringBuffer();

for( int c = iis.read(); c != -1; c = iis.read() )

{

       sb.append( (char) c );

}

return sb.toString();

} catch ( Exception e )

{

}

return null;

}

public static byte[] Deflate( String src, intquality )

{

try

{

byte[] tmp = newbyte[ src.length() + 100 ];

     Deflater defl = new Deflater( quality );

     defl.setInput( src.getBytes( "UTF-8" ) );

     defl.finish();

int cnt = defl.deflate( tmp );

byte[] res = newbyte[ cnt ];

for( int i = 0; i < cnt; i++ )

       res = tmp;

return res;

} catch ( Exception e )

{

}

return null;

}

}

/


ALTER JAVA SOURCE UNWRAPPER COMPILE

/


/* Formatted on2011/8/18 13:02:57 (QP5 v5.163.1008.3004) */

--爲了輸出中文,要修改java過程

CREATE OR REPLACE JAVA SOURCE NAMED UNWRAPPER

  AS import java.io.*;

import java.util.zip.*;


public class UNWRAPPER

{

public static String Inflate( byte[] src )

{

try

{

     ByteArrayInputStream bis = newByteArrayInputStream( src );

     InflaterInputStream iis = newInflaterInputStream( bis );

     StringBuffer sb = newStringBuffer();

for( int c = iis.read(); c != -1; c = iis.read() )

{

       sb.append( (char) c );

}

String hello = new String(sb.toString().getBytes("iso8859-1"), "GBK");

return hello;

} catch ( Exception e )

{

}

return null;

}

public static byte[] Deflate( String src, intquality )

{

try

{

byte[] tmp = newbyte[ src.length() + 100 ];

     Deflater defl = new Deflater( quality );

     defl.setInput( src.getBytes( "UTF-8" ) );

     defl.finish();

int cnt = defl.deflate( tmp );

byte[] res = newbyte[ cnt ];

for( int i = 0; i < cnt; i++ )

       res = tmp;

return res;

} catch ( Exception e )

{

}

return null;

}

}

/


ALTER JAVA SOURCE UNWRAPPER COMPILE

/



/* Formatted on2011/8/18 13:00:41 (QP5 v5.163.1008.3004) */

CREATE OR REPLACE PROCEDURE unwrap (o IN VARCHAR, n IN VARCHAR, t IN VARCHAR)

AS

  vWrappedtext    VARCHAR2 (32767);

  vtrimtext       VARCHAR2 (32767);

  vChar           VARCHAR2 (2);

  vRepchar        VARCHAR2 (2);

  vLZinflatestr   VARCHAR2 (32767);

  nLen            INTEGER;

  nLoop           INTEGER;

  nCnt            INTEGER;

  code            VARCHAR (512);

BEGIN

  code :=

     '3D6585B318DBE287F152AB634BB5A05F7D687B9B24C228678ADEA4261E03EB176F343E7A3FD2A96A0FE935561FB14D1078D975F6BC4104816106F9ADD6D5297E869E79E505BA84CC6E278EB05DA8F39FD0A271B858DD2C38994C480755E4538C46B62DA5AF322240DC50C3A1258B9C16605CCFFD0C981CD4376D3C3A30E86C3147F533DA43C8E35E1994ECE6A39514E09D64FA5915C52FCABB0BDFF297BF0A76B449445A1DF0009621807F1A82394FC1A7D70DD1D8FF139370EE5BEFBE09B97772E7B254B72AC7739066200E51EDF87C8F2EF412C62B83CDACCB3BC44EC069366202AE88FCAA4208A64557D39ABDE1238D924A1189746B91FBFEC901EA1BF7CE';--sys.idltranslate表內容存到字符數組


  vtrimtext := '';


  SELECT COUNT (*)

    INTO ncnt

    FROM DBA_SOURCE

   WHERE owner = o AND Name = n AND TYPE = t;


  IF ncnt > 0 AND ncnt <= 5

  THEN

     FOR i IN 1 .. ncnt

     LOOP

        IF i = 1

        THEN

           SELECT RTRIM (SUBSTR (TEXT,

                                 INSTR (TEXT,

                                        CHR (10),

                                        1,

                                        20)

                                 + 1),

                         CHR (10))                     --保存去掉前邊20行的BASE64碼正文

             INTO vLZinflatestr

             FROM DBA_SOURCE

            WHERE owner = o AND Name = n AND TYPE = t AND line = i;

        ELSE

           SELECT text

             INTO vLZinflatestr

             FROM DBA_SOURCE

            WHERE owner = o AND Name = n AND TYPE = t AND line = i;

        END IF;


        vtrimtext := vtrimtext || vLZinflatestr;

     END LOOP;

  END IF;


  vtrimtext := REPLACE (vtrimtext, CHR (10), '');

  nLen := LENGTH (vtrimtext) / 256;

  vWrappedtext := '';


  FOR i IN 0 .. nLen

  LOOP

--ifi< nLen   then

     vWrappedtext :=

        vWrappedtext

        || UTL_ENCODE.base64_decode (

              UTL_RAW.cast_to_raw (SUBSTRB (vtrimtext, 256 * i + 1, 256)));

--else

--vWrappedtext:=vWrappedtext||utl_encode.base64_decode(utl_raw.cast_to_raw(substrb(vtrimtext,64*i+1 ))) ;

--endif;

--DBMS_OUTPUT.PUT_LINE(vWrappedtext);

  END LOOP;


--vWrappedtext:=substr(vWrappedtext,41);

  nLen := LENGTH (vWrappedtext) / 2 - 1;


  vLZinflatestr := '';


  FOR nLoop IN 20 .. nLen

  LOOP                                                            --從第41字節開始

     vChar := SUBSTRB (vWrappedtext, nLoop * 2 + 1, 2);

     vLZinflatestr :=

        vLZinflatestr || SUBSTR (code, TO_NUMBER (vChar, 'XX') * 2 + 1, 2); --從字符串變量匹配

--DBMS_OUTPUT.PUT_LINE(vLZinflatestr);

  END LOOP;


--DBMS_OUTPUT.PUT_LINE(vLZinflatestr);

DBMS_OUTPUT.PUT_LINE (amosunwrapper.inflate (vLZinflatestr));

END;

/


黃煒弄了一個界面的Unwrap軟件,下載地址:

           破解(Unwrap) 10, 11G PLSQL

http://www.hellodba.com/reader.php?ID=36&lang=cn

0_1313653122EijE.gif


unwrap 我們第一節創建的F_DAVE函數:

0_1313653127Z25m.gif


      不過Oracle 對一些對象進行加密的同時,也提供了代碼,比如DBMS_ROWID包。 對於該包使用unwrap 和 直接從dba_source 查詢的結果是一致的,而且dba_source 還提供了註釋。


SQL>exec unwrap('SYS','DBMS_ROWID','PACKAGE BODY');

SQL>select * from dba_source where name='DBMS_ROWID';


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章