iTextSharp 를 사용하여 PDF 파일에서 텍스트를 읽습니다. 그러나 PDF 파일에는 이미지 만 포함되어 있기 때문에 텍스트를 추출 할 수없는 경우가 있습니다. 매일 동일한 PDF 파일을 다운로드하고 PDF가 수정되었는지 확인하고 싶습니다. 텍스트 및 수정 날짜를 얻을 수없는 경우 MD5 체크섬이 파일이 변경되었는지 확인하는 가장 신뢰할 수있는 방법입니까?
그렇다면 암호화에 대한 경험이 많지 않기 때문에 일부 코드 샘플이 좋습니다.
iTextSharp 를 사용하여 PDF 파일에서 텍스트를 읽습니다. 그러나 PDF 파일에는 이미지 만 포함되어 있기 때문에 텍스트를 추출 할 수없는 경우가 있습니다. 매일 동일한 PDF 파일을 다운로드하고 PDF가 수정되었는지 확인하고 싶습니다. 텍스트 및 수정 날짜를 얻을 수없는 경우 MD5 체크섬이 파일이 변경되었는지 확인하는 가장 신뢰할 수있는 방법입니까?
그렇다면 암호화에 대한 경험이 많지 않기 때문에 일부 코드 샘플이 좋습니다.
답변:
System.Security.Cryptography.MD5 사용하면 매우 간단합니다 .
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return md5.ComputeHash(stream);
}
}
( 실제로 사용 된 MD5 구현은 폐기 할 필요는 없지만, 여전히 그렇게 할 것입니다.)
나중에 결과를 비교하는 방법은 귀하에게 달려 있습니다. 예를 들어 바이트 배열을 base64로 변환하거나 바이트를 직접 비교할 수 있습니다. (배열은 재정의하지 않습니다 Equals
. base64를 사용하는 것이 더 간단하지만 해시 비교에만 관심이 있다면 약간 덜 효율적입니다.)
해시를 문자열로 나타내야하는 경우 다음을 사용하여 해시를 16 진수로 변환 할 수 있습니다 BitConverter
.
static string CalculateMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
BitConverter.ToString(md5.ComputeHash(stream)).Replace("-","").ToLower();
.Replace("-", String.Empty)
더 나은 접근법 이라고 생각 합니다. 사용자 입력을 파일 해시와 비교할 때 잘못된 결과가 나오기 때문에 1 시간 디버그 세션을 거쳤습니다.
이것이 내가하는 방법입니다.
using System.IO;
using System.Security.Cryptography;
public string checkMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return Encoding.Default.GetString(md5.ComputeHash(stream));
}
}
}
using
파일을 여는 것이 실패 할 가능성이 높기 때문에 블록을 바꾸는 것이 유용 할 것이라고 생각합니다 . 조기 / 빠른 접근 실패는 이러한 시나리오에서 MD5 인스턴스를 생성 및 파괴하는 데 필요한 리소스를 절약합니다. 또한 첫 번째 중괄호를 생략하고 using
가독성을 잃지 않고 들여 쓰기 수준을 저장할 수 있습니다.
나는이 질문에 이미 답변되었지만 이것이 내가 사용하는 것입니다.
using (FileStream fStream = File.OpenRead(filename)) {
return GetHash<MD5>(fStream)
}
어디 GetHash :
public static String GetHash<T>(Stream stream) where T : HashAlgorithm {
StringBuilder sb = new StringBuilder();
MethodInfo create = typeof(T).GetMethod("Create", new Type[] {});
using (T crypt = (T) create.Invoke(null, null)) {
byte[] hashBytes = crypt.ComputeHash(stream);
foreach (byte bt in hashBytes) {
sb.Append(bt.ToString("x2"));
}
}
return sb.ToString();
}
아마도 가장 좋은 방법은 아니지만 유용 할 수 있습니다.
public static String GetHash<T>(this Stream stream) where T : HashAlgorithm, new() { StringBuilder sb = new StringBuilder(); using (T crypt = new T()) { byte[] hashBytes = crypt.ComputeHash(stream); foreach (byte bt in hashBytes) { sb.Append(bt.ToString("x2")); } } return sb.ToString(); }
여기 내가 찾은 약간 더 간단한 버전이 있습니다. 전체 파일을 한 번에 읽고 단일 using
지시문 만 필요합니다 .
byte[] ComputeHash(string filePath)
{
using (var md5 = MD5.Create())
{
return md5.ComputeHash(File.ReadAllBytes(filePath));
}
}
ReadAllBytes
전체 파일을 단일 배열로로드한다는 것입니다. 2GiB보다 큰 파일에서는 전혀 작동하지 않으며 중간 크기 파일에서도 GC에 많은 부담을줍니다. Jon의 대답은 약간 더 복잡하지만 이러한 문제로 고통받지 않습니다. 그래서 나는 당신보다 그의 대답을 선호합니다.
using
첫 번째 중괄호 using (var md5 = MD5.Create()) using (var stream = File.OpenRead(filename))
없이 서로를 s에 넣으면 불필요한 들여 쓰기없이 한 줄에 하나씩 사용할 수 있습니다.
using
지시어 만 있으면된다"는 것이 었습니다 . 모든 것을 메모리로 읽어야하는 좋은 이유는 아니 었습니다. 보다 효과적인 접근 방식은 데이터를에 스트리밍하는 것이며 ComputeHash
가능한 using
경우에만 사용해야하지만 추가 수준의 들여 쓰기를 피하려면 완전히 이해할 수 있습니다.
나는 파티에 늦었지만 실제로 솔루션을 구현하기 전에 테스트를 수행했다는 것을 알고 있습니다.
내장 MD5 클래스와 md5sum.exe 에 대한 테스트를 수행 했습니다 . 필자의 경우 내장 클래스는 md5sum.exe가 매 실행마다 16-18 초 정도 걸리는 13 초가 걸렸습니다.
DateTime current = DateTime.Now;
string file = @"C:\text.iso";//It's 2.5 Gb file
string output;
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(file))
{
byte[] checksum = md5.ComputeHash(stream);
output = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();
Console.WriteLine("Total seconds : " + (DateTime.Now - current).TotalSeconds.ToString() + " " + output);
}
}
그리고 MD5를 계산하여 Azure Blob의 MD5와 일치하는지 확인해야하는 경우이 SO 질문과 답변이 도움이 될 수 있습니다. Azure에 업로드 된 BLOB의 MD5 해시가 로컬 컴퓨터의 동일한 파일과 일치하지 않습니다.