原文转自:http://space.itpub.net/17203031/viewspace-695700
存储过程、函数、包等结构,表示了软件系统的业务逻辑和领域逻辑。将业务逻辑组织在数据层之上,特别是数据库软件中,是一种比较传统和常见的做法。虽然这种方式与时下流行的设计理念有差异,但是在实际工作中却有着很多优势。
作为领域逻辑的代表,具体的过程实现对软件企业来说,是一笔重要的无形资产财富,是需要额外进行保护的。但是在Oracle中,我们是可以直接的看到各种函数逻辑的实现。所以,我们需要一种手段,保护在Oracle数据字典中保存的源代码信息。
在Oracle中,推出了Wrap技术,既可以实现代码的加密,使用户不能够直接获取到程序代码的DDL语句,同时不会影响到程序代码的执行。在最新的Oracle版本中,提供了两种方式进行Wrap加密。
ü Wrap命令行工具,可以在命令行中实现源代码文件的加密;
ü Dbms_ddl包,其中包括的方法也可以实现在PL/SQL中进行代码的加密;
1、非Wrap使用时的情况
首先,我们可以查看在没有进行Wrap处理的时候,Oracle如何进行源代码保存。
演示代码,本文中将使用该段SP作为演示内容。
//存储过程代码
create or replace procedure P_WRAP_TEST_NC
( o_vc_message out varchar2) is
begin
dbms_output.put_line('Wrap Test Procedure Working !');
end P_WRAP_TEST_NC;
当没有进行Wrap处理的时候,我们可以通过DBMS_METADATA和user_source等数据字典工具查看到源代码。
--无wrap过程
SQL> create or replace procedure P_WRAP_TEST_NC
(
o_vc_message out varchar2
)
is
begin
dbms_output.put_line('Wrap Test Procedure Working !');
end P_WRAP_TEST_NC;
/
Procedure created//成功创建存储过程;
//使用dbms_metadata获取生成ddl;
SQL> set serveroutput on size 10000;
SQL> exec dbms_output.put_line(dbms_metadata.get_ddl(object_type => 'PROCEDURE',name => 'P_WRAP_TEST_NC'));
CREATE OR REPLACE PROCEDURE "SYS"."P_WRAP_TEST_NC"
( o_vc_message out varchar2) is
begin
dbms_output.put_line('Wrap Test Procedure Working !');
end P_WRAP_TEST_NC;
PL/SQL procedure successfully completed
//通过数据字典视图,查看源代码;
SQL> select line,text from user_source where name='P_WRAP_TEST_NC';
LINE TEXT
---------- --------------------------------------------------------------------------------
1 procedure P_WRAP_TEST_NC
2 (
3 o_vc_message out varchar2
4 )
5 is
6 begin
7 dbms_output.put_line('Wrap Test Procedure Working !');
8 end P_WRAP_TEST_NC;
9
10
10 rows selected
2、使用Wrap命令行工具进行加密处理
使用Wrap命令行处理是比较传统的源代码加密手段。思路和过程如下:
1. 将编写好并且调试好的程序,保存为.sql源代码文件,保存在本地磁盘上;
2. 通过命令行工具wrap,将源代码文件处理为加密过的文件(通常为.plb格式)。此时的文件内容,已经是加密过的;
3. 在Oracle的命令行中执行处理过的加密文件。Oracle可以将加密信息识别为正确的代码信息,并且将加密文保存在数据字典中;
4. 开发人员要妥善保管源代码文件,防止丢失;
下面进行过程演示:
首先,将存储过程定义文件p_wrap_test_nc保存为.sql文件,存入c盘根目录,名称为p_wrap_test_nc.sql,之后进行处理。
//命令行处理
E:\>wrap iname=p_wrap_test_nc.sql oname=p_res_nc.plb
PL/SQL Wrapper: Release10.2.0.1.0- Production on星期三5月 18 13:10:46 2011
Copyright (c) 1993, 2004, Oracle. All rights reserved.
Processing p_wrap_test_nc.sql to p_res_nc.plb
Wrap工具有两个参数,iname和oname。Iname指定的进行处理的文件名称,而oname指定的是处理后的输出文件。
此时如果打开输出文件,可以看到加密过的密文代码:
create or replace procedure P_WRAP_TEST_NC wrapped
a000000
93 ce
bmPSrzSW+JbvbB0IrfiI/oW92IYwg0zwfyisfI45kJpkzm6pla+NJokfFPdh3plfljn9C1nb
w3O1Zdpo9ZxuTivH2iNAtzHVSfeEjowmNvtLZd6IVzY9f4oEfz5krpcsJuGBN6u5IwMCeYI2
MTT9hjiE/+3uwnVOQwJ1GSxTNNEpkte9Tuws/sGy+FHlNX6DnVLt+Pv3Jz4d
(篇幅原因,有删节…)
/
接下来,通过执行这些加密文件,来创建对象。
//执行生成的代码文件
SQL> @c:\p_res_nc.plb
Procedure created
之后,通过执行存储过程,来确定对象创建。
--执行成功
SQL> set serveroutput on size 10000;
SQL> var x varchar2(100);
SQL> exec P_WRAP_TEST_NC(:x);
Wrap Test Procedure Working !
PL/SQL procedure successfully completed
SQL> print x
x
---------
说明,数据库中已经建立了该对象,可以执行成功。接下来,我们通过查看数据字典信息确定是否加密。
//获取源文件
SQL> exec dbms_output.put_line(dbms_metadata.get_ddl(object_type => 'PROCEDURE',name => 'P_WRAP_TEST_NC'));
CREATE OR REPLACE PROCEDURE "SYS"."P_WRAP_TEST_NC" wrapped
a000000
7
93 ce
bmPSrzSW+JbvbB0IrfiI/oW92IYwg0zwfyisfI45kJpkzm6pla+NJokfFPdh3plfljn9C1nb
w3O1Zdpo9ZxuTivH2iNAtzHVSfeEjowmNvtLZd6IVzY9f4oEfz5krpcsJuGBN6u5IwMCeYI2
MTT9hjiE/+3uwnVOQwJ1GSxTNNEpkte9Tuws/sGy+FHlNX6DnVLt+Pv3Jz4d
(篇幅原因,有省略……)
PL/SQL procedure successfully completed
//检查数据字典信息
SQL> select line,text from user_source where name='P_WRAP_TEST_NC';
LINE TEXT
---------- --------------------------------------------------------------------------------
1 procedure P_WRAP_TEST_NC wrapped
bmPSrzSW+JbvbB0IrfiI/oW92IYwg0zwfyisfI45kJpkzm6pla+NJokfFPdh3plfljn9C1nb
w3O1Zdpo9ZxuTivH2iNAtzHVSfeEjowmNvtLZd6IVzY9f4oEfz5krpcsJuGBN6u5IwMCeYI2
MTT9hjiE/+3uwnVOQwJ1GSxTNNEpkte9Tuws/sGy+FHlNX6DnVLt+Pv3Jz4d
结论:使用Wrap命令行加密的原则,就是将源代码独立作为文件单独保存,在数据字典中仅仅保存加密过的密文。这样,就剔除了Oracle数据库作为源代码容器的作用,也就防止业务逻辑和关键信息算法的丢失。
3、使用DBMS_DDL包进行处理
这种方式就是在PL/SQL代码中实现加密处理,DBMS_DDL包有两个处理方法,一个为Wrap的函数,另一个是Create_Wrap的存储过程。
DBMS_DDL.Wrap函数是将一个字符串(或者类似的结构体),作为参数传入其中,返回加密过的代码信息。但是,wrap函数只是将代码加密,并不执行。
调用演示代码如下:
//调用代码
declare
vc_sql varchar2(2000);
vc_wraps varchar2(2000);
begin
vc_sql := 'create or replace procedure P_WRAP_TEST_NC '
||'(o_vc_message out varchar2) is begin'
||' dbms_output.put_line(''Wrap Test Procedure'
||' Working !''); end P_WRAP_TEST_NC;';
vc_wraps := dbms_ddl.wrap(vc_sql);
dbms_output.put_line(vc_wraps);
end;
/
执行之后,结果为:
//执行结果
create or replace procedure P_WRAP_TEST_NC wrapped
a000000
4mpjc088ji+D2FUnX/3WKc5v04wwg0zX7Z4VfI5AOJyeYV1Of8reEsrQUXbCIKODW43Bs
/HMFMe6QQe4yGfIJ+rZ2F5Z2gJ738KL2QqdfgFLSOf5mWrhUs2n2pN2B5DkA+pcnRlWpv
Tw1rYfqBm+ZWuyhxTGQBOjysNDzGc0JqvCkjyMyqmD/+HdT2Fkw=
(篇幅原因,有省略……)
PL/SQL procedure successfully completed
注意,此时我们并没有创建存储过程。如果我们此时调用,会是失败。
SQL> var x varchar2(100);
SQL> exec P_WRAP_TEST_NC(:x); //执行存储过程;
begin P_WRAP_TEST_NC(:x); end;
ORA-06550:第1行,第7列:
PLS-00201: identifier 'P_WRAP_TEST_NC' must be declared
ORA-06550:第1行,第7列:
PL/SQL: Statement ignored
DBMS_DDL包的另一个方法create_wrapped,作用就是更进一步。该方法能够直接将源代码进行加密后创建。
--create_wrapped
SQL> declare
2 vc_sql varchar2(2000);
3 --vc_wraps varchar2(2000);
4 begin
5 vc_sql := 'create or replace procedure P_WRAP_TEST_NC '
6 ||'(o_vc_message out varchar2) is begin'
7 ||' dbms_output.put_line(''Wrap Test Procedure'
8 ||' Working !''); end P_WRAP_TEST_NC;';
10 dbms_ddl.create_wrapped(vc_sql);
11 end;
12 /
PL/SQL procedure successfully completed
此时,执行存储过程,如下。
SQL> exec P_WRAP_TEST_NC(:x);
Wrap Test Procedure Working !
PL/SQL procedure successfully completed
x
---------
此时,数据字典的内容,就必然是加密过的内容。
SQL> exec dbms_output.put_line(dbms_metadata.get_ddl(object_type => 'PROCEDURE',name => 'P_WRAP_TEST_NC'));
CREATE OR REPLACE PROCEDURE "SYS"."P_WRAP_TEST_NC" wrapped
a000000
89 c6
4mpjc088ji+D2FUnX/3Wv04wwg0zX7Z4VfI5AOJZDxyeYV1Of8reEsrQUXbCIKODW43Bs
/HMFMe6QQe4yGfIJ+rZ2FJ738KL2Qqd6zOfgFLSOf5mWrhUs2n2pN2B5DkA+pcnRlWpv
Tw1rYfqBm+ZWuyhxTGQBOjysNDzGc0JqvCkjyMyqmD/+HdT2Fkw=
PL/SQL procedure successfully completed
Create_wrapped方法,的确实现了加密。
使用Wrap代码的注意问题:
Wrap技术可以实现对源代码的保护,企业核心算法资源的保护。但是,使用的时候,最后在投产前测试再进行加密过程,而且采用额外的代码管理手段实现对源文件的保护管理。
此外,一些对象,如触发器等,是不能进行加密处理的。这种情况下,需要进行一些变通处理。
建议只对核心算法进行加密处理,防止由于算法本身问题,引起的调试和应用问题。