一、需求说明
公司的项目有个需求:在存储过程中对数据进行加密,所以要自己编写Oracle函数进行相关的操作。Oracle自带的DBMS_CRYPTO包提供了对加密算法的支持,不过只支持一些常见的加密解密算法,比如AES256、MD5等。现在要进行国密算法的加密,尝试了下可行性分析:
- 网络上无法查询到有关Oracle SM4加密算法的相关信息,只有Java和其他语言(Python、C、JavaScript)版本。
- 从github上查询到Java版本的SM4加密算法的代码,总共代码约有500行(包含ECB与CBC模式的加密、解密以及相关的工具方法),其中和ECB加密直接相关的代码有160行
- Oracle实现sm4加密算法需要理解该加密算法的原理,该加密算法的底层包含对底层字节的操作以及位运算,不容易理解并且不容易实现。
- Oracle存储过程的语法以及位运算的语法不是很熟悉
经过可行性分析,决定退而求其次,在Oracle中调用java代码。刚开始觉得不可思议,Oracle中还能调用Java代码,在网上搜索了一下,还真有这种方式。
二、方法实现
1、环境配置
需要本机安装PLSQL与Oracle instant client,这两个软件的版本必须一致,也就是说如果你的PLSQL是32位的,instant client也必须是32位的,如果是64位的,另一个也要是64位的。再进行一些必要的操作就可以连接远程数据库。参考这篇文章:https://blog.csdn.net/lys1220/article/details/86689256。
2、具体做法
-
在java resouces目录下新建Java类
java source文件夹是用来存放java方法的,里面的代码通过orale中的jdk编译,可以在存储过程中直接运行。
-
在这个文件中写Java代码
create or replace and compile java source named MyTest as public class MyTest { public static String entry(String s) { return s; } }
代码的第一行是填好类名与文件名自动生成的。创建完成后执行一遍就会在java classes文件夹下生成对应的.class文件
在functions文件夹下创建一个函数
Oracle的函数和存储过程很像,函数必须返回值,存储过程不用返回值。
create or replace function MYTEST(v1 in varchar2) return varchar2
as language java name
'MyTest.entry(java.lang.String) return java.lang.String';
创建完成后执行一遍
-
运行函数
SELECT MyTest('DSASASWEDSFSRS') FROM DUAL;
3、导入jar包的方式
loadjava -r -f -verbose -resolve -user dbname/password@instancename "C:\Documents and Settings\Administrator\桌面\sm-algorithm.jar"
dropjava -r -f -verbose -resolve -user dbname/password@instancename "C:\Documents and Settings\Administrator\桌面\sm-algorithm.jar"
上面的命令是加载java的jar包,下面的命令是卸载。相较于上面的方式能够一次性加载更多的类