Oracle的存储过程加密
Oracle的存储过程加密
Oracle的存储过程加密,顾名思义,就是对Oracle存储过程源码的加密,使得别人看不到你的源码,达到保护的目的,当然不是什么都是需要的,有的项目对安全性要求比较高的时候,就可能会用到,好了,废话不多说了,开始这部分的旅程吧。
首先,Oracle提供了加密方式,--Wrap和DBMS_DDL,当然这两种不光是是对存储过程加密的,函数,包体,类型等都是可以加密的,在此只对存储过程的加密进行解释。
Wrap方式加密
1.用法:
他的用法还是比较简单的,一个命令就可以实现加密,以下是命令的格式
wrap iname=input_file [ oname=output_file ]
以下两种方式是等价的,我的理解是你指定的文件中只要是SQL的statement就可以了,他会默认给一个sql的后缀
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql
其实这样写也是可以的,其实他只是加密一个SQL文件的,我们加密的确实存储过程,只是后缀不一样
wrap iname=/mydir/myfile.src
再看下他的输出。以下两种情况也是等价的。及时你不会指定输出文件是什么,他也会给你指定一个输出的文件,当然你也可以自己指定的,第二行就是和系统默认的指定的一样的。
wrap iname=/mydir/myfile
wrap iname=/mydir/myfile.sql oname=/mydir/myfile.plb
这样写也是可以的,他默认输出的是源文件的名称加上plb的后缀,如果你要执行输出的后缀名的话,也可以这样写,我理解是后缀由你指定的,当然只要加密之后的文件能被Oracle正确解析就好了
wrap iname=/mydir/myfile oname=/yourdir/yourfile.out
notes:如果你拿一个已经加密过的sql文件,再次去用命令加密的话,得到的文件实际上和原来的是一样的,可以尝试下。
Wrap的限制:
1.此方法对加密类似密码的东西,不是很安全。
2.加密后的文件对于一般人来说,是比较安全的,但是对于专业人士来说,也是形同虚设的。
3.不能加密触发器。
4.加密的过程中,是不会检查你的语法错误的,只是在编译的时候会检查。
5.他是向上兼容的,依赖于Oracle的版本,比如是8.1.5的加密文件,可以在8.1.6的版本上跑,但是
8.1.6版本的Oracle加密文件,在8.1.5上不一定能跑。
6.只能加密如下类型,不能加密匿名块
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
Wrap的操作步骤:
不管是在Linux下还是Oracle下,首先保证你能sqlplus的命令能正常运行,即:你的Oracle环境必须装好的,这个时候才可以使用。
Windows下你可以直接打开命令窗口,按照以上格式的输入即可。
wrap iname=wrap_test.sql
输入命令之后
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
如下图,我没有指定输出的文件名,这个时候他就会在我当前的目录下创建一个pro1.plb的文件。
打开之后可以看到:
用Plsql执行加密后的文件
SQL> @wrapped_file_name.plb;
打开之后就是加密后的,这个时候你只能看到存储过程名称
需要注意的是:当你的原始文件中含有注释的话,如果注释是以"--"开头的,也就是行注释,他在加密的时候会删除掉,如果是"/**/"类似C语言的注释的话,不会删除。
Notes:插入的时候是被PLSQL解析的,所以不能插入sqlplus的声明,
DBMS_DDL Subprograms方式加密
DBMS_DDL包含了加密存储过程,函数,类型说明,类型体,包说明,包体,此子程序提供了动态生成PLSQL单元的能力。其实内部就是一个WRAP函数和一个CREATE_WRAPPED存储过程。再加上一个异常处理的单元MALFORMED_WRAP_INPUT。
下面直接给个例子吧
DECLARE
package_text VARCHAR2(32767); -- text for creating package spec & body
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
-- Generate package spec
package_text := generate_spec('emp_actions')
-- Create wrapped package spec
DBMS_DDL.CREATE_WRAPPED(package_text);
-- Generate package body
package_text := generate_body('emp_actions');
-- Create wrapped package body
DBMS_DDL.CREATE_WRAPPED(package_text);
END;
/
-- Invoke procedure from wrapped package
CALL emp_actions.raise_salary(120, 100);
当然调用DBMS_DDL.CREATE_WRAPPED的时候必须保证你的本地没有生命这样的存储过程,或者你在调用的时候要加上SYS.DBMS_DDL.WRAP or SYS.DBMS_DDL.CREATE_WRAPPED,这个时候就得有执行这两个存储过程的权限了。
加密完成之后,查询结果
SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
TEXT
--------------------------------------------------------------------
PACKAGE emp_actions WRAPPED
a000000
1f
abcd
...
这样就成功加密了想要加密的东西。
DBMS_DDL Subprograms限制:
值得注意的是当你调用DBMS_SQL.PARSE这个函数去解析DBMS_DDL.WRAP这个加密的结果的时候,传入的文本超多了32767 bytes,你就必须设置LFFLG为FALSE,否则DBMS_SQL.PARSE这个解析的结果将是混乱的。
好了到此为止,我们的整个旅程就将结束了,东西说的不是很深,并且只是涉及到存储过程的加密,当然了,以此类推,如果你会了存储过程的加密方式,你也就会其他的加密了,知道这些已经够用了,毕竟不是每个项目都能用到此知识点。写的比较乱,主要是我防止日后再用到,能快速查出,备忘而已。