问题
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;
}
}
}
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.
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;
It throws the following error:
Exception: java.security.InvalidKeyException: Illegal key size or default parameters
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?
回答1:
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;
/
来源:https://stackoverflow.com/questions/64765725/java-6-function-working-in-command-line-but-not-working-on-oracle-server-aes-2