2014-09-30 11 views
11

나는 다음과 같은 사용 사례가 : 파일에서.NET HashAlgorithm (반복되는 증분 해시 결과의 경우)을 복사 할 수 있습니까?

  • 읽기 N 바이트
  • 이 n 바이트를위한
  • 계산 (MD5) 해시 파일
  • 계산 (MD5) 해시에서
  • 읽기 다음 m 바이트 최대 n + m 바이트까지의 파일에 대해

파일을 점진적으로 해싱하면 just call TransformBlock and TransformFinalBlock이 문제가되지 않습니다.

문제

는 나는 그것의 시작 바이트를 공유하는 데이터의 여러 해시 필요하지만, 내가 TransformFinalBlock 전화 후 나는 같은 객체와 해시 계속할 수있는 최초의 n 바이트 Hash를 읽고 새로운 하나를 필요로한다는 것이다. (반환을

hash.copy()

사본을 :

문제 검색, 둘 다 Python뿐만 아니라 OpenSSL 정확히 이러한 목적을 위해 해싱 개체를 복사 할 수있는 옵션을 가지고 보았다 "복제"). 이 은 공통 초기 하위 문자열을 공유하는 문자열의 다이제스트를 효율적으로 계산하는 데 사용할 수 있습니다.

 

EVP_MD_CTX_copy_ex()는 아웃 메시지에 상태에서 소화 복사하는데 사용될 수있다. 대용량의 데이터가 마지막 바이트 인에서만 차이가있는 으로 해시 될 때 유용합니다. 이 함수를 호출하기 전에 out을 으로 초기화해야합니다. 해시 계속 나중에하고 -

나는, 나는 그것의 TransformFinalBlock 메소드를 호출 전에 나를 Clone() ==는 객체 를 복사 효율적으로 할 수 있도록 할 주식의 C# HashAlgorithm withing에 아무것도 찾을 수 있습니다으로 검색 복제본과 함께 나머지 데이터.

클로닝 (*)을 지원하기 위해 쉽게 조정할 수 있지만 코드베이스에 그러한 것을 도입하는 대신 무엇을 사용하는 것이 좋습니다.

이러한 알고리즘은이 모든 상태가의 한 형태이기 때문에 (*) 사실, 지금까지의 내가 이해, 어떤 해싱 알고리즘 (암호화/암호 해독 반대) 나는 확인할 방해 한 하찮게 복사 가능한 것입니다 요람.

그래서 여기에 뭔가가 없거나 실제로 표준 C#/.NET 인터페이스가 해시 객체를 복사하는 방법을 제공하지 않습니다.


또 다른 데이터 포인트는 :

CryptDuplicateHash 기능을 만드는 데 사용할 수 있습니다 :

crypto services에 대한 마이크로 소프트의 자신의 네이티브 API 함수 CryptDuplicateHash, 국가의 문서, 견적을했다 동일한 내용으로 시작하는 두 개의 서로 다른 내용으로 된 의 해시를 분리하십시오.

Windows XP 이후. : - |


참고 wrt. MD5 : 유즈 케이스는 암호 학적으로 민감하지 않습니다. 신뢰할 수있는 파일 체크섬.

+0

일부 클래스는 쉽게 복제 할 수 없지만 일부 리소스는 원시 리소스를 사용하거나 핸들이있는 특수 하드웨어를 호출 할 수 있습니다. 이러한 유형의 클래스는 복제하기가 쉽지 않습니다. –

+0

@ 스콧 - 고마워. 네, 수업이있을 것 같아요. 여전히 MD5와 같은 것은 * 복제가 가능해야합니다. 그럼 방법이 없나요? –

+0

얕은 복사본을 원한다면 모든 것을 반복하고 직접 만들어야하는 것처럼 보입니다. –

답변

3

한숨

주식 .NET 라이브러리는이를 허용하지 않습니다. 슬퍼.어쨌든, 대안의 몇 가지 있습니다 :

  • MD5Managed pure .NET ("기본"MD5 RSA 라이센스)
  • PInvoke를 통해 MS 크립토 API (추출하는 몇 가지 작업을해야 할 수도 있습니다 랩
  • ClonableHashOrg.Mentalis 네임 스페이스 만에서 예비 시험이 정상적인 .NET 라이브러리보다 훨씬 더 빠른 것 같다 것으로 나타났습니다,하지만하지 않습니다 - 라이센스는 예를 들어 C++/CLI 래퍼의 C++ implementation 포장에

그것은도 가능) 허용입니다 내 말은. 나 또한 쓴/자신은 C++ 기반의 솔루션을 채택하기 때문에


: https://github.com/bilbothebaggins/md5cpp

요구 사항이 변경 되었기 때문에 그것은, 생산에 사라하지 않았지만 그것은 좋은 운동이고 나는 그것을 생각하고 싶다 꽤 잘 작동합니다. (순수한 C# 구현이 아닌 것)

4

나는 이것이 당신이 요구하는 것과 정확히 일치하지 않는다는 것을 알고 있습니다. 그러나 이것이 당신이 해결하려고하는 문제와 일치한다면 그것은 당신에게 동일한 보장을 줄 수있는 대안적인 접근이라고 말합니다. & 유사한 스트리밍 성능 특성. 나는 송신자/수신자가 항상 이용 가능/신뢰할 수있는 것은 아닌 서버 대 서버 파일 전송 프로토콜에 대해 이것을 과거에 사용 해왔다. 허락하신다면, 나는 당신이 모른다는 것을 깨닫는 전선 양면의 코드에 대한 통제권을 가졌습니다. 그 경우에는 무시하십시오 ;-)

내 접근 방식은 전체 파일을 처리하는 HashAlgorithm과 파일의 고정 크기 블록 해시를 설정하는 것입니다 (문제를 피할 수는 없지만). 독립형 해시. 따라서 논리적으로 32MB 블록으로 분리 된 1034MB (1GB + 10MB) 파일을 상상해보십시오. 보낸 사람이 파일을로드하고 파일 수준과 블록 수준의 HashAlgorithm 모두에서 TransformBlock을 동시에 호출합니다. 32MB가 끝나면 블록 레벨에서 TransformFinalBlock을 호출하고 해당 블록의 해시를 기록한 후 다음 블록에 대해 새 HashAlgorithm을 재설정/만들었습니다. 파일의 끝에 도달하면 파일 및 블록 수준의 해머에서 TransformFinalBlock을 호출했습니다. 이제 보낸 사람은 파일 이름, 파일 크기, 파일 해시 및 각 블록의 오프셋, 길이 및 해시를 포함하는 전송 계획을 마련했습니다.

새 파일 (파일 길이 % 블록 크기는 마지막 블록이 32MB보다 작음을 알립니다)에 대한 공간을 할당하거나 기존 파일을 열어 놓은 계획을 수신자에게 보냈습니다. 파일이 이미 있으면 동일한 알고리즘을 실행하여 크기가 동일한 블록의 해시를 계산합니다. 계획과의 모든 불일치로 인해 보낸 사람에게 해당 블록 만 요청하게되었습니다 (이는 아직 전송되지 않은 블록/모두 0과 손상된 블록을 나타냅니다). 이 작업을 수행 (확인, 블록 요청) 할 때까지 루프에서 작동합니다. 그런 다음 파일 수준의 해시를 계획과 비교하여 검사했습니다. 파일 수준 해시가 유효하지 않지만 블록 수준 해시가 모두 유효한 경우 해시 콜리 션 또는 불량 RAM (매우 드문 경우 ... SHA-512 사용)을 의미합니다. 이로 인해 수신기가 불완전한 블록이나 손상된 블록에서 복구 할 수있었습니다. 최악의 시나리오로 인해 1 개의 불량 블록을 다시 다운로드해야하는 불이익이있었습니다. 이는 블록 크기를 조정하여 상쇄 될 수 있습니다.

+0

감사드립니다. 성능이 관련성이 없거나 (예 : 파일 전송 속도와 관련이없는 경우) 동시에 두 해시를 실행하는 것은 확실히 해결책입니다. –

+0

@MartinBa 당신은 그의 솔루션을 조정할 수 있습니다, 청크 해시를 사용하지만 다음 청크에 대한 입력에서 당신은 이전 청크의 출력을 concat. 해시를 "복사"하려면 다른 파일의 동일한 오프셋에서 다시 시작한 다음 첫 번째 파일의 이전 청크에서 출력 한 내용으로 채 웁니다. 기본적으로 [CBC 암호화 모드] (http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29)와 비슷한 알고리즘을 사용하지만 입력을 XOR하는 대신 연결합니다. –

+1

오버 헤드가 나쁘지 않습니다. 나는 한 번에 32kb/64kb 바이트의 파일을 버퍼로 읽었습니다. 두 인스턴스 모두 동일한 byte [] 버퍼를 처리하므로 해싱을 두 번 수행 할 때 디스크 I/O 패널티가 발생하지 않습니다. I/O는 대부분의 속도 위반이 발생하는 곳입니다. – scottt732