c# - 将 Oracle AES 256 加密复制到 C#

标签 c# oracle encryption

我很难复制 oracle 如何使用 AES 256 + CBC + PKCS5/7 将其复制到 C# 中进行加密。感谢您在此方面的帮助。

我在 oracle 包中有以下功能(简化):

--Character set used by GEN_ENCRYPT_PASSWORD and GEN_DECRYPT_PASSWORD
G_CHARACTER_SET   VARCHAR2(10) := 'AL32UTF8';    
FUNCTION GEN_ENCRYPT_PASSWORD(p_in_val      IN VARCHAR2
                                    ,p_key         IN VARCHAR2                                        
                                    ,p_iv          IN VARCHAR2 := NULL)
          RETURN RAW
       IS
          l_enc_val    RAW(4000);
          l_enc_algo   PLS_INTEGER;
          l_in         RAW(4000);
          l_iv         RAW(4000);
          l_key        RAW(4000);
          --l_ret        VARCHAR2(4000 CHAR);
          v_mod        NUMBER;
       BEGIN
          l_in         := UTL_I18N.STRING_TO_RAW(data => p_in_val, dst_charset => G_CHARACTER_SET);
          l_iv         := UTL_I18N.STRING_TO_RAW(p_iv, G_CHARACTER_SET);
          l_key        := UTL_I18N.STRING_TO_RAW(data => p_key, dst_charset => G_CHARACTER_SET);
          l_enc_algo   := DBMS_CRYPTO.encrypt_aes256;
          --chain_cbc: Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted.
          --pad_pkcs5: Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard.
          v_mod        := (l_enc_algo + DBMS_CRYPTO.chain_cbc + DBMS_CRYPTO.pad_pkcs5);

          l_enc_val    := DBMS_CRYPTO.encrypt(src => l_in, KEY => l_key, typ => v_mod);
          --l_ret       := RAWTOHEX(l_enc_val);
          RETURN l_enc_val;
       END GEN_ENCRYPT_PASSWORD;

       FUNCTION GEN_DECRYPT_PASSWORD(p_in_val      IN RAW
                                    ,p_key         IN VARCHAR2                                        
                                    ,p_iv          IN VARCHAR2 := NULL)
          RETURN VARCHAR2
       IS
          l_enc_val    RAW(4000);
          l_enc_algo   PLS_INTEGER;
          l_in         RAW(4000);
          l_iv         RAW(4000);
          l_key        RAW(4000);
          l_ret        VARCHAR2(4000 CHAR);
          v_mod        NUMBER;
       BEGIN
          l_in         := p_in_val;            --UTL_I18N.STRING_TO_RAW(data => p_in_val, dst_charset => G_CHARACTER_SET);

          l_iv         := UTL_I18N.STRING_TO_RAW(p_iv, G_CHARACTER_SET);
          l_key        := UTL_I18N.STRING_TO_RAW(data => p_key, dst_charset => G_CHARACTER_SET);

          l_enc_algo   := DBMS_CRYPTO.encrypt_aes256;

          --chain_cbc: Cipher Block Chaining. Plaintext is XORed with the previous ciphertext block before it is encrypted.
          --pad_pkcs5: Provides padding which complies with the PKCS #5: Password-Based Cryptography Standard.
          v_mod        := (l_enc_algo + DBMS_CRYPTO.chain_cbc + DBMS_CRYPTO.pad_pkcs5);

          l_enc_val    := DBMS_CRYPTO.decrypt(src => l_in, KEY => l_key, typ => v_mod);
          l_ret        := UTL_I18N.raw_to_char(data => l_enc_val, src_charset => G_CHARACTER_SET);

          RETURN l_ret;
       END GEN_DECRYPT_PASSWORD;

然后我运行查询:

SELECT pkg_Encyption_Test.GEN_ENCRYPT_PASSWORD('Test', '12345678901234567890123456789012', '26744a68b53dd87a') Encrypted FROM DUAL;
--Result: 7D2894678D46C769B3001BD75F603E3C

并解密结果:

SELECT pkg_Encyption_Test.GEN_DECRYPT_PASSWORD('7D2894678D46C769B3001BD75F603E3C', '12345678901234567890123456789012', '26744a68b53dd87a') Decrypt from dual;
--Result: Test

所以以上都有效,问题是我如何将其转换为 C# 用于解密结果? 示例控制台应用程序:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace SSO_EncryptionTest
{
    class Program
    {
        /* ORACLE
         * TEXT ENC: 7D2894678D46C769B3001BD75F603E3C
         * TEXT: Test
         * KEY: 12345678901234567890123456789012
         * .NET
         * ENC: EAAAADI2NzQ0YTY4YjUzZGQ4N2GfHsbuE8t1/hhwz3v9isJ1         
         */
        static void Main(string[] args)
        {
            //Use the values from Oracle
            string inputText = "Test";
            string encryptedTextValue = "7D2894678D46C769B3001BD75F603E3C";
            string encryptPrivateKey = "12345678901234567890123456789012";
            string encryptSharedIV = "26744a68b53dd87a";

            Console.WriteLine("******************** Initial values from Oracle ******************");
            Console.WriteLine("inputText: '{0}'", inputText);
            Console.WriteLine("encryptedTextValue: '{0}'", encryptedTextValue);
            Console.WriteLine("encryptPrivateKey: '{0}'", encryptPrivateKey);
            Console.WriteLine("encryptSharedIV: '{0}'", encryptSharedIV);
            Console.WriteLine();

            //This is just here to convert the Encrypted byte array to a string for viewing purposes.
            UTF8Encoding UTF = new UTF8Encoding();
            byte[] inputTextByte = UTF.GetBytes(inputText);
            byte[] encryptedTextValueByte = UTF.GetBytes(encryptedTextValue);
            byte[] encryptPrivateKeyByte = UTF.GetBytes(encryptPrivateKey);
            byte[] encryptSharedIvByte = UTF.GetBytes(encryptSharedIV);

            string Encrypted_Text;
            //string Decrypted;
            try
            {
                Console.WriteLine("********************Encryption Example******************");

                Console.WriteLine("Plain text is: '{0}'", inputText);
                Encrypted_Text = EncryptOracleAES(inputTextByte, encryptPrivateKeyByte, encryptSharedIvByte);
                Console.WriteLine("Encrypted text is: '{0}'", Encrypted_Text);               

                Console.WriteLine();

                /*Console.WriteLine("********************Decryption Example******************");
                Console.WriteLine("Input Encrypted text is '{0}'", XXXXXXXXXXXX);
                Decrypted = "";
                Console.WriteLine("Decrypted text is: '{0}'", Decrypted);*/

            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
            }

            Console.WriteLine("Press enter to exit");

            Console.ReadLine();
        }

        public static string EncryptOracleAES(byte[] plainText, byte[] privateKey, byte[] sharedIVKey)
        {
            //select UTL_I18N.STRING_TO_RAW('Test', 'AL32UTF8') from dual;
            //54657374         

            string outStr = null;                       // Encrypted string to return
            AesManaged aesAlg = null;
            try
            {                
                aesAlg = new AesManaged();
                aesAlg.Key = privateKey;
                aesAlg.KeySize = 256;
                aesAlg.BlockSize = 128;
                aesAlg.Padding = PaddingMode.PKCS7; //Same as PKCS5/7
                aesAlg.Mode = CipherMode.CBC;
                aesAlg.IV = sharedIVKey;
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, sharedIVKey);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    // prepend the IV
                    msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
                    msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);

                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                    }
                    outStr = Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
            finally
            {

                if (aesAlg != null)
                    aesAlg.Clear();
            }

            // Return the encrypted bytes from the memory stream.
            return outStr;

        }
    }
}

但我的结果并不一致:

******************** Initial values from Oracle ******************
inputText: 'Test'
encryptedTextValue: '7D2894678D46C769B3001BD75F603E3C'
encryptPrivateKey: '12345678901234567890123456789012'
encryptSharedIV: '26744a68b53dd87a'

********************Encryption Example******************
Plain text is: 'Test'
Encrypted text is: 'EAAAADI2NzQ0YTY4YjUzZGQ4N2FCXNXYzo2xWZym3dNFwCSJ'

我错过了什么?

最佳答案

主要问题实际上是当我传入 IV 值时我的 select 语句缺少参数“AES256”(与解密相同)duh moment...我为此归咎于同事不断的烦恼 :)。

SELECT pkg_Encyption_Test.GEN_ENCRYPT_PASSWORD('Test', '12345678901234567890123456789012', '26744a68b53dd87a') Encrypted FROM DUAL;
--Result: 7D2894678D46C769B3001BD75F603E3C

应该是:

SELECT pkg_Encyption_Test..GEN_ENCRYPT_PASSWORD('Test'
                                       ,'12345678901234567890123456789012'
                                       ,'AES256' --Or NULL
                                       ,'26744a68b53dd87a26744a68b53dd87a')
          Encrypted
  FROM DUAL;
--Result: E320A0CABF881088A424B4F36F188029

这需要重构,但总体思路已经存在。

类:AesEncryption

 public static AesCryptoServiceProvider AesEncryptionType(byte[] privateKeyByte, byte[] sharedIVKeyByte)
        {
            var aes = new AesCryptoServiceProvider();
            aes.BlockSize = 128;
            aes.KeySize = 256;
            aes.IV = sharedIVKeyByte;
            aes.Key = privateKeyByte;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            return aes;
        }

我使用的变体:

public static string EncryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
        {
            using (var aesEncryption = AesEncryption.AesEncryptionType(privateKeyByte, sharedIVKeyByte))
            {
                // Convert string to byte array                
                byte[] dest = new byte[inputTextByte.Length];

                // encryption
                using (ICryptoTransform encrypt = aesEncryption.CreateEncryptor(aesEncryption.Key, aesEncryption.IV))
                {
                    dest = encrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);

                    encrypt.Dispose();                        
                }
                return BitConverter.ToString(dest).Replace("-", "");
            }
        }

public static string DecryptUsingAes(byte[] inputTextByte, byte[] privateKeyByte, byte[] sharedIVKeyByte)
        {
            using (var aesDecryption = AesEncryption.AesEncryptionType(privateKeyByte, sharedIVKeyByte))
            {
                // Convert string to byte array                
                byte[] dest = new byte[inputTextByte.Length];

                // encryption
                using (ICryptoTransform decrypt = aesDecryption.CreateDecryptor(aesDecryption.Key, aesDecryption.IV))
                {
                    dest = decrypt.TransformFinalBlock(inputTextByte, 0, inputTextByte.Length);

                    decrypt.Dispose();

                }
                // Convert byte array to UTF8 string
                return Encoding.UTF8.GetString(dest); ;
            }
        }

还有主要的:

private static void Main(string[] args)
        {
            //Use the values from Oracle
            string inputText = "Test";
            string encryptionType = "AES256";
            string encryptPrivateKey = "12345678901234567890123456789012";
            string encryptSharedIV = "26744a68b53dd87a";//26744a68b53dd87a26744a68b53dd87a";
            string encryptedTextValue = "E320A0CABF881088A424B4F36F188029";

            Console.WriteLine("******************** Initial values from Oracle ******************");
            Console.WriteLine("inputText: '{0}'", inputText);
            Console.WriteLine("encryptionType: '{0}'", encryptionType);
            Console.WriteLine("encryptedTextValue: '{0}'", encryptedTextValue);
            Console.WriteLine("encryptPrivateKey: '{0}'", encryptPrivateKey);
            Console.WriteLine("encryptSharedIV: '{0}'", encryptSharedIV);

            //OracleRaw
            string oracleRawText = "54657374";
            string oracleRawPrivateKey = "3132333435363738393031323334353637383930313233343536373839303132";
            string oracleRawSharedIV = "32363734346136386235336464383761"; //26744a68b53dd87a - IV is 16 byte array.            

            Console.WriteLine("******************** Initial values from Oracle OracleRaw ******************");
            Console.WriteLine("oracleRawText: '{0}'", oracleRawText);
            Console.WriteLine("oracleRawPrivateKey: '{0}'", oracleRawPrivateKey);
            Console.WriteLine("oracleRawSharedIV: '{0}'", oracleRawSharedIV);
            Console.WriteLine();

            //This is just here to convert the Encrypted byte array to a string for viewing purposes.
            var utf = new UTF8Encoding();
            byte[] inputTextByte = utf.GetBytes(inputText); //byte: 4 - "Test"
            byte[] privateKeyByte = utf.GetBytes(encryptPrivateKey); //byte: 32 - "12345678901234567890123456789012"
            byte[] sharedIVByte = utf.GetBytes(encryptSharedIV); //byte: 16 - "26744a68b53dd87a"

            //string Decrypted;
            try
            {
                string encryptedText = string.Empty;

                byte[] oracleRawTextByte = StringToByteArray(oracleRawText);
                byte[] oracleRawPrivateKeyByte = StringToByteArray(oracleRawPrivateKey);
                byte[] oracleRawSharedIVByte = StringToByteArray(oracleRawSharedIV);

                encryptedText = EncryptUsingAes(oracleRawTextByte, oracleRawPrivateKeyByte, oracleRawSharedIVByte);
                Console.WriteLine("********************Encryption Example EncryptUsingAes(OracleRaw) ******************");
                Console.WriteLine("Plain text is: '{0}'", inputText);
                Console.WriteLine("Encrypted text is: '{0}'", encryptedText);
                Console.WriteLine();

                encryptedText = EncryptUsingAes(inputTextByte, privateKeyByte, sharedIVByte);
                Console.WriteLine("********************Encryption Example EncryptUsingAes******************");
                Console.WriteLine("Plain text is: '{0}'", inputText);
                Console.WriteLine("Encrypted text is: '{0}'", encryptedText);
                Console.WriteLine();

                Console.WriteLine("********************Encryption Example DecryptUsingAes******************");
                Console.WriteLine("Encrypted text is: '{0}'", encryptedText);

                byte[] cypherText = StringToByteArray(encryptedText);

                encryptedText = DecryptUsingAes(cypherText, privateKeyByte, sharedIVByte);

                Console.WriteLine("Plain text is: '{0}'", encryptedText);
                Console.WriteLine();                    
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
            }

            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }

关于c# - 将 Oracle AES 256 加密复制到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33420630/

相关文章:

ios - 在 mac 终端中将 pem 格式的公钥转换为 der 格式时出错

encryption - 在 ssl key 交换期间,如何在 wireshark 中查看加密 key ?

c# - HttpContext的线程安全

c# - Unity3D:从 RenderTexture 的一个像素制作纹理

c# - 从数据库中获取记录

node.js - Node 加密 - 定义输出密码长度

c# - 如何在 C# .Net 3.5 SP1 中显示身份验证对话框

c# - 通用列表在 C# 中添加空值

sql - 无论 NLS 设置如何,工作日数

java - 数据库错误: Vendor 20