原文地址:http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/wrap.htm
本文描述如何使用独立的wrap工具以及DBMS_DDL程序包混淆,或者加密PL/SQL源代码。通过混淆(加密)PL/SQL单元,可以在交付PL/SQL应用时隐藏源代码和实现细节。
1、什么是混淆?
混淆(Obfuscation),或者加密PL/SQL单元就是隐藏PL/SQL源代码的过程。加密可以使用wrap工具以及DBMS_DDL子程序实现。wrap工具从命令行运行,处理一个SQL输入文件,例如一个SQL*Plus安装脚本。DBMS_DDL子程序加密单个动态生成的PL/SQL程序,例如CREATE PROCEDURE命令。
使用它们加密PL/SQL源代码的优点如下:
其他开发人员不易误用你的代码,或者商业竞争对手难以查看你的算法。
源代码不能通过数据字典视图USER_SOURCE、ALL_SOURCE或者DBA_SOURCE进行查看。
SQL*Plus能够处理加密的源文件。
Import和Export工具支持加密文件。可以备份或者移动加密的程序。
1.1、技巧
混淆(加密)PL/SQL单元时,记住以下技巧:
加密程序包或者对象类型时,只加密包体,而不加密包规范。这样可以允许其他开发人员使用该程序包或者类型时查看需要的信息,但是他们不能查看实现细节。
加密文件中的PL/SQL源代码不能进行编辑。要改变加密的PL/SQL代码,编辑原始源文件并再次加密。
确认源代码的所有重要部分都进行了加密,发布之前使用文本编辑器查看加密文件。
1.2、局限
加密PL/SQL源代码时具有以下局限性:
虽然加密一个编译单元有利于隐藏算法并且使得逆向工程难以进行,Oracle不建议将它作为一个隐藏密码或者表名称的安全方法。加密可以阻止大多数用户查看源代码,但可能不是全部。
加密工具不会加密触发器的源代码。为了隐藏触发器的内容,可以编写只包含调用加密程序的单行触发器。
加密仅仅检测分词错误,而不会检测语法或者语义错误,例如表或视图是否存在。这些错误在PL/SQL编译时或者执行加密后的输出文件时进行检测。
加密的PL/SQL程序单元不能被导入先前(更低的)版本中。加密的编译单元在Oracle版本中向上兼容,但不能向下兼容。
wrap工具的局限
由于源代码通过PL/SQL编译器进行解析,而不是SQL*Plus,因此不能在PL/SQL代码中使用SQL*Plus的DEFINE定义替换变量。可以在不进行加密的其他SQL语句中使用替换变量。
加密文件中会删除大多数的注释。参见下文。
DBMS_DDL的局限
如果调用DBMS_SQL.PARSE解析DBMS_DDL.WRAP的输出(当为超过32767字节的文本定义VARCHAR2A或者VARCHAR2S类型时),需要将LFFLG参数设置为FALSE。否则DBMS_SQL.PARSE添加新行到加密单元中,破坏程序单元。
2、使用wrap工具加密PL/SQL代码
wrap工具处理一个输入的SQL文件,并且仅加密文件中的PL/SQL单元,例如程序包规范、包体、函数、过程、类型规范或者类型体。它不会加密匿名块、触发器或者非PL/SQL代码。
要运行wrap工具,使用以下语法在操作系统提示符后输入wrap命令:
wrap iname=input_file [oname=output_file]
等号两边不能包含任何空格。
input_file是包含SQL语句的文件名称。如果忽略文件扩展名,默认使用.sql。例如,以下命令是等价的:
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql
也可以指定其他的文件扩展名:
wrap iname=/mydir/myfile.src
output_file是创建的加密文件名称。oname可选,因为输出文件名默认为输入文件名加上扩展名.plb。例如,以下命令是等价的:
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql name=/mydir/myfile.plb
也可以使用oname指定一个不同的文件名和扩展名:
wrap iname=/mydir/myfile name=/yourdir/yourfile.out
2.1、wrap工具的输入与输出文件
输入文件可以包含任何SQL语句的组合。大多数语句不会进行更改。定义子程序、程序包或者对象类型的CREATE语句被加密;它们的程序体被替换为一种PL/SQL编译器能够理解的加密形式。
以下CREATE语句会被加密:
CREATE [OR REPLACE] FUNCTION function_name
CREATE [OR REPLACE] PROCEDURE procedure_name
CREATE [OR REPLACE] PACKAGE package_name
CREATE [OR REPLACE] PACKAGE BODY package_name
CREATE [OR REPLACE] TYPE type_name AS OBJECT
CREATE [OR REPLACE] TYPE type_name UNDER type_name
CREATE [OR REPLACE] TYPE BODY type_name
语句CREATE [OR REPLACE] TRIGGER,以及[DECLARE] BEGIN .. END块不加密。其他所有SQL语句不变,直接写入输出文件。
被加密单元中的所有注释行,除了CREATE OR REPLACE头部的注释,或者C-style的注释(使用/* */界定),都会被删除。
输出文件是一个文本文件,可以像脚本一样在SQL*Plus运行并创建PL/SQL过程、函数以及程序包。使用以下命令运行加密文件:
SQL> @wrapped_file_name.plb;
2.2、运行wrap工具
假设wrap_test.sql文件包含以下内容:
CREATE PROCEDURE wraptest IS
TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
all_emps emp_tab;
BEGIN
SELECT * BULK COLLECT INTO all_emps FROM employees;
FOR i IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id);
END LOOP;
END;
/
要加密该文件,从操作系统提示符中运行以下命令:
wrap iname=wrap_test.sql
wrap工具的输出信息如下:
PL/SQL Wrapper: Release 10.2.0.0.0 on Tue Apr 26 16:47:39 2005
Copyright (c) 1993, 2005, Oracle. All rights reserved.
Processing wrap_test.sql to wrap_test.plb
如果查看文本文件wrap_test.plb的内容,第一行为CREATE PROCEDURE wraptest wrapped并且其他内容进行了加密。
可以在SQL*Plus中运行wrap_test.plb以执行文件中的SQL语句:
SQL> @wrap_test.plb
然后,可以执行创建的过程:
SQL> CALL wraptest();
3、使用DBMS_DDL子程序
DBMS_DDL程序包包含加密单个PL/SQL单元的程序,例如程序包规范、包体、函数、过程、类型规范或者类型体。这些重载的子程序提供了一种加密动态创建的PL/SQL程序单元的机制。
DBMS_DDL程序包包含WRAP函数和CREATE_WRAPPED过程。CREATE_WRAPPED同时加密文本并创建PL/SQL单元。调用加密程序时,使用完全描述的包名,SYS.DBMS_DLL,避免任何命名冲突,或者其他人创建了一个本地的DBMS_DDL程序或DBMS_DDL公共同义词的可能性。输入的CREATE OR REPLACE语句以调用者的权限执行。
DBMS_DDL程序包还提供了MALFORMED_WRAP_INPUT异常(ORA-24230),在输入不是一个有效PL/SQL单元时抛出。
3.1、使用create_wrapped过程
示例A-1说明了如何使用CREATE_WRAPPED动态创建并加密一个程序包规范和包体。
示例 A-1 使用create_wrapped过程加密程序包
DECLARE
-- the package_text variable contains the text to create the package spec and body
package_text VARCHAR2(32767);
FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'CREATE PACKAGE ' || pkgname || ' AS
PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
END ' || pkgname || ';';
END generate_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 || ';';
END generate_body;
BEGIN
package_text := generate_spec('emp_actions'); -- generate package spec
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- create and wrap the package spec
package_text := generate_body('emp_actions'); -- generate package body
SYS.DBMS_DDL.CREATE_WRAPPED(package_text); -- create and wrap the package body
END;
/
-- call a procedure from the wrapped package
CALL emp_actions.raise_salary(120, 100);
当你查看*_SOURCE视图时,emp_actions的源码进行了加密,或者隐藏,以便其他人不能查看代码细节。例如:
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
输出结果如下:
TEXT
---------------------------------------------------------------
PACKAGE emp_actions wrapped
a000000
1f
abcd
...
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24945919/viewspace-746677/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24945919/viewspace-746677/