2012-07-12 2 views
1

선택한 파일에 대해 MD5, MD4, SHA1, SHA256, SHA512, RIPEMD160 등의 계산을하고 있습니다. 다음 알고리즘을 만들었지 만 문제가 있습니다.C#에서 해시 계산

 string finalHash; 
     byte[] buffer; 
     byte[] oldBuffer; 
     int bytesRead; 
     int oldBytesRead; 
     long streamSize; 
     long totalBytesRead = 0; 
     try 
     { 
      if (!String.IsNullOrEmpty(selectedFile)) 
      { 
       _dataStream = File.OpenRead(selectedFile); 
       selectedFile = string.Empty; 
      } 
      foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject) 
      { 
       //totalBytesRead = 0; 
       streamSize = _dataStream.Length; 
       buffer = new byte[4096]; 
       bytesRead = _dataStream.Read(buffer, 0, buffer.Length); 
       totalBytesRead += bytesRead; 
       do 
       { 
        oldBytesRead = bytesRead; 
        oldBuffer = buffer; 
        buffer = new byte[4096]; 
        bytesRead = _dataStream.Read(buffer, 0, buffer.Length); 
        totalBytesRead += bytesRead; 
        if (bytesRead == 0) 
        { 
         hashObject.TransformFinalBlock(oldBuffer, 0, oldBytesRead); 
        } 
        else 
        { 
         hashObject.TransformBlock(oldBuffer, 0, oldBytesRead, oldBuffer, 0); 
        } 
        hashCalculationWorker.ReportProgress((int)((double)totalBytesRead * 100/streamSize)); 
       } while (bytesRead != 0); 
       e.Result = hashObject.Hash; 
       finalHash = GenerateHex(hashObject.Hash); 
       Invoke(new MethodInvoker(() => 
              { 
               // Get finalHash 
              })); 
       hashObject.Dispose(); 
      } 
     } 
     catch (Exception) 
     { 
     } 


     private HashAlgorithm HashObject 
     {   
      get 
      { 
       if (isMD5Selected) 
       { 
        _hashObject = MD5.Create(); 
        isMD5Selected = false; 
       } 
       else if (isMD4Selected) 
       { 
        _hashObject = MD4.Create(); 
        isMD4Selected = false; 
       } 
       else if (isSHA1Selected) 
       { 
        _hashObject = SHA1.Create(); 
        isSHA1Selected = false; 
       } 
       ... 
       return _hashObject; 
       } 
      } 

위의 코드에서 foreach 문은 선택한 해시 알고리즘의 수에 따라 다릅니다. 첫 번째 선택된 해시를 올바르게 계산하지만 두 번째 및 다음 반복마다 다른 값을 제공합니다. 뭐가 잘못 됐어. 아무도 나를 도울 수 있습니까? 미리 감사드립니다.

+4

처음에는'_dataStream'을 재설정하지 않았습니다 ... –

+1

내 머리 꼭대기에서 변수와 데이터 스트림을 올바르게 재설정하지 않았습니다. – KingCronus

+0

@KingCronus 각 반복마다 _dataStream을 가져와야합니까? –

답변

2

루프를 통해 반복 할 때마다 내용을 다시 읽을 수 있도록 스트림을 재설정하지 않습니다. 버퍼 관리 논리를 상당히 단순화 할 수 있으므로 finally 블록에서 hashObject.Dispose을 호출하여 예외가 발생할 경우 리소스가 해제되도록하는 것이 바람직합니다.

 streamSize = _dataStream.Length; 
     buffer = new byte[4096]; 
     foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject) 
     { 
      try 
      { 
       // reset stream position, progress 
       _dataStream.Position = 0; 
       _totalBytesRead = 0; 

       do 
       { 
        bytesRead = _dataStream.Read(buffer, 0, buffer.Length); 
        totalBytesRead += bytesRead; 
        if (_dataStream.Position == _dataStream.Length) 
        { 
         hashObject.TransformFinalBlock(buffer, 0, bytesRead); 
        } 
        else 
        { 
         hashObject.TransformBlock(buffer, 0, bytesRead, buffer, 0); 
        } 
        hashCalculationWorker.ReportProgress((int)((double)totalBytesRead * 100/streamSize)); 
       } while (_dataStream.Position < _dataStream.Length); 

       e.Result = hashObject.Hash; 
       finalHash = GenerateHex(hashObject.Hash); 
       Invoke(new MethodInvoker(() => 
              { 
               // Get finalHash 
              })); 
      } 
      finally 
      { 
       hashObject.Dispose(); 
      } 
     } 

나은 솔루션 파일이 크지 않은 경우 :

그런 다음 한번 버퍼에 스트림에서의 모든 데이터를 판독하도록 더 확대됨 이어도되고, 다시 사용

 if (!String.IsNullOrEmpty(selectedFile)) 
     { 
      buffer = File.ReadAllBytes(selectedFile); 
      streamSize = buffer.Length; 
      selectedFile = string.Empty; 
     } 

     foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject) 
     { 
      int offset = 0; 
      while (buffer.Length - offset >= streamSize) 
      { 
       offset += hashObject.TransformBlock(buffer, offset, streamSize, buffer, offset); 
       hashCalculationWorker.ReportProgress((int)((double)offset * 100/streamSize)); 
      } 

      hashObject.TransformFinalBlock(buffer, offset, buffer.Length - offset); 
      hashCalculationWorker.ReportProgress(100); 

      e.Result = hashObject.Hash; 
      finalHash = GenerateHex(hashObject.Hash); 
      Invoke(new MethodInvoker(() => 
             { 
              // Get finalHash 
             })); 
      hashObject.Dispose(); 
     } 
+0

고마워요. 나는 큰 파일에 대한 귀하의 솔루션을 시도했다. 그것은 올바르게 작동하지만 각 해시 알 고에 (큰 파일을 사용하여) 많은 시간이 걸리지 만, 만약 내가 각 반복을 메소드로 분리하고 하나씩 호출한다면, 첫 번째 메소드에서만 시간이 걸리며 _dataStream을 재설정 할 필요가 없습니다. 그러나이 기술에서는 줄 수가 늘어나 많은 시간을 보냈습니다. –

+0

@ M.NasserJavaid 어떻게 든 각 해시 알고리즘을 통해 동일한 데이터를 가져와야합니다. 모든 데이터를 한 번 미리로드하거나 ('File.ReadAllBytes'), 매번 다시 읽어야합니다. 즉, 스트림을 다시 설정해야합니다. –

관련 문제