金仓数据库KingbaseES PLSQL代码加密
关键字
KingbaseES、PLSQL、代码加密、人大金仓、KingbaseES、
代码加密概述
在某些情况下,我们所编写的PLSQL代码中可能含有机密信息,为了不使这些机密信息泄露出去,KingbaseES提供了加密PLSQL代码的功能。在KingbaseES中,有两种方式可以为PLSQL代码进行加密——使用PLSQL Wrapper 工具、使用系统包DBMS_DDL中的子程序。我们可以使用代码加密功能为PLSQL中的包体、存储过程和函数进行加密,对外隐藏这些程序的实现细节。
使用PLSQL Wrapper 工具进行代码加密
Wrapper工具是KingbaseES实例下的一个程序,位于bin目录。使用该程序可以加密一个包含PLSQL代码的文件,该文件中相应的包体、存储过程和函数都会被加密。其具体用法如下:
wrap iname=<input_file> [ oname=<output_file> ]
其中,“input_file”是待加密文件的绝对路径,“output_file”指定了加密以后生成的结果文件的绝对路径,如果省略了“oname=<output_file>”,则wrap工具会在当前文件夹下生成一个跟待加密文件同名且后缀为.plb的结果文件。注意上述用法的等号左右都不能有空格。对于加密以后生成的结果文件可以在ksql工具中作为脚本运行,用法如下:
\i <output_file>
其中,“output_file”是结果文件的绝对路径。以下的示例说明了使用Wrapper工具进行代码加密的具体用法。
step 1: 创建一个待加密的sql文件secret.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
DBMS_OUTPUT.PUT_LINE('T1 Id: ' || all_id(i).id);
END LOOP;
END;
/
CREATE OR REPLACE FUNCTION wrapfunc (n INTEGER) RETURN INTEGER /* PLSQL 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;
/
step 2: 首先切换到KingbaseES实例的bin目录下,然后使用Wrapper工具将secret.sql文件加密。并在对应文件夹下生成secret.plb结果文件。
./wrap iname=/home/xiejianbin/secret/secret.sql oname=/home/xiejianbin/secret/secret.plb
step 3:查看加密的结果文件secret.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
AMqplClEWG2jhSOoI/pMUcwbXdfVo4+DsEPlSpMBGozCgDZ5G9RUQa8oCaoE
FC6BWg2b9+qYRYLTJxe7hyu94nF4uJmVu8Ggmt4S3nTOxkHXItBle0zojnw/
ykg02W58rDk5TS3RLa1kyKI+Hoxf0w35Wga9Idmq+WObgEsE2gjOCo8EtgyJ
ANlCSh7+Nf5HnVofkqK/U5Nr9pAZSPJvYCIpArRHQ9w22ehSPYGrB6w+W5WT
SyyKjmpDMUnRpSlXeZ5XtvVWIpRbsmNtO4jZ5F96TjCN6V6gZVj1cJWVmS9n
i2KKAQB0HVeqkPvCrHgS
END;
/
CREATE OR REPLACE FUNCTION wrapfunc (n INTEGER) RETURN INTEGER /* PLSQL style comment inside wrapfunc function spec */
AUTHID CURRENT_USER
IS WRAPPED
vCioJASzJ6rHLaQ/YM+GdYLv5DE3BBgrWzisTOjeP4ZOhNM3e1FN0k6u0FU/
+WODZzfIozyrfY80wJ8PBbB1M8Uk16jCnNko3vg0O3cPI4BN02eUBUQORzQY
2wVKl0vtp0FXNyfHzVDdC5FebijwSCBRsx+N/yVCmK2ZaFQB1p4EmoUUAXk5
7d8o8z931QstHHgtodPosoR+TobWxvwdC3yaj8PPoY+b3mLXhOBhF895die/
8ofvs8Qj40kYTHXUmxkSwbV+DGpirLkzziSDjSeII7f3aJnQJe70nlUlYAUr
OFkavRu7McUIRHr/z/4HECdcwmijQXKbTJqtXknLpl9KW7tMsFMDE5c49QvB
8RZKoOn1RcfMHr420j1qME8W
END;
/
对比secret.sql文件和secret.plb文件发现,建表和查询等单条语句没有被加密,而创建存储过程和函数体的语句已经被加密。
step 4: 在ksql中执行secret.plb结果文件。
执行结果创建表、存储过程和函数的动作都已完成。
step 5: 从系统表sys_proc中查询已创建存储过程和函数的源代码,发现它们都已被加密,无法查看。
使用DBMS_DDL中的子程序进行代码加密
在KingbaseES的系统包DBMS_DDL中提供了两个子程序为代码加密,分别是DBMS_DDL.WRAP和DBMS_DDL.CREATE_WRAPPED。下面将分别介绍这两个子程序的用法和功能。
3.1 使用DBMS_DDL.WRAP加密代码
子程序 DBMS_DDL.WRAP 以 “CREATE [ OR REPLACE ]”开头的创建包体、函数和存储过程的语句作为输入,并返回该语句对应的加密语句。语法格式如下:
DBMS_DDL.WRAP (ddl VARCHAR2) RETURN VARCHAR2;
其中,参数ddl 指定了用于创建一个包体、函数、存储过程的以“CREATE [ OR REPLACE ]”开头的语句。如果参数不是以“CREATE [ OR REPLACE ]”开头的语句,则报错“向 DBMS_DDL.WRAP 输入的内容不是合法的PLSQL 单元”。该函数将返回 32k 字节以内已加密的字符串。值得注意的是,该函数只返回对应的已加密语句,但是并不执行该语句。我们可以使用返回的已加密语句去执行相应的创建包体、函数、存储过程的动作。以下的示例说明了使用DBMS_DDL.WRAP进行代码加密的具体用法。
step 1: 调用DBMS_DDL.WRAP加密创建函数的语句。
\set SQLTERM /
select dbms_ddl.wrap(
'create or replace function func4 return int is
begin
NULL;
return 3;
end;'
);
/
step 2: 使用返回的加密语句来创建函数。
create or replace function func4 return int is WRAPPED
YdNNhvXpx6ZZu9XuYrgfBNCXxun3YuNQZEPgr2tPCbddKy3schhp1FXL1q8WkKJ3
END;
/
显示使用加密语句成功地创建了函数func4.
step 4: 调用已创建的函数。
3.2 使用DBMS_DDL.CREATE_WRAPPED加密代码
子程序 DBMS_DDL.CREATE_WRAPPED的功能是创建一个包体、函数或存储过程。它的实现流程是将以参数形式输入的 “CREATE [ OR REPLACE ] 语句”转换为加密后的 “CREATE [ OR REPLACE ] 语句”,并执行转换后的加密语句。即该过程将加密与执行语句合为一体。语法格式如下:
DBMS_DDL.CREATE_WRAPPED (ddl VARCHAR2);
其中,参数ddl 指定了用于创建一个包体、函数、存储过程的以“CREATE [ OR REPLACE ]”开头的语句。跟DBMS_DDL.WRAP类似,如果参数不是以“CREATE [ OR REPLACE ]”开头的语句,则也会报错。 以下的示例说明了使用DBMS_DDL.CREATE_WRAPPED进行代码加密的具体用法。
step 1: 调用DBMS_DDL.CREATE_WRAPPED加密并执行创建函数的语句。
\set SQLTERM /
call dbms_ddl.create_wrapped(
'create or replace function func5 return int is
begin
NULL;
return 4;
end;'
);
/
step 2: 调用已创建的函数func5,调用结果如图6所示,表明函数创建成功。
step 3: 从系统表sys_proc中查询已创建函数func5的源代码,发现已被加密,无法查看。
代码加密中的注意事项
- 不能加密触发器的 PLSQL 源代码。要隐藏触发器的实现细节,可以将它们放在子程序中,然后通过加密子程序的方式来加密触发器,然后再编写一个调用该子程序的触发器来实现触发功能。
- 代码加密只能加密包体,而不能加密包规范。不加密包规范可以允许其他开发人员查看使用包或类型所需的信息。加密包体可以防止泄露包的实现细节。
- 不能编辑加密后的文件。如果加密的文件需要更改,必须先编辑原始文本,然后再将其加密。
- 调用 DBMS_DDL的子程序进行代码加密时,请使用完全限定的包名称 SYS.DBMS_DDL,以避免在有人创建名为DBMS_DDL 的本地包或定义公共同义词 DBMS_DDL 时发生名称冲突。
参考资料