none
DES解密遇到CryptographicException:不正确的数据。 RRS feed

  • 问题

  • 问题让我头疼两天,请大家指点一下,谢谢!

    我写了两个方法,一个是DES加密,一个是DES解密,环境为VS2010,.NET4.0,使用C#,方法如下:

    /// <summary>
    /// CBC-DES加密
    /// </summary>
    public static byte[] DESEncrypt(byte[] data, byte[] key, byte[] iv)
    {
        //注:已省略检查参数合法性等代码,以缩短帖子长度
        byte[] result = null;
        using (DES des = new DESCryptoServiceProvider() { Key = key, IV = iv })
        using (MemoryStream outStream = new MemoryStream())
        using (CryptoStream encStream = new CryptoStream(outStream, des.CreateEncryptor(), CryptoStreamMode.Write))
        {
            encStream.Write(data, 0, data.Length);
            result = outStream.ToArray();
        }
        return result;
    }
    
    /// <summary>
    /// CBC-DES解密
    /// </summary>
    public static byte[] DESDecrypt(byte[] data, byte[] key, byte[] iv)
    {
        //注:已省略检查参数合法性等代码,以缩短帖子长度
        byte[] result = null;
        using (DES des = new DESCryptoServiceProvider() { Key = key, IV = iv })
        using (MemoryStream inStream = new MemoryStream(data))
        using (CryptoStream encStream = new CryptoStream(inStream, des.CreateDecryptor(), CryptoStreamMode.Read))
        {
            List<byte> byteList = new List<byte>();
            int i;
            while ((i = encStream.ReadByte()) != -1)
            {
                byteList.Add((byte)i);
            }
            result = byteList.ToArray();
        }
        return result;
    }
    

     

    然后我就建立了几个数据测试它们,测试代码如下: 

    byte[] oriBytes = { 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 };   //32个字节,做为被加密的内容。
    byte[] key = { 225, 11, 183, 166, 175, 189, 133, 111 }; //8个字节,做为加密用的KEY
    byte[] iv = { 181, 12, 1, 234, 97, 154, 240, 3 };   //8个字节,做为加密用的IV
    byte[] desBytes = EncryptHelper.DESEncrypt(oriBytes, key, iv);   //加密oriBytes,加密结果为desBytes。
    byte[] oriBytes2 = EncryptHelper.DESDecrypt(desBytes, key, iv);  //使用同样的key和iv解密desBytes,解密结果为oriBytes2。但只成功解密了前24个字节,解密第25字节时,DESDecrypt方法里的encStream.ReadByte()语句会抛出异常:不正确的数据。
    bool isSuccess = desBytes.SequenceEqual(oriBytes2); //按照我的设想,desBytes里的内容应该和desBytes2里的内容一致,即isSuccess为true。但因为上句解密代码会抛异常,根本执行不到这一步。
    

    我实现找到不错误的原因,我找了很多资料,还把baidu和google都翻了一遍,都没找到解决问题的方法。现在老板催,同事要,我的头都快炸啦,难道非得要到根据DES算法自己去XOR字节的地步么。各位大侠,快把我从地狱中救赎出来吧,谢谢!!!!!


    Wantal
    2011年12月16日 5:53

答案

  • 你好:)

    1)在DesEncypt函数中,你缺少了对Stream的Close操作,意味着你无法把数据写入到流中,注意我黑色、粗体、下划线部分——

     using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                {
                    using (MemoryStream outStream = new MemoryStream())
                    {
                        using (CryptoStream encStream = new CryptoStream(outStreamdes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            encStream.Write(data0data.Length);
                            encStream.Close();
                            result = outStream.ToArray();
                        }
                    }
                }
    2)注意你比较:把加密前和加密后比较!
     bool isSuccess = oriBytes2.SequenceEqual(oriBytes2);
    以下给出完整代码:
    namespace A
    {
        class Program
        {
            public static byte[] DESEncrypt(byte[] databyte[] keybyte[] iv)
            {
                //注:已省略检查参数合法性等代码,以缩短帖子长度
                byte[] result = null;

                using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                {
                    using (MemoryStream outStream = new MemoryStream())
                    {
                        using (CryptoStream encStream = new CryptoStream(outStreamdes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            encStream.Write(data0data.Length);
                            encStream.Close();
                            result = outStream.ToArray();
                        }
                    }
                }
                return result;
            }

            public static byte[] DESDecrypt(byte[] databyte[] keybyte[] iv)
            {
                //注:已省略检查参数合法性等代码,以缩短帖子长度
                byte[] result = null;
                using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                using (MemoryStream inStream = new MemoryStream(data))
                using (CryptoStream encStream = new CryptoStream(inStreamdes.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    List<byte> byteList = new List<byte>();
                    int i;
                    while ((i = encStream.ReadByte()) != -1)
                    {
                        byteList.Add((byte)i);
                    }
                    result = byteList.ToArray();
                }
                return result;
            }


            static void Main(string[] args)
            {
                byte[] oriBytes = { 12341234123412341234123412341234 };  
                byte[] key = { 22511183166175189133111 }; 
    byte[] iv = { 181121234971542403 };   
    byte[] desBytes = DESEncrypt(oriByteskeyiv);   
                byte[] oriBytes2 = DESDecrypt(desByteskeyiv);  
                bool isSuccess = oriBytes2.SequenceEqual(oriBytes2); 
                Console.WriteLine(isSuccess);
            }
        }
    }

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2011年12月16日 7:07
    版主

全部回复

  • 你好:)

    1)在DesEncypt函数中,你缺少了对Stream的Close操作,意味着你无法把数据写入到流中,注意我黑色、粗体、下划线部分——

     using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                {
                    using (MemoryStream outStream = new MemoryStream())
                    {
                        using (CryptoStream encStream = new CryptoStream(outStreamdes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            encStream.Write(data0data.Length);
                            encStream.Close();
                            result = outStream.ToArray();
                        }
                    }
                }
    2)注意你比较:把加密前和加密后比较!
     bool isSuccess = oriBytes2.SequenceEqual(oriBytes2);
    以下给出完整代码:
    namespace A
    {
        class Program
        {
            public static byte[] DESEncrypt(byte[] databyte[] keybyte[] iv)
            {
                //注:已省略检查参数合法性等代码,以缩短帖子长度
                byte[] result = null;

                using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                {
                    using (MemoryStream outStream = new MemoryStream())
                    {
                        using (CryptoStream encStream = new CryptoStream(outStreamdes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            encStream.Write(data0data.Length);
                            encStream.Close();
                            result = outStream.ToArray();
                        }
                    }
                }
                return result;
            }

            public static byte[] DESDecrypt(byte[] databyte[] keybyte[] iv)
            {
                //注:已省略检查参数合法性等代码,以缩短帖子长度
                byte[] result = null;
                using (DES des = new DESCryptoServiceProvider() { Key = keyIV = iv })
                using (MemoryStream inStream = new MemoryStream(data))
                using (CryptoStream encStream = new CryptoStream(inStreamdes.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    List<byte> byteList = new List<byte>();
                    int i;
                    while ((i = encStream.ReadByte()) != -1)
                    {
                        byteList.Add((byte)i);
                    }
                    result = byteList.ToArray();
                }
                return result;
            }


            static void Main(string[] args)
            {
                byte[] oriBytes = { 12341234123412341234123412341234 };  
                byte[] key = { 22511183166175189133111 }; 
    byte[] iv = { 181121234971542403 };   
    byte[] desBytes = DESEncrypt(oriByteskeyiv);   
                byte[] oriBytes2 = DESDecrypt(desByteskeyiv);  
                bool isSuccess = oriBytes2.SequenceEqual(oriBytes2); 
                Console.WriteLine(isSuccess);
            }
        }
    }

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2011年12月16日 7:07
    版主
  • 谢谢,我试了试,就是少了那句encStream.Close();,加上这句代码,就没有错误了。现在看来,需要在读取outStream前主动Close一下encStream,等using标记来处理encStream就太迟了。多谢指教。另外感谢指出了比较内容那里的变量错误,否则如果比较结果为false,我又要被吓出一头汗。

    谢谢!!!!!!!!!!!!!!!!!!!!


    Wantal
    • 已编辑 Wantal 2011年12月16日 7:33
    2011年12月16日 7:26
  • 谢谢,我试了试,就是少了那句encStream.Close();,加上这句代码,就没有错误了。现在看来,需要在读取outStream前主动Close一下encStream,等using标记来处理encStream就太迟了。多谢指教。另外感谢指出了比较内容那里的变量错误,否则如果比较结果为false,我又要被吓出一头汗。

    谢谢!!!!!!!!!!!!!!!!!!!!


    Wantal

    不用谢!希望你多来MSDN,并且多多帮助别人哦!
       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处
    2011年12月16日 7:41
    版主