Рассчитать контрольную сумму 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,
        };
    }
    
    ...
}

https://www.questpdf.com/concepts/document-metadata.html

Другие вопросы по тегам