2012-03-15 2 views
4

아래 코드에 문제가 있습니다. 암호화가 필요한 임시 위치에 파일이 있습니다.이 함수는 "pathToSave"위치에 저장된 데이터를 암호화합니다.스트림 끝까지의 암호문 읽기

검사에서 전체 파일을 제대로 처리하지 못하는 것 같습니다. 출력에 누락 된 비트가 있고 전체 루프에서 실행되지 않는 while 루프와 관련이 있다고 생각됩니다.

예외적으로, 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 크기는 Block size/8 see MSDN으로 설정해야합니다. 따라서 IV 크기가 정확합니다.

  1. 패딩 모드가 없음입니다. 데이터가 정확한 블록 크기가 아니라면 문제가 발생할 것입니다. 패딩 모드를 선택하는 것이 좋습니다.
  2. 일반적으로 모든 데이터가 스트림에 기록되도록 암호화 할 때 암호화 스트림에 쓰면 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 바이트입니다. 패딩은 0입니다. 내 while 루프를 제안과 비슷하게 변경했지만 FlushFinalBlock을 호출하면 오류가 발생합니다. - "메서드가 CryptoStream에서 두 번 호출되었으며, 한 번만 호출 할 수 있습니다." . 나는 그것이 처음부터 불러 졌다고 믿지 않는다! – David

+0

글쎄, 암호화 할 때 마지막으로 루프 밖에서 FlushFinalBlock 만 호출하면됩니다. 해독 할 때 호출 할 필요가 없습니다. 해시를 호출 할 때 그냥 플러시를 호출하십시오. 해독 할 때 블록 크기가 정확해야하므로 패딩을 추가 할 필요가 없습니다. 호출 여부에 관계없이 디버거에서 코드를 실행하고 해당 줄에 중단 점을 설정할 수 있습니다. 그것이 부딪치지 않으면 호출되지 않았습니다. – pstrjds

+1

_ 키 크기가 256 인 경우 Rijndael의 IV는 16 바이트입니다. 만약 당신이 그 이상의 바이트를 가진 키를 설정하려고하면 예외를 얻게 될 것입니다. _ 올바르지 않습니다. 만약 당신이'BlockSize = 256'을 가지고 있다면 당신의 IV는 32가되어야합니다. 예외. – Trisped