您可以为以下PL/SQL 单元加密 PL/SQL 源文本,从而防止任何人使用数据字典显示该文本:
包体
函数
存储过程
包含加密的 PL/SQL 源文本的文件称为加密文件。客户端工具可以移动、备份或直接导入处理。
要生成加密文件,请使用 PL/SQL Wrapper 实用程序或 DBMS_DDL 子程序。 PL/SQL Wrapper 实用程序加密由指定 SQL 文件创建的每个可加密 PL/SQL 单元的源文本。 DBMS_DDL 子程序加密单个动态生成的可加密 PL/SQL 单元的源文本 。
PL/SQL Wrapper 实用程序和 DBMS_DDL 子程序都检测标记化错误(例如,失控的字符串),但不会检测语法或语义错误(例如,不存在的表或视图)。
加密 PL/SQL 源文本不是隐藏密码或表名的安全方法。
不能加密触发器的 PL/SQL 源文本。
要隐藏触发器的实现细节,请将它们放在存储的子程序中,加密子程序,并编写一个调用子程序的触发器。
仅加密包体,而不是包规范。
不加密规范是允许其他开发人员查看使用包或类型所需的信息(参见示例 A-5)。加密包体可以防止他们看到包的实现。
仅在完成编辑文本后才对文件进行加密。
不能编辑加密的文件。如果加密的文件需要更改,必须编辑原始文本,然后将其加密。
在分发加密文件之前,请在文本编辑器中查看它并确保所有重要部分都已加密。
PL/SQL Wrapper 实用程序采用单个 SQL 文件并生成一个等效的文本文件,其中加密了每个可加密 PL/SQL 单元的 PL/SQL 源文本。
有关可加密的 PL/SQL 单元的列表,请参阅“PL/SQL源文本加密”的介绍。
PL/SQL Wrapper 实用程序无法连接到 KingbaseES 数据库。要运行 PL/SQL Wrapper 实用程序,请在操作系统提示符下输入以下命令(等号周围没有空格):
wrap iname=input_file [ oname=output_file ]
input_file是包含 SQL 语句的任意组合的现有文件的名称。
output_file是 PL/SQL Wrapper 实用程序创建的文件的名称——被加密的文件。
注意
如果input_file是一个加密文件,则output_file是再次加密的文件。
input_file 的默认文件扩展名是 sql。 output_file 的默认名称是 input_file.plb。 因此,这些命令是等价的:
wrap iname=/kesdir/kesfile
wrap iname=/kesdir/kesfile.sql oname=/kesdir/kesfile.plb
此示例为 指定不同的文件扩展名input_file和不同的名称output_file:
wrap iname=/mydir/myfile.src oname=/yourdir/yourfile.out
您可以将output_file在 Ksql 中作为脚本运行。例如:
test=# \i kesfile.plb
示例 A-1 具有两个可加密 PL/SQL 单元的 SQL 文件
这个例子显示了一个 SQL 文件的文本 wrap_test.sql,它包含两个可加密的 PL/SQL 单元——过程 wrapproc 和函数 wrapfunc 。该文件还包含注释和一些SQL语句。
/* 这条注释不会改变 */ create table t1(id int); / insert into t1 values(1),(2),(3); / SELECT COUNT(*) FROM t1; / /* 加密两条CREATE 语句 */ CREATE PROCEDURE wrapproc AUTHID CURRENT_USER /* C style comment in procedure declaration */ IS TYPE t1_tab IS TABLE OF t1%ROWTYPE INDEX BY INTEGER; all_id t1_tab; BEGIN SELECT * BULK COLLECT INTO all_id FROM t1; FOR i IN 1..3 LOOP /* C style in pl/sql source */ DBMS_OUTPUT.PUT_LINE('T1 Id: ' || all_id(i).id); END LOOP; END; / CREATE OR REPLACE FUNCTION wrapfunc ( n INTEGER ) RETURN INTEGER /* PL/SQL style comment inside wrapfunc function spec */ AUTHID CURRENT_USER -- PL/SQL style comment inside wrapfunc function spec, but will be deleted. IS fun_a1 INTEGER := 0; fun_a2 INTEGER := 1; BEGIN IF n = 1 THEN -- terminating condition RETURN fun_a1; ELSIF n = 2 THEN RETURN fun_a2; /* terminating condition */ ELSE RETURN wrapfunc(n-2) + wrapfunc(n-1); /* recursive invocations */ END IF; END; /
示例 A-2 使用 PL/SQL 加密实用程序加密文件
此示例使用 PL/SQL Wrapper 实用程序来加密 wrap_test.sql 并显示已加密的文件 wrap_test.plb。 加密文件加密(变得不可读)过程 wrapproc 和函数 wrapfunc 的 PL/SQL 源文本,但将注释保留在加密源之外。 假设操作系统提示符是 >。 加密文件 wrap_test.sql:
> wrap iname=wrap_test.sql
结果:
Processing wrap_test.sql to wrap_test.plb
wrap_test.plb 的内容:
\set SQLTERM / /* 这条注释不会改变 */ create table t1(id int); / insert into t1 values(1),(2),(3); / SELECT COUNT(*) FROM t1; / /* 加密两条CREATE 语句 */ CREATE PROCEDURE wrapproc AUTHID CURRENT_USER /* C style comment in procedure declaration */ IS WRAPPED tEi28mifS2OE24WQ+yecGjUsj6F36jtaPpqsFptzxzPmnTAa+ytnZhtyjby5 w/DwRKHtpTsc/YGdT1LTbNBeDBjFJZ9aAcPJZh4zF7ejhO1M5yOHThhF0VU3 xQky+16gfsF4rZST1VGIe6zKwtkzj6hpryrv8yafr5UHnm0SmF2tN7z9YeAB IvVm6mK+VyNee0dMV8yxL1Z5BZqQe7UzNz9M5gys3MuoY6q7zYlxcwc6KSK0 RQLBvdFY9W7vm5GROMDJ1N/h96f4dbZWpPnxdEJz0VWJT7tT99AWyKOt5eZE vGR743hQbXM91u+X7DglQszFNsrtoqZogDwZG73ylw== END; / CREATE OR REPLACE FUNCTION wrapfunc ( n INTEGER ) RETURN INTEGER /* PL/SQL style comment inside wrapfunc function spec */ AUTHID CURRENT_USER IS WRAPPED VFLIjR+55WAyW9Lw6/g9ZJw8EQ7gAKk3JTPfpj3aocdX+cBYc1QbrVExIa3V D10p/1twjkM4Ss9ISXEqm2t4K5JEPJv8BXErpA1dzTVL8Lzw4vZa8957ZOYg Hk/Kc43CHTbaLYq6/QVsG2nNXNLyM5XPr4ZZY1GC601/2CjIRY3I9dC+muml r2K65AoXRtOv+XSpaIW3ojFbAtfIe4u1PPDi9lrz3ntk5iAeT8pzjcK8nqt2 zTAZ+zJPiKUGiM/qXlRTGbN3R6du1/fH7UoSqzaIA6xKb7NzGUfRtDjCW7js wj0VtmtG1jGst4pDWA5W0zwSu2PDIYigfz88ye/6qbgHdb9pZu+SIlAmtenZ yZzbOHH2f8ftsSk/kK8m+erPAUpSNvPOoFgzYgy4l88YYw== END; /
示例 A-3 运行加密的文件并查看加密的 PL/SQL 单元 在 Ksql 中,此示例运行加密文件wrap_test.plb,创建过程 wrapproc 和函数 wrapfunc 。 选择子程序的文本(被加密,因此不可读),然后调用子程序。
test=# -- Run wrapped file: test=# \i wrap_test.plb CREATE TABLE INSERT 0 3 count ------- 3 (1 row) CREATE PROCEDURE CREATE FUNCTION test=# -- Try to display procedure source text: test=# select prosrc from sys_proc where proname='wrapproc'; test-# / prosrc -------------------------------------------------------------- WRAPPED + tEi28mifS2OE24WQ+yecGjUsj6F36jtaPpqsFptzxzPmnTAa+ytnZhtyjby5+ w/DwRKHtpTsc/YGdT1LTbNBeDBjFJZ9aAcPJZh4zF7ejhO1M5yOHThhF0VU3+ xQky+16gfsF4rZST1VGIe6zKwtkzj6hpryrv8yafr5UHnm0SmF2tN7z9YeAB+ IvVm6mK+VyNee0dMV8yxL1Z5BZqQe7UzNz9M5gys3MuoY6q7zYlxcwc6KSK0+ RQLBvdFY9W7vm5GROMDJ1N/h96f4dbZWpPnxdEJz0VWJT7tT99AWyKOt5eZE+ vGR743hQbXM91u+X7DglQszFNsrtoqZogDwZG73ylw== + END (1 row) test=# test=# -- Try to display function source text: test=# test=# select prosrc from sys_proc where proname='wrapfunc'; test-# / prosrc -------------------------------------------------------------- WRAPPED + VFLIjR+55WAyW9Lw6/g9ZJw8EQ7gAKk3JTPfpj3aocdX+cBYc1QbrVExIa3V+ D10p/1twjkM4Ss9ISXEqm2t4K5JEPJv8BXErpA1dzTVL8Lzw4vZa8957ZOYg+ Hk/Kc43CHTbaLYq6/QVsG2nNXNLyM5XPr4ZZY1GC601/2CjIRY3I9dC+muml+ r2K65AoXRtOv+XSpaIW3ojFbAtfIe4u1PPDi9lrz3ntk5iAeT8pzjcK8nqt2+ zTAZ+zJPiKUGiM/qXlRTGbN3R6du1/fH7UoSqzaIA6xKb7NzGUfRtDjCW7js+ wj0VtmtG1jGst4pDWA5W0zwSu2PDIYigfz88ye/6qbgHdb9pZu+SIlAmtenZ+ yZzbOHH2f8ftsSk/kK8m+erPAUpSNvPOoFgzYgy4l88YYw== + END (1 row) test=#set serverout on test=# BEGIN wrapproc; DBMS_OUTPUT.PUT_LINE('wrapfunc(5) = ' || wrapfunc(5)); END; / T1 Id: 1 T1 Id: 2 T1 Id: 3 wrapfunc(5) = 3
DBMS_DDL 包提供了 WRAP 函数和 CREATE_WRAPPED 过程,它们中的每一个都可以加密单个动态生成的可加密 PL/SQL 单元的 PL/SQL 源文本。 如果 WRAP 或 CREATE_WRAPPED 的输入不是有效的可加密 PL/SQL 单元,则会引发该异常。(有关可加密的 PL/SQL 单元的列表,请参阅“PL/SQL源文本加密”的介绍。)
每个 WRAP 函数将单个 CREATE 语句作为输入,该语句创建一个可加密的 PL/SQL 单元并返回一个等效的 CREATE 语句,其中PL/SQL 源文本已被加密。有关这些WRAP函数的更多信息,请参阅KingbaseES插件参考手册
每个 CREATE_WRAPPED 过程执行其对应的 WRAP 函数所做的事情,然后运行返回的 CREATE 语句,创建指定的 PL/SQL 单元。有关这些CREATE_WRAPPED过程的更多信息,请参阅:KingbaseES插件参考手册
提示
调用 DBMS_DDL 子程序时,请使用完全限定的包名称 SYS.DBMS_DDL,以避免在有人创建名为 DBMS_DDL 的本地包或定义公共同义词 DBMS_DDL 时发生名称冲突。
注意
输入到 WRAP 函数或 CREATE_WRAPPED 过程的 CREATE 语句以调用子程序的用户的权限运行。
示例 A-4 使用 CREATE_WRAPPED 过程动态创建包规范(使用 EXECUTE IMMEDIATE 语句)和加密的包体。
示例 A-5 选择示例 A-4 创建的包的文本 stu_scores ,然后调用过程 stu_scores.raise_score。如果包体被加密,那么调用过程所需的信息将不可读。
示例 A-4 使用 CREATE_WRAPPED 过程创建加密的包体
\set SQLTERM ; CREATE TABLE student (id int, name text, score number); insert into student values(1, 'zhangsan', 100); insert into student values(2, 'lisi', 99); insert into student values(3, 'lihua', 98); \set SQLTERM / DECLARE pkg_text VARCHAR2(32767); -- 创建包规范和包体的文本 FUNCTION generate_spec (pkgname VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN 'CREATE PACKAGE ' || pkgname || ' AUTHID CURRENT_USER AS PROCEDURE raise_score (stu_id NUMBER, amount NUMBER); END ' || pkgname || ';'; END generate_spec; FUNCTION generate_body (pkgname VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN 'CREATE PACKAGE BODY ' || pkgname || ' AS PROCEDURE raise_score (stu_id NUMBER, amount NUMBER) IS BEGIN UPDATE student SET score = score + amount WHERE id = stu_id; END raise_score; END ' || pkgname || ';'; END generate_body; BEGIN pkg_text := generate_spec('stu_scores'); -- 生成包规范文本 EXECUTE IMMEDIATE pkg_text; -- 创建包规范 pkg_text := generate_body('stu_scores'); -- 生成包体文本 SYS.DBMS_DDL.CREATE_WRAPPED(pkg_text); -- 创建加密包体 END; /
选择包文本:
SELECT pkgbodysrc FROM sys_package WHERE pkgname = 'stu_scores';
结果:
pkgbodysrc -------------------------------------------------------------- WRAPPED + sS7LP7io7BJ2UEXlOlhSo0HIIrYrCHL3IE6U7gYU5eGMACwaixq/NwDZ9pZl+ fP512lSl1zUs99jLD2fiOkpAsjtWGvnihfTzebAeKgX8rDo6ONGOk2sohRxJ+ VD52h4ecCDWsGlTEH62AM3CC3aQ9AgeIPPkuE7ftJWkA5WkashX/jnF5/AsQ+ vt5jX/2p/R/boV5jqwpzNzjrwAyf2AV4wSJSRf+tuk+VCtPuUlqDzSIXyzip+ Z983Ri/r1ou7L833 + END
结果:
\set SQLTERM ; select * from student; id | name | score ----+----------+------- 1 | zhangsan | 100 2 | lisi | 99 3 | lihua | 98 (3 rows) call stu_scores.raise_score(3, 2); select * from student; id | name | score ----+----------+------- 1 | zhangsan | 100 2 | lisi | 99 3 | lihua | 100 (3 rows)