人大金仓数据库KingbaseES PLSQL代码加密

131 阅读6分钟

金仓数据库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的源代码,发现已被加密,无法查看。

代码加密中的注意事项

  1. 不能加密触发器的 PLSQL 源代码。要隐藏触发器的实现细节,可以将它们放在子程序中,然后通过加密子程序的方式来加密触发器,然后再编写一个调用该子程序的触发器来实现触发功能。
  2. 代码加密只能加密包体,而不能加密包规范。不加密包规范可以允许其他开发人员查看使用包或类型所需的信息。加密包体可以防止泄露包的实现细节。
  3. 不能编辑加密后的文件。如果加密的文件需要更改,必须先编辑原始文本,然后再将其加密。
  4. 调用 DBMS_DDL的子程序进行代码加密时,请使用完全限定的包名称 SYS.DBMS_DDL,以避免在有人创建名为DBMS_DDL 的本地包或定义公共同义词 DBMS_DDL 时发生名称冲突。

参考资料

《KingbaseES PLSQL过程语言参考手册》

《KingbaseES 插件参考手册》