C#要解密的数据长度无效

时间:2015-04-17 19:28:01

标签: c# encryption unicode filestream rijndael

关于此问题有很多类似的问题,但“无”与我的问题相符。

我创建了一个充满加密随机字节的文件。然后在特定位置的此文件中,我写了几个加密字节。当我尝试读取该字节部分时,我得到“要解密的数据长度无效”。

这是加密和解密方法(在某些时候在SO上找到)

 private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
        //TODO: The SALT needs to be derived and unique for each user!

        internal  byte[] Encrypt(byte[] plain)
        {
            string password = Properties.Settings.Default.PasswordOne;
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(plain, 0, plain.Length);
            cryptoStream.Close();
            return memoryStream.ToArray();
        }

        internal  byte[] Decrypt(byte[] cipher)
        {
            string password = Properties.Settings.Default.PasswordOne;
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(cipher, 0, cipher.Length);
            cryptoStream.Close();
            return memoryStream.ToArray();
        }

我使用此

将新数据保存在第一个文件中
 private void InsertDEFT2NameLength(FileSystemEncryption fse, string Deft2FileName, FileStream fs, StreamWriter sw)
        {

            string deft2NameLength = "0";                                       // init the length
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name to Bytes");
            byte[] bdeft2Name = GetBytes(Deft2FileName);                        // convert filename to bytes
            if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name");
            byte[] ebdeft2Name = fse.Encrypt(bdeft2Name);                       // Encrypt
            if (DrivesLog != null) DrivesLog("Getting Length of Encrypted DEFT2 Name");
            long ebdeft2NameLength = ebdeft2Name.LongLength;                    // Get Length of the Encrypted Bytes as a long
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to String");
            string sebdeft2NameLength = ebdeft2NameLength.ToString() + "!";     // Convert Length to string Add Exclamation so we know when we have read the full length
            if (DrivesLog != null) DrivesLog("Converting DEFT2 Name Length to Bytes");
            byte[] bsebdeft2NameLength = GetBytes(sebdeft2NameLength);          // Convert length string to bytes
            if (DrivesLog != null) DrivesLog("Encrypting DEFT2 Name Length");
            byte[] ebsebdeft2NameLength = fse.Encrypt(bsebdeft2NameLength);     // Encrypt
            if (DrivesLog != null) DrivesLog("Converting Encrypted DEFT2 Name Length to String");
            deft2NameLength = GetString(ebsebdeft2NameLength);                  // Convert to string

            if (DrivesLog != null) DrivesLog("Seeking to Correct Location");
            long startPos = GenerateDEFT2LengthStartPosition();
            fs.Seek(startPos, SeekOrigin.Current);    // Seek to correct location
            if (DrivesLog != null) DrivesLog("New Position " + startPos.ToString("N0"));
            if (DrivesLog != null) DrivesLog("Writing Encrypted Name Length to New Position");
            sw.Write(deft2NameLength);                                          // Write the Encrypted length
            fs.Flush();                                                         // Flush the buffer immediately
        }

我尝试使用此方法重新读取该位置的加密数据:

private long ReadDEFT2Len(string DEFT, long lenPos, FileSystemEncryption fse)
        {
            if (DrivesLog != null) DrivesLog("Reading DEFT2 Name Length");
            StringBuilder sb = new StringBuilder();

            FileStream fs = null;
            StreamReader sr = null;

            try
            {
                fs = new FileStream(DEFT, FileMode.Open, FileAccess.Read, FileShare.Read);
                sr = new StreamReader(fs, Encoding.Unicode);

                char[] C = new char[101];
                fs.Seek(lenPos, SeekOrigin.Begin);
                sr.Read(C, 0, 100);

                string sC = new string(C);
                byte[] bsC = GetBytes(sC);

                byte[] dRes = fse.Decrypt(bsC);  // This is where the Exception is thrown.
                foreach(char ic in GetString(dRes))
                {
                    if (ic == '!') break;
                    sb.Append(ic.ToString());
                }

                sr.Close();
                fs.Close();

                if (DrivesLog != null) DrivesLog("DEFT2 Name Length = " + sb.ToString());
                return long.Parse(sb.ToString());
            }
            catch (Exception ex)
            {
                if (DrivesLog != null) DrivesLog("ERROR Reading DEFT2 Name Length " + ex.Message);
                if (sr != null) sr.Close();
                if (fs != null) fs.Close();
                return -1;
            }

        }

我已使用Unicode编码保存并加载,因此这不是问题..有关为什么抛出此异常以及如何解决它的任何想法?

1 个答案:

答案 0 :(得分:1)

Rijndael密码仅适用于特定的块大小(16,24或32字节)。你在这里得到一个例外,因为你要解密的数据长度不是块大小的精确倍数。