oracle AES加密 和 java AES加密 C#加密解密互通的问题

1. oracle 加密解密:

1)进入oracle命令行(sqlplus /as sysdba) 或登录oracle 管理员账号 
2)执行赋权命令-赋权命令需在加密解密函数之前执行   ehrds 是用户名
grant execute on sys.dbms_crypto to ehrds;
grant execute on sys.UTL_I18N to ehrds;

2. 使用plsql, 登录数据库,执行下面函数

   加密解密函数(需注意,oracle 加密后字符串是大写,代码中需要转大写处理):

-- 加密函数
CREATE OR REPLACE FUNCTION FUN_AES(
    V_STR VARCHAR2 ,
    V_KEY VARCHAR2
)
    RETURN VARCHAR2
AS
    V_KEY_RAW RAW(24) ;
    V_STR_RAW RAW(2000) ;
    V_RETURN_STR VARCHAR2(2000) ;
    V_TYPE PLS_INTEGER ;
BEGIN
    V_KEY_RAW := UTL_I18N.STRING_TO_RAW(V_KEY,'UTF8') ;
    V_STR_RAW := UTL_I18N.STRING_TO_RAW(V_STR,'UTF8') ;
    V_TYPE := DBMS_CRYPTO.ENCRYPT_AES128+DBMS_CRYPTO.CHAIN_ECB+DBMS_CRYPTO.PAD_PKCS5 ;
    V_STR_RAW := DBMS_CRYPTO.ENCRYPT(SRC => V_STR_RAW , typ => V_TYPE, key => V_KEY_RAW) ;
    V_RETURN_STR := RAWTOHEX(V_STR_RAW);
    RETURN V_RETURN_STR ;
END;
/

-- 解密函数
CREATE OR REPLACE FUNCTION FUN_DAES(
    V_STR VARCHAR2 ,
    V_KEY VARCHAR2
)
    RETURN VARCHAR2
AS
    V_KEY_RAW RAW(24) ;
    V_STR_RAW RAW(2000) ;
    V_RETURN_STR VARCHAR2(2000) ;
    V_TYPE PLS_INTEGER ;
BEGIN
    V_KEY_RAW := UTL_I18N.STRING_TO_RAW(V_KEY,'UTF8') ;
    V_STR_RAW := HEXTORAW(V_STR);
    V_TYPE := DBMS_CRYPTO.ENCRYPT_AES128+DBMS_CRYPTO.CHAIN_ECB+DBMS_CRYPTO.PAD_PKCS5 ;
    V_STR_RAW := DBMS_CRYPTO.DECRYPT(SRC => V_STR_RAW , typ => V_TYPE, key => V_KEY_RAW ) ;
    V_RETURN_STR := UTL_I18N.RAW_TO_CHAR(V_STR_RAW,'UTF8');
    RETURN V_RETURN_STR ;

END;
/

2. java 加密函数:

private static final String ECB_PKCS5_PADDING = "AES/ECB/PKCS5Padding";
private static final String AES = "AES";
//编码方式
public static final String CODE_TYPE = "UTF-8";
/**
 * AES 加密操作  ECBPK5Hex
*
* @param content 待加密内容
* @param key 加密密钥
* @return 返回Base64转码后的加密数据
*/
public static String encryptECBPK5Hex(String content, String key) {
if (content == null || "".equals(content)) {
return content;
}
try {
/*
* 新建一个密码编译器的实例,由三部分构成,用"/"分隔,分别代表如下
* 1. 加密的类型(如AES,DES,RC2等)
* 2. 模式(AES中包含ECB,CBC,CFB,CTR,CTS等)
* 3. 补码方式(包含nopadding/PKCS5Padding等等)
* 依据这三个参数可以创建很多种加密方式
*/
Cipher cipher = Cipher.getInstance(ECB_PKCS5_PADDING);//"AES/ECB/PKCS5Padding";
byte[] byteContent = content.getBytes(CODE_TYPE);

//使用加密秘钥
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(CODE_TYPE), AES);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);// 初始化为加密模式的密码器
byte[] result = cipher.doFinal(byteContent);// 加密
return byteToHex(result);//通过hex转码返回
} catch (Exception ex) {
}
return null;
}

/**
* AES 解密操作 ECBPK5Hex
*
* @param content
* @param key
* @return
*/
public static String decryptECBPK5Hex(String content, String key) {
if (content == null || "".equals(content)) {
return content;
}
try {
//实例化
Cipher cipher = Cipher.getInstance(ECB_PKCS5_PADDING);

//使用加密秘钥
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(CODE_TYPE), AES);
cipher.init(Cipher.DECRYPT_MODE, skeySpec);// 初始化为加密模式的密码器

byte[] result = cipher.doFinal(hexToByte(content));

return new String(result, CODE_TYPE);
} catch (Exception ex) {
}
return null;
}

public static String byteToHex(byte[] bytes){
String strHex = "";
StringBuilder sb = new StringBuilder("");
for (int n = 0; n < bytes.length; n++) {
strHex = Integer.toHexString(bytes[n] & 0xFF);
sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0
}
return sb.toString().trim();
}

public static byte[] hexToByte(String hex){
int m = 0, n = 0;
int byteLen = hex.length() / 2; // 每两个字符描述一个字节
byte[] ret = new byte[byteLen];
for (int i = 0; i < byteLen; i++) {
m = i * 2 + 1;
n = m + 1;
int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
ret[i] = Byte.valueOf((byte)intVal);
}
return ret;
}

 

C# 版本

 

/// <summary>
        /// AES 算法加密(ECB模式) 将明文加密,加密后进行Hex编码,返回密文
        /// </summary>
        /// <param name="str">明文</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后Hex编码的密文</returns>
        public static string AesEncryptor_ECB_Hex(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

            RijndaelManaged rm = new RijndaelManaged
            {
                //Key = StrToHexByte(key),  //把key转成16进制
                Key = Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return ToHexString(resultArray);
        }


        /// <summary>
        ///AES 算法解密(ECB模式) 将密文Hex解码后进行解密,返回明文
        /// </summary>
        /// <param name="str">密文</param>
        /// <param name="key">密钥</param>
        /// <returns>明文</returns>
        public static string AesDecryptor_ECB_Hex(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = StrToHexByte(str);

            RijndaelManaged rm = new RijndaelManaged
            {
                //Key = StrToHexByte(key), //key16进制解码
                Key = Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateDecryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Encoding.UTF8.GetString(resultArray);
        }

        /// <summary>
        /// byte数组Hex编码
        /// </summary>
        /// <param name="bytes">需要进行编码的byte[]</param>
        /// <returns></returns>
        public static string ToHexString(byte[] bytes)
        {
            string hexString = string.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    strB.Append(bytes[i].ToString("X2"));
                }
                hexString = strB.ToString();
            }
            return hexString;
        }
        /// <summary>
        /// 字符串进行Hex解码(Hex.decodeHex())
        /// </summary>
        /// <param name="hexString">需要进行解码的字符串</param>
        /// <returns></returns>
        public static byte[] StrToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

测试:

        static void Main(string[] args)
        {
            //密码
            
            string message = AES_Cipher.AesEncryptor_ECB_Hex("1233211234567", "1234567890123456");
        
            
            Console.WriteLine(message);
            System.Diagnostics.Trace.WriteLine(message);

            string inmsg =  AES_Cipher.AesDecryptor_ECB_Hex(message, "1234567890123456");

            Console.WriteLine(inmsg);
            System.Diagnostics.Trace.WriteLine(inmsg);
        }

 

 3. 分析:

加密方式网上工具测试:

1. ECB 模式

2. pkcs5padding 

3. 长度128

4. 蜜月16位

5. 输出 hex

6. 输入编码  UTF-8

4. 测试:

select FUN_ENCRYPTION128C('1233211234567','1234567890123456'),FUN_DECRYPTION128C('BEA8BDDCE00E13B8713A071C8EDFB12C','1234567890123456') from dual;
    public static void main(String[] args) {
        String content = "1233211234567";
        String key = "1234567890123456";
        System.out.println("content:" + content);
        String s1 = EncryptRuleAESSupport.encryptORACLE(content, key);
        System.out.println("result1:" + s1);

//        s1="G8SP97HnhXIGcPvnc7ObyA";
//        System.out.println("result2:" + EncryptRuleAESSupport.decrypt(s1, key));
//        System.out.println("key : " + key);
//        System.out.println("VIPARA" + VIPARA);

    }

 

5. clickhouse  解密:

     SELECT decrypt('aes-128-ecb',unhex('5C4029C7B05E26C156465165446451651635516991'),'1234567887456321')  AS  ciphertext;

     SELECT hex(encrypt('aes-128-ecb','370786194905280925','1234567887456321'))  AS  ciphertext;

参考: https://clickhouse.com/docs/zh/sql-reference/functions/encryption-functions/

 

posted @ 2022-04-27 16:49  leolzi  阅读(1129)  评论(0编辑  收藏  举报