關於pl/sql的程式碼保護

dbqs8710發表於2015-01-16

在開始學習資料庫的時候,總是嘗試手動建立資料庫,安裝完成之後需要執行一些指令碼,總是看到螢幕上閃個不停,可以看到大多數的儲存過程程式碼都是一堆亂碼,最開始還以為是亂碼了。:)有時候心血來潮想看看裡面的程式碼,但是基本上都是看到儲存過程名或者函式名,再細節的程式碼都被遮蔽掉了。
大家在執行awr,ash的時候,也看不到核心的程式碼。所以這些技術細節oracle是不希望開放的。
比如awr,如果看到最關鍵的地方。dbms_workload_repository的內容又是遮蔽的,還是有些讓人鬱悶。
-- call the table function to generate the report
select output from table(dbms_workload_repository.&fn_name( :dbid,
                                                            :inst_num,
                                                            :bid, :eid,
                                                            :rpt_options ));

我們在開發自己的程式的時候,根據具體的需求也可以包含程式碼。當然了是在有這種需求的情況下,要不反倒弄巧成拙。
關於程式碼的加密有幾種方式。
一種是使用wrap命令直接來格式化。這種方式比較直接,操作也很簡單。
比如我們有如下的包宣告。
create or replace package  pack_bonus as
function get_bonus(param1 in number,param2 in number,param3 in number,param4 in number) return number;
function get_bonus(param1 in number,param2 in number,param3 in number) return number;
function get_bonus(param1 in number,param2 in number)return number;
end;
/

直接使用wrap命令就可以加密了,iname是輸入的檔案,oname是輸出檔案。檔名可以自己根據需要來定義。

$ wrap iname=a.sh oname=aaaa.bin

PL/SQL Wrapper: Release 11.2.0.3.0- 64bit Production on Fri Oct 17 08:21:49 2014

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

Processing a.sh to aaaa.bin

>ls -lrt

-rw-r--r-- 1 ora11g dba    305 Oct 17 08:21 a.sh
-rw-r--r-- 1 ora11g dba    309 Oct 17 08:21 aaaa.bin

如果想呼叫的話,直接在sqlplus中執行就可以了。
SQL> @aaaa.bin

Package created.


第二種屬於程式設計級別的,使用dbms_ddl來實現,可以使用wrap和create_wrap來完成加密。
這兩個方法的不同之處在於wrap是加密指定的程式碼,只會把加密之後的內容顯示出來,不會嘗試編譯。
而create_wrap是嘗試編譯加密後的程式碼。
先看一個例子上手。直接呼叫wrap就列印出了加密後的程式碼。

set serveroutput on
declare
i_program varchar2(32767);
begin
i_program:='create or replace package  pack_bonus as
function get_bonus(param1 in number,param2 in number,param3 in number,param4 in number) return number;
function get_bonus(param1 in number,param2 in number,param3 in number) return number;
function get_bonus(param1 in number,param2 in number)return number;
end;
';
dbms_output.put_line(DBMS_DDL.wrap(i_program));
end;
/

create or replace package  pack_bonus wrapped

a000000
369
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
ab
cd
abcd
9
11d
a6
o/obm0C7f2ty/o3UQRhkqAQzXJMwg5m49TOf9b9cFlpZ/0qul3LVYiu4dIvAmYHHywjS/l64
v7L0
v5v+mbI857h0wNIqw6XSXqWZgTLAsiX7mQRrmQSMmXXKNiGUrHGE5tZwcfb8VISUXiqz
R7iBxy2L4Ka
mlS9ZLQ==

PL/SQL procedure successfully completed.


還有一種稍微複雜點的方式,但是也是比較實用的。
定義了dbms_sql.varchar2a型別,可以支援每行32k

declare
  source_code  DBMS_SQL.VARCHAR2A;
  wrap_code    DBMS_SQL.VARCHAR2A;
BEGIN
  SELECT
'create or replace package  pack_bonus as
function get_bonus(param1 in number,param2 in number,param3 in number,param4 in number) return number;
function get_bonus(param1 in number,param2 in number,param3 in number) return number;
function get_bonus(param1 in number,param2 in number)return number;
end;
'
  bulk collect into source_code from dual ;
        
  wrap_code := SYS.DBMS_DDL.WRAP(ddl => source_code,
                              lb  => 1,
                              ub  => source_code.count);

  FOR i IN 1 .. wrap_code.count LOOP
    DBMS_OUTPUT.put_line(wrap_code(i));
  END LOOP;  --直到這個地方,還沒有開始嘗試編譯加密的程式碼,只是列印出來。
  DBMS_DDL.create_wrapped(source_code,source_code.FIRST,source_code.LAST);   --這個步驟是開始嘗試編譯加密後的程式碼
END;
/

輸出如下。
create or replace package  pack_bonus wrapped

a000000
369
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
ab
cd
abcd
9
11d
a6
o/obm0C7f2ty/o3UQRhkqAQzXJMwg5m49TOf9b9cFlpZ/0qul3LVYiu4dIvAmYHHywjS/l64
v7L0
v5v+mbI857h0wNIqw6XSXqWZgTLAsiX7mQRrmQSMmXXKNiGUrHGE5tZwcfb8VISUXiqz
R7iBxy2L4Ka
mlS9ZLQ==

PL/SQL procedure successfully completed.
執行之後就可以看到有一個package物件就建立好了。

SQL> select object_name from user_objects where object_name='PACK_BONUS';

OBJECT_NAME
--------------------------------------------------------------------------------
PACK_BONUS

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29762980/viewspace-1403890/,如需轉載,請註明出處,否則將追究法律責任。

相關文章