文件解密从结尾丢失~10个字符

时间:2009-10-27 17:19:17

标签: c# cryptography encryption

我在C#中使用RC2CryptoServiceProvider编写了加密/解密方法,出于某种原因,我无法让解密器解密最后几个字节。该文件似乎只是切断了。我的加密方法如下:

    public static byte[] EncryptString(byte[] input, string password)
    {
        PasswordDeriveBytes pderiver = new PasswordDeriveBytes(password, null);
        byte[] ivZeros = new byte[8];
        byte[] pbeKey = pderiver.CryptDeriveKey("RC2", "MD5", 128, ivZeros);

        RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();

        byte[] IV = new byte[8];
        ICryptoTransform encryptor = RC2.CreateEncryptor(pbeKey, IV);

        MemoryStream msEncrypt = new MemoryStream();
        CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
        csEncrypt.Write(input, 0, input.Length);
        csEncrypt.FlushFinalBlock();

        return msEncrypt.ToArray();
    }

虽然我的解密看起来像:

    public static byte[] DecryptString(byte[] input, string password, int originalSize)
    {
        PasswordDeriveBytes pderiver = new PasswordDeriveBytes(password, null);
        byte[] ivZeros = new byte[8];
        byte[] pbeKey = pderiver.CryptDeriveKey("RC2", "MD5", 128, ivZeros);

        RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();

        byte[] IV = new byte[8];
        ICryptoTransform decryptor = RC2.CreateDecryptor(pbeKey, IV);

        MemoryStream msDecrypt = new MemoryStream();
        CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write);

        csDecrypt.Write(input, 0, originalSize);
       // csDecrypt.FlushFinalBlock();

        char[] decrypted = new char[input.Length];
        decrypted = System.Text.Encoding.UTF8.GetChars(msDecrypt.ToArray());
        return msDecrypt.ToArray();

    }

char [] decrypted返回整个文件解密,除了文件以</LudoData>结尾,并且在解密时,我只能到达第一个<字符。

我一直在玩各种各样的东西,没有任何改变。在我的具体情况下,input的长度为11296,originalSize的大小为11290.但是,decrypted在解密时最终的大小为 11280 。是什么给了!

2 个答案:

答案 0 :(得分:6)

你有没有注意到Flush()的注释?你试过完全关闭你的流吗?

答案 1 :(得分:0)

叹了口气,我在一个月前参加了这场战斗并且遇到了一个非常类似的问题,除了我最后经历了太多的事情。 ToArray是我的解决方案。

你在做一些奇怪的事情我不太确定。当你不需要时,你正在使用cryptuffream,你出于某种奇怪的原因跟踪原始长度并且你正在使用已弃用的类。你的问题可能是填充,不正确的假设(由originalLength证明)和错误的流处理(这可能是棘手的)的组合。试试这个:

加密:

var rij = RijndaelManaged.Create();
rij.Mode = CipherMode.CBC;
rij.BlockSize = 256;
rij.KeySize = 256;
rij.Padding = PaddingMode.ISO10126;
var pdb = new Rfc2898DeriveBytes(password, 
          Encoding.Default.GetBytes("lolwtfbbqsalt" + password));
var enc = rij.CreateEncryptor(pdb.GetBytes(rij.KeySize / 8), 
          pdb.GetBytes(rij.BlockSize / 8));
return enc.TransformFinalBlock(unencryptedBytes, 0, unencryptedBytes.Length);

解密:

// throws a cryptographic exception if password is wrong
var rij = RijndaelManaged.Create();
rij.Mode = CipherMode.CBC;
rij.BlockSize = 256;
rij.KeySize = 256;
rij.Padding = PaddingMode.ISO10126;
var pdb = new Rfc2898DeriveBytes(password, 
          Encoding.Default.GetBytes("lolwtfbbqsalt" + password));
var dec = rij.CreateDecryptor(pdb.GetBytes(rij.KeySize / 8), 
          pdb.GetBytes(rij.BlockSize / 8));
return dec.TransformFinalBlock(encryptedBytes, 0, 
          encryptedBytes.Length);

请注意,这两个方法中唯一不同的是CreateEncryptor / CreateDecryptor,因此您可以重构大量的重复。还要注意我进入一个字节数组并得到一个字节数组而不必使用任何流。它也比RC2更安全,如果盐更随机,它会更加安全。