Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Oracle和.NET中不同的DES加密_C#_.net_Oracle_Encryption - Fatal编程技术网

C# Oracle和.NET中不同的DES加密

C# Oracle和.NET中不同的DES加密,c#,.net,oracle,encryption,C#,.net,Oracle,Encryption,出于某种原因,我使用相同的加密密钥从OracleDMBS_CRYPTO和.NET实现的DecryptoServiceProvider获得了不同的编码结果 对于数据库,我正在使用具有以下加密类型的DBMS\u CRYPTO.ENCRYPT函数: encryption_type PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_DES + DBMS_CRYPTO.CHAIN_CBC

出于某种原因,我使用相同的加密密钥从Oracle
DMBS_CRYPTO
和.NET实现的
DecryptoServiceProvider
获得了不同的编码结果

对于数据库,我正在使用具有以下加密类型的
DBMS\u CRYPTO.ENCRYPT
函数:

   encryption_type    PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_DES
                                + DBMS_CRYPTO.CHAIN_CBC
                                +DBMS_CRYPTO.PAD_PKCS5;
DB函数

 FUNCTION encrypt (p_plainText VARCHAR2) RETURN RAW DETERMINISTIC
 IS
    encrypted_raw      RAW (2000);
 BEGIN
    encrypted_raw := DBMS_CRYPTO.ENCRYPT
    (
       src => UTL_RAW.CAST_TO_RAW (p_plainText),
       typ => encryption_type,
       key => encryption_key
    );
   RETURN encrypted_raw;
 END encrypt;
这是C#片:


产生不同加密结果的原因可能是什么?

问题可能在于您使用的密钥的填充。使用不同的密钥/不同的填充进行检查

问题可能在于您使用的密钥的填充。根据,您的C#代码使用默认的填充PKCS7,而Oracle代码似乎使用的是PKCS5。这可能是一个很好的起点。在这样做时,您可能也应该显式地设置块链接模式

编辑:对不起,PKCS5和PKCS7应该将具有相同字节的明文填充到相同的长度。可能不是这样。Vincent Malgrat建议尝试使用纯文本的原始字节来消除编码问题,这听起来是一个很好的开始。C代码将把您的字符串视为unicode。我认为,在Oracle中,它将使用数据库的任何编码设置。

根据,您的C#代码使用默认填充PKCS7,而Oracle代码似乎使用PKCS5。这可能是一个很好的起点。在这样做时,您可能也应该显式地设置块链接模式


编辑:对不起,PKCS5和PKCS7应该将具有相同字节的明文填充到相同的长度。可能不是这样。Vincent Malgrat建议尝试使用纯文本的原始字节来消除编码问题,这听起来是一个很好的开始。C代码将把您的字符串视为unicode。我认为,在Oracle中,它将使用数据库设置为的任何编码。

在.NET和Oracle加密之间有基本的区别

例如,Oracle的十六进制默认初始化值(IV)为“0123456789ABCDEF”。 .NET的十六进制默认初始化值(IV)为“C992C3154997E0FB”。 此外,在.NET中还有几个填充模式选项:ANSIX923、零、ISO1026、PKCS7和无

在下面的示例代码中,您应该可以不使用用于自定义填充的两行代码,并为填充模式指定ANSIX923。我们不得不容忍DBA的失礼,他们决定用波浪号“~”字符填充字符串,因此我将代码作为示例,以帮助其他类似情况下的人

以下是一组适用于我们的解决方案的简单方法:

    private static string EncryptForOracle(string message, string key)
    {

        string iv = "0123456789ABCDEF";

        int lengthOfPaddedString;
        message = PadMessageWithCustomChar(message, out lengthOfPaddedString);

        byte[] textBytes = new byte[lengthOfPaddedString];
        textBytes = ASCIIEncoding.ASCII.GetBytes(message);

        byte[] keyBytes = new byte[key.Length];
        keyBytes = ASCIIEncoding.ASCII.GetBytes(key);

        byte[] ivBytes = new byte[iv.Length];
        ivBytes = StringUtilities.HexStringToByteArray(iv);
        byte[] encrptedBytes = Encrypt(textBytes, keyBytes, ivBytes);

        return StringUtilities.ByteArrayToHexString(encrptedBytes);
    }

    /// <summary>
    // On the Oracle side, our DBAs wrapped the call to the toolkit encrytion function to pad with a ~, I don't recommend
    // doing down this path, it is prone to error.
    // we are working with blocks of size 8 bytes, this method pads the last block with ~ characters.
    /// </summary>
    /// <param name="message"></param>
    /// <param name="lengthOfPaddedString"></param>
    /// <returns></returns>
    private static string PadMessageWithCustomChar(string message, out int lengthOfPaddedString)
    {
        int lengthOfData = message.Length;
        int units;
        if ((lengthOfData % 8) != 0)
        {
            units = (lengthOfData / 8) + 1;
        }
        else
        {
            units = lengthOfData / 8;
        }

        lengthOfPaddedString = units * 8;

        message = message.PadRight(lengthOfPaddedString, '~');
        return message;
    }


    public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
    {
        MemoryStream ms = new MemoryStream();
        // Create a symmetric algorithm.
        TripleDES alg = TripleDES.Create();
        alg.Padding = PaddingMode.None;
        // You should be able to specify ANSIX923 in a normal implementation 
        // We have to use none because of the DBA's wrapper
        //alg.Padding = PaddingMode.ANSIX923;

        alg.Key = Key;
        alg.IV = IV;

        CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearData, 0, clearData.Length);
        cs.Close();

        byte[] encryptedData = ms.ToArray();
        return encryptedData;
    }

NET和Oracle加密之间存在基本区别

例如,Oracle的十六进制默认初始化值(IV)为“0123456789ABCDEF”。 .NET的十六进制默认初始化值(IV)为“C992C3154997E0FB”。 此外,在.NET中还有几个填充模式选项:ANSIX923、零、ISO1026、PKCS7和无

在下面的示例代码中,您应该可以不使用用于自定义填充的两行代码,并为填充模式指定ANSIX923。我们不得不容忍DBA的失礼,他们决定用波浪号“~”字符填充字符串,因此我将代码作为示例,以帮助其他类似情况下的人

以下是一组适用于我们的解决方案的简单方法:

    private static string EncryptForOracle(string message, string key)
    {

        string iv = "0123456789ABCDEF";

        int lengthOfPaddedString;
        message = PadMessageWithCustomChar(message, out lengthOfPaddedString);

        byte[] textBytes = new byte[lengthOfPaddedString];
        textBytes = ASCIIEncoding.ASCII.GetBytes(message);

        byte[] keyBytes = new byte[key.Length];
        keyBytes = ASCIIEncoding.ASCII.GetBytes(key);

        byte[] ivBytes = new byte[iv.Length];
        ivBytes = StringUtilities.HexStringToByteArray(iv);
        byte[] encrptedBytes = Encrypt(textBytes, keyBytes, ivBytes);

        return StringUtilities.ByteArrayToHexString(encrptedBytes);
    }

    /// <summary>
    // On the Oracle side, our DBAs wrapped the call to the toolkit encrytion function to pad with a ~, I don't recommend
    // doing down this path, it is prone to error.
    // we are working with blocks of size 8 bytes, this method pads the last block with ~ characters.
    /// </summary>
    /// <param name="message"></param>
    /// <param name="lengthOfPaddedString"></param>
    /// <returns></returns>
    private static string PadMessageWithCustomChar(string message, out int lengthOfPaddedString)
    {
        int lengthOfData = message.Length;
        int units;
        if ((lengthOfData % 8) != 0)
        {
            units = (lengthOfData / 8) + 1;
        }
        else
        {
            units = lengthOfData / 8;
        }

        lengthOfPaddedString = units * 8;

        message = message.PadRight(lengthOfPaddedString, '~');
        return message;
    }


    public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
    {
        MemoryStream ms = new MemoryStream();
        // Create a symmetric algorithm.
        TripleDES alg = TripleDES.Create();
        alg.Padding = PaddingMode.None;
        // You should be able to specify ANSIX923 in a normal implementation 
        // We have to use none because of the DBA's wrapper
        //alg.Padding = PaddingMode.ANSIX923;

        alg.Key = Key;
        alg.IV = IV;

        CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearData, 0, clearData.Length);
        cs.Close();

        byte[] encryptedData = ms.ToArray();
        return encryptedData;
    }

你能展示一下你在哪里执行加密的oracle代码吗,特别是在密钥进入的情况下?我更新了第一篇文章,添加了具有所有这些功能的DB函数。你能尝试在两侧使用RAW/字节来消除字符集转换错误的风险吗?你能用一些强大的东西来代替加密吗?打破DES相当便宜(100美元左右)。您还应该为每个加密使用不同的IV,添加身份验证通常也是一个好主意。您能否显示执行加密的oracle代码,特别是在密钥进入的情况下?我更新了第一篇文章,添加了具有所有这些功能的DB函数。你能尝试在两侧使用RAW/字节来消除字符集转换错误的风险吗?你能用强加密替换加密吗?打破DES相当便宜(100美元左右)。您还应该为每个加密使用不同的IV,添加身份验证通常也是一个好主意。
    /// <summary>
    /// Method to convert a string of hexadecimal character pairs
    /// to a byte array.
    /// </summary>
    /// <param name="hexValue">Hexadecimal character pair string.</param>
    /// <returns>A byte array </returns>
    /// <exception cref="System.ArgumentNullException">Thrown when argument is null.</exception>
    /// <exception cref="System.ArgumentException">Thrown when argument contains an odd number of characters.</exception>
    /// <exception cref="System.FormatException">Thrown when argument contains non-hexadecimal characters.</exception>
    public static byte[] HexStringToByteArray(string hexValue)
    {
        ArgumentValidation.CheckNullReference(hexValue, "hexValue");

        if (hexValue.Length % 2 == 1)
            throw new ArgumentException("ERROR: String must have an even number of characters.", "hexValue");

        byte[] values = new byte[hexValue.Length / 2];

        for (int i = 0; i < values.Length; i++)
            values[i] = byte.Parse(hexValue.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);

        return values;
    }   // HexStringToByteArray()


    /// <summary>
    /// Method to convert a byte array to a hexadecimal string.
    /// </summary>
    /// <param name="values">Byte array.</param>
    /// <returns>A hexadecimal string.</returns>
    /// <exception cref="System.ArgumentNullException">Thrown when argument is null.</exception>
    public static string ByteArrayToHexString(byte[] values)
    {
        ArgumentValidation.CheckNullReference(values, "values");

        StringBuilder hexValue = new StringBuilder();

        foreach (byte value in values)
        {
            hexValue.Append(value.ToString("X2"));
        }

        return hexValue.ToString();
    }   // ByteArrayToHexString()

    public static byte[] GetStringToBytes(string value)
    {
        SoapHexBinary shb = SoapHexBinary.Parse(value);
        return shb.Value;
    }

    public static string GetBytesToString(byte[] value)
    {
        SoapHexBinary shb = new SoapHexBinary(value);
        return shb.ToString();
    } 
create or replace FUNCTION DecryptPassword(EncryptedText IN VARCHAR2,EncKey IN VARCHAR2) RETURN VARCHAR2
IS
encdata RAW(2000);
numpad NUMBER;
result VARCHAR2(100);
BEGIN
  encdata:=dbms_obfuscation_toolkit.DES3Decrypt(input=&amp;gt;hextoraw(EncryptedText),key=&amp;gt;UTL_RAW.CAST_TO_RAW(EncKey));

  result :=rawtohex(encdata);
  numpad:=substr(result,length(result)-1);
  result:= substr(result,1,length(result)-(numpad*2));
  result := hextoraw(result);
  result := utl_raw.cast_to_varchar2(result);
  return result;

END DecryptPassword;