Oracle DES 加密研究(Oracle DES加密、Java 解密)

因为工作原因,需要将Oracle中的加密数据读取到Java中进行解密,因为程序并不是通过JDBC直接访问数据库,而是Oracle导出文件的方式(为了避免关键信息在文件传输中泄漏因而加密),所以不能使用Oracle自身的解密方法解密,因而才有了下文。

Oracle加密

加密函数

加密函数代码如下:

create or replace function encrypt_des(p_text varchar2, p_key varchar2) return varchar2 
is
  v_text varchar2(4000);
  v_enc varchar2(4000);
  raw_input RAW(128) ;
  key_input RAW(128) ;
  decrypted_raw RAW(2048);
begin
  v_text := rpad( p_text, (trunc(length(p_text)/8)+1)*8, chr(0));
  raw_input := UTL_RAW.CAST_TO_RAW(v_text);
  key_input := UTL_RAW.CAST_TO_RAW(p_key);
  dbms_obfuscation_toolkit.DESEncrypt(input => raw_input,key => key_input,encrypted_data =>decrypted_raw);
  select utl_raw.cast_to_varchar2(utl_encode.base64_encode(decrypted_raw)) into v_enc from dual;
return v_enc;
end;
/

简单说明一下加密函数:要加密的原文必须是8的整数倍字节,如果不足,会在右侧填充ASCII为0的字符,而不是字符0;如果原文字节整好是8的整数倍会额外添加8个字节的0;代码是v_text := rpad( p_text, (trunc(length(p_text)/8)+1)*8, chr(0));这一句。然后调用
调用函数进行加密DESEncrypt加密,加密完成后,使用base64_encode对密文进行base64加密,并输出结果。

函数调用

select encrypt_des('123456', 'encryptk') from dual;
select encrypt_des('12345678', 'encryptk') from dual;
select encrypt_des('1234567812345678', 'encryptk') from dual;
'123456'是要加密的密文,'encryptk'是用来加密的密钥,必须8字节,如果超过8字节不会报错,但是实际计算中会被截断。
结果如图:


image.png

encrypt_des('123456', 'encryptk') => DCxkHWiXj68=
encrypt_des('12345678', 'encryptk') => RVo37OSWJUcfYVa4klQ0zg==
encrypt_des('1234567812345678', 'encryptk') => RVo37OSWJUfF3nxSbhl12nnrknts79U6

加密分析

密文对比如下:
DCxkHWiXj68=
RVo37OSWJUcfYVa4klQ0zg==
RVo37OSWJUfF3nxSbhl12nnrknts79U6
比较明显的是,对于12345678的加密密文并base64编码后是RVo37OSWJU,原文第二字节同样也是12345678,但是base64编码后在JUfF3nxSbhl12nnrknts79U6中,很明显与第一字节的密文相差甚远,所以可以肯定的是Oracle中DES加密,并不是采用了ECB模式,极有可能是CBC模式。

DES的加密的几种模式可以参考这里:https://www.cnblogs.com/yanzi-meng/p/9640578.html

比较ECB和CBC两种模式,可以发现,ECB对相同原文的加密密文是相同的,和字节位置无关,CBC对相同原文的加密密文是不同的,和字节位置有关。那么对于第一组字节(前8字节,即64bit)来说,CBC是有可能和ECB相同的,那么什么时候相同呢?

image.png

由图可以看出,DES加密算法的CBC模式和ECB模式主要的区别在于,CBC算法使用了加密向量IV对原文进行异或,而且IV是变化的,第组字节的加密结果是第二组字节的IV。这就是CBC加密相同字节但是密文不同的原因。

对于第一组字节来说,如果IV向量是ASCII码为0是8字节数据的话,那么ECB的加密结果和CBC是一样的。

综上分析:Oracle中使用的DES加密算法是CBC模式,使用NoPadding方式,原文的填充是其他代码完成的,且初时向量位8字节ASCII码为0的数据。

Java实现相同DES加密和解密

JAVA实现相同DES加密算法

直接附上代码:

try {
            DESKeySpec desKey = new DESKeySpec("encryptk".getBytes());
            SecretKey securekey = SecretKeyFactory.getInstance("DES").generateSecret(desKey);

            Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, securekey, new IvParameterSpec(new byte[8]));

            Base64.Encoder encoder = Base64.getEncoder();

            String inStr = "1234567812345678";
            byte[] inBytes = new byte[((int) (inStr.length() / 8) + 1) * 8];
            for (int i = 0; i < inStr.length(); i++) {
                inBytes[i] = inStr.getBytes()[i];
            }

            byte[] enBytes = cipher.doFinal(inBytes);
            byte[] base64Bytes = encoder.encode(enBytes);
            String hexStr = DatatypeConverter.printHexBinary(enBytes);

            System.out.println(inStr + " encrypted (hex)   :" + hexStr);
            System.out.println(inStr + " encrypted (base64):" + new String(base64Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }

执行结果:

image.png

image.png

image.png

比较和Oracle加密结果相同。

Java DES 解密

代码如下:

public static void main(String[] args) {
        System.out.println(DesDecrypt("RVo37OSWJUfF3nxSbhl12nnrknts79U6"));
    }

    public static String DesDecrypt(String encryptStr)
    {
        try {
            DESKeySpec desKey = new DESKeySpec("encryptk".getBytes());
            SecretKey securekey = SecretKeyFactory.getInstance("DES").generateSecret(desKey);

            Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, securekey, new IvParameterSpec(new byte[8]));

            byte[]decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptStr));

            return new String(decryptBytes);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

执行结果:


image.png

你可能感兴趣的:(Oracle DES 加密研究(Oracle DES加密、Java 解密))