2012-03-15 30 views
4

我遇到一些麻烦,下面的代码可以在读取。我有一个需要加密的临时位置的文件,这个函数会加密那些存储在“pathToSave”位置的数据。从CryptoStream就到流

在检查似乎并没有被正确地处理整个文件 - 有从我的输出失位,我怀疑它做的,而不是循环在整个流运行。

顺便说一句,如果我尝试和while循环后调用CryptStrm.Close()我收到一个异常。这意味着如果我试图解密文件,我得到一个已经在使用中的文件错误!

尝试了所有的常用和伊夫这里看着在类似的问题,任何帮助将是巨大的。

感谢

public void EncryptFile(String tempPath, String pathToSave) 
    { 
     try 
     { 
      FileStream InputFile = new FileStream(tempPath, FileMode.Open, FileAccess.Read); 
      FileStream OutputFile = new FileStream(pathToSave, FileMode.Create, FileAccess.Write); 

      RijndaelManaged RijCrypto = new RijndaelManaged(); 

      //Key 
      byte[] Key = new byte[32] { ... }; 

      //Initialisation Vector 
      byte[] IV = new byte[32] { ... }; 

      RijCrypto.Padding = PaddingMode.None; 
      RijCrypto.KeySize = 256; 
      RijCrypto.BlockSize = 256; 
      RijCrypto.Key = Key; 
      RijCrypto.IV = IV; 

      ICryptoTransform Encryptor = RijCrypto.CreateEncryptor(Key, IV); 

      CryptoStream CryptStrm = new CryptoStream(OutputFile, Encryptor, CryptoStreamMode.Write); 

      int data; 
      while (-1 != (data = InputFile.ReadByte())) 
      { 
       CryptStrm.WriteByte((byte)data); 
      } 
     } 
     catch (Exception EncEx) 
     { 
      throw new Exception("Encoding Error: " + EncEx.Message); 
     } 
    } 

编辑:

我所做的假设,我的问题是加密。我的解密可能是罪魁祸首

 public String DecryptFile(String encryptedFilePath) 
    { 
     FileStream InputFile = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read); 

     RijndaelManaged RijCrypto = new RijndaelManaged(); 

     //Key 
     byte[] Key = new byte[32] { ... }; 

     //Initialisation Vector 
     byte[] IV = new byte[32] { ... }; 

     RijCrypto.Padding = PaddingMode.None; 
     RijCrypto.KeySize = 256; 
     RijCrypto.BlockSize = 256; 
     RijCrypto.Key = Key; 
     RijCrypto.IV = IV; 

     ICryptoTransform Decryptor = RijCrypto.CreateDecryptor(Key, IV); 

     CryptoStream CryptStrm = new CryptoStream(InputFile, Decryptor, CryptoStreamMode.Read); 

     String OutputFilePath = Path.GetTempPath() + "myfile.name"; 
     StreamWriter OutputFile = new StreamWriter(OutputFilePath); 

     OutputFile.Write(new StreamReader(CryptStrm).ReadToEnd()); 

     CryptStrm.Close(); 
     OutputFile.Close(); 

     return OutputFilePath; 
    } 

回答

12

好吧,这里有几件事情出错了。

1.您设置IV过大的尺寸。如果您的密钥大小为256,Rijndael的IV为16个字节。如果您尝试使用比该字节更多的字节来设置密钥,则会发生异常。 IV尺寸应设置为块尺寸/ 8 see MSDN,因此您拥有的IV尺寸是正确的。

  • 您有无的填充模式。除非你的数据是正确的块大小,否则你将会遇到问题。您可能想要选择填充模式。
  • 当您在加密时写入密码流时,通常需要调用FlushFInalBlock以确保将所有数据写入流中。
  • 我发布了一些示例代码,使用内存流来显示加密和解密。

    var tempData = "This is the text to encrypt. It's not much, but it's all there is."; 
    
    using (var rijCrypto = new RijndaelManaged()) 
    { 
        byte[] encryptedData; 
        rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126; 
        rijCrypto.KeySize = 256; 
    
        using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData))) 
        using (var output = new MemoryStream()) 
        { 
         var encryptor = rijCrypto.CreateEncryptor(); 
    
         using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) 
         { 
          var buffer = new byte[1024]; 
          var read = input.Read(buffer, 0, buffer.Length); 
          while (read > 0) 
          { 
           cryptStream.Write(buffer, 0, read); 
           read = input.Read(buffer, 0, buffer.Length); 
          } 
          cryptStream.FlushFinalBlock(); 
          encryptedData = output.ToArray(); 
         } 
        } 
    
        using (var input = new MemoryStream(encryptedData)) 
        using (var output = new MemoryStream()) 
        { 
         var decryptor = rijCrypto.CreateDecryptor(); 
         using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) 
         { 
          var buffer = new byte[1024]; 
          var read = cryptStream.Read(buffer, 0, buffer.Length); 
          while (read > 0) 
          { 
           output.Write(buffer, 0, read); 
           read = cryptStream.Read(buffer, 0, buffer.Length); 
          } 
          cryptStream.Flush(); 
          var result = Encoding.Unicode.GetString(output.ToArray()); 
         } 
        } 
    } 
    
    +0

    谢谢pstrjds - 我做了一些改变,但仍然有问题。 IV现在是16个字节,填充是零,我已经改变了我的while循环,看起来更像是你的建议,但当我调用FlushFinalBlock时,我仍然得到错误 - “方法在CryptoStream上调用两次,只能调用一次” 。尽管如此,我不相信它已被称为第一位! – David 2012-03-16 09:15:44

    +0

    那么,你应该只在调用循环之外调用FlushFinalBlock作为加密时的最后一件事。你不需要在解密时调用它,解密时只需调用Flush。当你解密时你的块大小应该是正确的,所以不需要添加任何填充。就相信它是否被调用而言,您可以在调试器下运行您的代码并在该行设置一个中断点。如果它没有击中它,那么它不会被调用。 – pstrjds 2012-03-16 12:48:39

    +1

    _如果你的密钥大小为256,Rijndael的IV是16个字节。如果你试图设置比这个字节更多的字节,你将会得到一个异常。如果你有'BlockSize = 256',那么你的IV应该是32,这是不正确的。如果它们不匹配,那么你将得到一个例外。 – Trisped 2013-03-02 05:00:05