我试图复制Oracle DB中java中存在的加密/解密方法,以便在Java中加密的数据可以通过Oracle Function解密.
以下是java代码:
package com.encr;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class EncrUtil
{
private static Cipher cipher = null;
public static void aesInit(String inKey) throws Exception
{
String methodName = "aesInit";
try
{
byte[] inkeyBytes = inKey.getBytes("utf-8");
System.out.println("inkeyBytes="+inkeyBytes.toString());
final SecretKeySpec clientkey = new SecretKeySpec(inkeyBytes, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec iv = new IvParameterSpec(new byte[32]);
cipher.init(Cipher.ENCRYPT_MODE,clientkey,iv);
}
catch (NoSuchAlgorithmException e) {
throw new Exception("NoSuchAlgorithmException", e);
} catch (NoSuchPaddingException e) {
throw new Exception("NoSuchPaddingException", e);
}
}
public static String encrypt(String inData,String inKey)
{
String methodName = "encrypt";
String strCipherText = null;
try
{
if ( null != inData && null != inKey)
{
if(EncrUtil.cipher == null){
EncrUtil.aesInit(inKey);
}
byte[] byteDataToEncrypt = inData.getBytes("utf-8");
System.out.println(byteDataToEncrypt.toString());
byte[] byteCipherText = cipher.doFinal(byteDataToEncrypt);
System.out.println(byteCipherText.toString());
strCipherText = new BASE64Encoder().encode(byteCipherText);
}
}
catch (Exception e) {
String sErrMsg = "Text to be encrypted: " + inData;
sErrMsg = new StringBuffer(methodName).append( sErrMsg) .append( " Message: ") .append(e.getMessage()).toString();
strCipherText = sErrMsg;
}
return strCipherText;
}
public static String decrypt(String inData,String inKey)
{
String methodName = "decrypt";
String strDecryptedText = null;
try
{
byte[] inkeyBytes = inKey.getBytes("utf-8");
final SecretKeySpec clientkey = new SecretKeySpec(inkeyBytes, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
final IvParameterSpec iv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.DECRYPT_MODE,clientkey,iv);
byte[] decodedData = new BASE64Decoder().decodeBuffer(inData);
byte[] byteDecryptedText = cipher.doFinal(decodedData);
strDecryptedText = new String(byteDecryptedText);
}
catch (Exception e) {
String sErrMsg = "Text to be decrypted: " + inData;
sErrMsg = new StringBuffer(methodName).append(sErrMsg) .append( "Message:") .append(e.getMessage()).toString();
strDecryptedText = sErrMsg;
}
return strDecryptedText;
}
public static void main(String[] args)
{
String inKey= "84hf763bht096hnf";
String inData= "Vikram";
System.out.println("Word to be encrypted is "+inData);
String encrypted = EncrUtil.encrypt(inData,inKey);
System.out.println("Encrpted word is"+encrypted);
}
}
我尝试复制的Oracle Pl / sql函数是
CREATE OR REPLACE PACKAGE BODY SYS.enc_dec
AS
encryption_type PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES
+ DBMS_CRYPTO.CHAIN_CBC
+ DBMS_CRYPTO.PAD_PKCS5;
encryption_key RAW (32) := UTL_I18N.STRING_TO_RAW ('84hf763bht096hnf', 'AL32UTF8');
FUNCTION encrypt (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC
IS
encrypted_raw RAW (2000);
BEGIN
DBMS_OUTPUT.PUT_LINE(UTL_RAW.CAST_TO_VARCHAR2(encryption_key));
encrypted_raw := DBMS_CRYPTO.ENCRYPT
(
--src => UTL_RAW.CAST_TO_RAW (p_plainText),
src =>UTL_I18N.STRING_TO_RAW (p_plainText,'AL32UTF8'),
typ => encryption_type,
key => encryption_key
);
RETURN encrypted_raw;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SUBSTR(SQLERRM, 1, 100));
END encrypt;
FUNCTION decrypt (p_encryptedText RAW) RETURN VARCHAR2 DETERMINISTIC
IS
decrypted_raw RAW (2000);
BEGIN
decrypted_raw := DBMS_CRYPTO.DECRYPT
(
src => p_encryptedText,
typ => encryption_type,
key => encryption_key
);
RETURN (UTL_I18N.RAW_TO_CHAR(decrypted_raw,'AL16UTF8'));
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SUBSTR(SQLERRM, 1, 100));
END decrypt;
END;
上述代码完成的加密与java中的加密不同
请告诉我在oracle函数中出错的地方或
请告诉我如何在oracle中添加java方法,在教程中我找不到如何在oracle中包含java的导入.
解决方法:
我能够将Java代码移动到Oracle.我正在为面临类似问题的人写这篇文章.
>登录到通过Putty安装Oracle数据库的服务器(如果是windows,则为命令提示符)
>使用WinSCP将Java文件放在服务器中.
>使用命令查找oracle home中的Java编译器
find / -name javac
>使用Oracle的Java编译器编译Java文件作为数据库使用的Java版本,并且通常使用的Java版本将不同
$ORACLE_HOME/jdk/bin/javac /home/vikram/EncrUtil.java
注意:可以将.class或.jar文件直接加载到数据库中,而不是在数据库服务器上进行编译.但请确保使用与数据库使用的相同版本的Java.
找到oracle使用的java版本
$ORACLE_HOME/jdk/bin/java -version
java version "1.5.0_17"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_17-b03)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_17-b03, mixed mode)
>如果未设置,则设置ORACLE_HOME
export ORACLE_HOME=/database/ora11gr2/product/11.2.0/dbhome_1/
>在路径中添加loadjava的目录(即数据库的bin目录)
export PATH=$PATH:$ORACLE_HOME/bin
注意:如果找不到类的异常,请通过“loadjava”检查路径是否正确设置或是否定义了变量未定义那些
>将类加载到数据库中
loadjava -user <user>/<password>@xxx.xxx.xxx.xxxx:1521:<instance> \
-thin –resolve /home/vikram/ EncrUtil.class
> -resolve用于在加载到数据库之前解析.class文件,因为它易于调试Java外部数据库.
> -thin用于瘦客户端
>加载类后,在其上创建一个包装函数,以便可以在数据库中使用它
CREATE OR REPLACE FUNCTION TEST_DECRYPTOR(indata IN VARCHAR2)
RETURN VARCHAR2 AS
LANGUAGE JAVA NAME ' EncrUtil. decrypt (java.lang.String) return java.lang.String';
CREATE OR REPLACE FUNCTION TEST_ENCRYPTOR (indata IN VARCHAR2)
RETURN VARCHAR2 AS
LANGUAGE JAVA NAME ' EncrUtil. encrypt (java.lang.String) return java.lang.String';
>然后可以像使用任何其他Oracle函数一样使用此函数:
SELECT TEST_ENCRYPTOR('Vikram') FROM DUAL;