Рассчитать контрольную сумму MD5 для файла
Я использую iTextSharp, чтобы прочитать текст из файла PDF. Однако иногда я не могу извлечь текст, потому что файл PDF содержит только изображения. Я загружаю одни и те же файлы PDF каждый день, и я хочу посмотреть, был ли PDF изменен. Если текст и дата модификации не могут быть получены, является ли контрольная сумма MD5 наиболее надежным способом определить, изменился ли файл?
Если это так, некоторые примеры кода будут оценены, потому что у меня нет большого опыта в криптографии.
8 ответов
Это очень просто, используя System.Security.Cryptography.MD5:
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
return md5.ComputeHash(stream);
}
}
(Я считаю, что на самом деле используемую реализацию MD5 не нужно утилизировать, но я все равно, вероятно, все равно буду это делать.)
Как вы сравниваете результаты впоследствии, зависит от вас; например, вы можете преобразовать байтовый массив в base64 или сравнить байты напрямую. (Просто знайте, что массивы не переопределяют Equals
, Использовать base64 проще, но немного менее эффективно, если вы действительно заинтересованы только в сравнении хешей.)
Если вам нужно представить хеш в виде строки, вы можете преобразовать его в шестнадцатеричный формат, используя 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();
}
}
}
Вот как я это делаю:
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 (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();
}
Вероятно, не самый лучший способ, но это может быть удобно.
Вот немного более простая версия, которую я нашел. Он читает весь файл за один раз и требует только одного using
директивы.
byte[] ComputeHash(string filePath)
{
using (var md5 = MD5.Create())
{
return md5.ComputeHash(File.ReadAllBytes(filePath));
}
}
Я знаю, что опоздал на вечеринку, но выполнил тест, прежде чем на самом деле реализовать решение.
Я выполнил тест на встроенный класс MD5, а также md5sum.exe. В моем случае встроенный класс занял 13 секунд, где md5sum.exe тоже примерно 16-18 секунд при каждом запуске.
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, чтобы увидеть, соответствует ли он MD5 большого двоичного объекта Azure, то этот вопрос и ответ SO могут оказаться полезными: MD5-хэш большого двоичного объекта, загруженный в Azure, не совпадает с тем же файлом на локальном компьютере.
Для динамически создаваемых PDF-файлов. Дата создания и даты изменения всегда будут разными.
Вы должны удалить их или установить для них постоянное значение.
Затем сгенерируйте хэш md5 для сравнения хэшей.
Вы можете использовать
PDFStamper
удалить или обновить даты.
В дополнение к методам, указанным выше, если вы сравниваете PDF-файлы, вам необходимо изменить даты создания и изменения, иначе хэши не будут совпадать.
Для PDF-файлов, созданных с помощью QuestPdf, вам необходимо переопределитьCreationDate
иModifiedDate
в метаданных документа .
public class PdfDocument : IDocument
{
...
DocumentMetadata GetMetadata()
{
return new()
{
CreationDate = DateTime.MinValue,
ModifiedDate = DateTime.MinValue,
};
}
...
}