问题描述
我在下面有一个 Java 6 函数:
I have a Java 6 function below:
import java.net.*;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.xml.bind.DatatypeConverter;
public class decryptSEK {
public static void main(String[] args) {
String encryptedSek = args[0];
String appKey = args[1];
byte[] appKey32b = DatatypeConverter.parseBase64Binary(appKey);
String decryptedSek = decryptBySymmetricKey(encryptedSek, appKey32b);
System.out.println(decryptedSek);
}
public static String decryptBySymmetricKey(String encryptedSek, byte[] appKey) {
Key aesKey = new SecretKeySpec(appKey, "AES"); // converts bytes(32 byte random generated) to key
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // encryption type = AES with padding PKCS5
cipher.init(Cipher.DECRYPT_MODE, aesKey); // initiate decryption type with the key
byte[] encryptedSekBytes = DatatypeConverter.parseBase64Binary(encryptedSek); //Base64.getDecoder().decode(encryptedSek); // decode the base64 encryptedSek to bytes
byte[] decryptedSekBytes = cipher.doFinal(encryptedSekBytes); // decrypt the encryptedSek with the initialized cipher containing the key(Results in bytes)
// String decryptedSek = Base64.getEncoder().encodeToString(decryptedSekBytes); // convert the decryptedSek(bytes) to Base64 StriNG
String decryptedSek = DatatypeConverter.printBase64Binary(decryptedSekBytes);
return decryptedSek; // return results in base64 string
} catch(Exception e) {
return "Exception; "+e;
}
}
}
当我将上述内容构建为类文件然后运行 java -classpath 时.解密SEK
它运行良好,输出符合预期.我为 Java 6 安装了 JCE,所以它运行良好.
When I build the above as class file and then run java -classpath . decryptSEK
it works well and the output is as expected. I installed JCE for Java 6, so it works well.
但是当我将其转换为 Oracle 程序以在服务器上运行时,如下所示:
But when I convert this into an Oracle program to run on server like below:
--DECRYPT SEK
create or replace JAVA SOURCE NAMED decryptSEK AS
import java.net.*;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import javax.xml.bind.DatatypeConverter;
public class decryptSEK {
public static void main(String[] args) {
String encryptedSek = args[0];
String appKey = args[1];
byte[] appKey32b = DatatypeConverter.parseBase64Binary(appKey);
String decryptedSek = decryptBySymmetricKey(encryptedSek, appKey32b);
System.out.println(decryptedSek);
}
public static String decryptSEKcall(String encryptedSek,String appKey)
{
byte[] appKey32b = DatatypeConverter.parseBase64Binary(appKey);
String decryptedSek = decryptBySymmetricKey(encryptedSek, appKey32b);
System.out.println(decryptedSek);
return decryptedSek;
}
public static String decryptBySymmetricKey(String encryptedSek, byte[] appKey) {
Key aesKey = new SecretKeySpec(appKey, "AES");
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] encryptedSekBytes = DatatypeConverter.parseBase64Binary(encryptedSek);
byte[] decryptedSekBytes = cipher.doFinal(encryptedSekBytes);
String decryptedSek = DatatypeConverter.printBase64Binary(decryptedSekBytes);
return decryptedSek;
} catch(Exception e) {
return "Exception; "+e;
}
}
}
/
CREATE OR REPLACE FUNCTION decryptSEK_func(P_ENCRYPTSEK VARCHAR2,P_APPKEY VARCHAR2)
RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'decryptSEK2.decryptSEKcall( java.lang.String,java.lang.String )
return java.lang.String';
select decryptSEK_func( 's8U+CjS8zKEmwmpCs7HnmTYKpx6rMwEdXVk/g8fNBhVMzKlFxkA1WemvUX00evh8',
'SpRstt3iYywGQlI8U8SQfOA3jajkZpJGjlI4sPeVk7A=')encryptsek from dual;
它抛出以下错误:
Exception: java.security.InvalidKeyException: Illegal key size or default parameters
我已经安装了 JCE 扩展文件,它似乎可以在命令提示符下运行,但在我将其更改为 Oracle 时却无法运行.我哪里出错了?
I have installed the JCE extension files and it seems to work on command prompt, but not when I change it to Oracle. Where I am going wrong?
推荐答案
我强烈建议使用 DBMS_CRYPTO 包.它确实支持 AES/ECB/PKCS5Padding
加密,您只需要设置正确的类型"即可.调用加密/解密函数时.下面是文档中的相同示例,但加密类型已修改为您在 Java 代码中使用的类型.
Instead of creating your own Java code to do encryption, I would highly recommend using the encryption functionality available in the DBMS_CRYPTO package. It does support AES/ECB/PKCS5Padding
encryption, you will just need to set the proper "type" when calling the encrypt/decrypt functions. Below is the same example from the documentation but with the encryption type modified to what you are using in your Java code.
DECLARE
input_string VARCHAR2 (200) := 'Secret Message';
output_string VARCHAR2 (200);
encrypted_raw RAW (2000); -- stores encrypted binary text
decrypted_raw RAW (2000); -- stores decrypted binary text
num_key_bytes NUMBER := 256 / 8; -- key length 256 bits (32 bytes)
key_bytes_raw RAW (32); -- stores 256-bit encryption key
encryption_type PLS_INTEGER
:= -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_ECB + DBMS_CRYPTO.PAD_PKCS5;
iv_raw RAW (16);
BEGIN
DBMS_OUTPUT.PUT_LINE ('Original string: ' || input_string);
key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);
iv_raw := DBMS_CRYPTO.RANDOMBYTES (16);
encrypted_raw :=
DBMS_CRYPTO.ENCRYPT (src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),
typ => encryption_type,
key => key_bytes_raw,
iv => iv_raw);
-- The encrypted value "encrypted_raw" can be used here
decrypted_raw :=
DBMS_CRYPTO.DECRYPT (src => encrypted_raw,
typ => encryption_type,
key => key_bytes_raw,
iv => iv_raw);
output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
/
这篇关于Java 6 函数在命令行中工作,但不适用于 Oracle 服务器 (AES 256)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!