Estou usando o iTextSharp para ler o texto de um arquivo PDF. No entanto, há momentos em que não consigo extrair texto, porque o arquivo PDF contém apenas imagens. Faço o download dos mesmos arquivos PDF todos os dias e quero ver se o PDF foi modificado. Se o texto e a data da modificação não puderem ser obtidos, uma soma de verificação MD5 é a maneira mais confiável de saber se o arquivo foi alterado?
Se for, alguns exemplos de código seriam apreciados, porque eu não tenho muita experiência com criptografia.
Respostas:
É muito simples usar System.Security.Cryptography.MD5 :
(Acredito que, na verdade, a implementação do MD5 usada não precisa ser descartada, mas provavelmente ainda o faria.)
Como você compara os resultados depois é com você; você pode converter a matriz de bytes em base64, por exemplo, ou comparar os bytes diretamente. (Lembre-se de que as matrizes não substituem
Equals
. Usar o base64 é mais simples de acertar, mas um pouco menos eficiente se você estiver realmente interessado apenas em comparar os hashes.)Se você precisar representar o hash como uma sequência, poderá convertê-lo em hexadecimal usando
BitConverter
:fonte
BitConverter.ToString(md5.ComputeHash(stream)).Replace("-","").ToLower();
.Replace("-", String.Empty)
é uma abordagem melhor. Passei por uma sessão de depuração de uma hora porque obtenho resultados errados ao comparar uma entrada do usuário com o hash do arquivo.É assim que eu faço:
fonte
using
blocos seria útil, porque a abertura de um arquivo provavelmente falhará. A abordagem de falha antecipada / rápida economiza os recursos necessários para criar (e destruir) a instância MD5 nesses cenários. Além disso, você pode omitir as chaves do primeirousing
e salvar um nível de indentação sem perder a legibilidade.Eu sei que esta pergunta já foi respondida, mas é isso que eu uso:
Onde GetHash :
Provavelmente não é o melhor caminho, mas pode ser útil.
fonte
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(); }
Aqui está uma versão um pouco mais simples que eu encontrei. Ele lê o arquivo inteiro de uma só vez e requer apenas uma única
using
diretiva.fonte
ReadAllBytes
é que ele carrega o arquivo inteiro em uma única matriz. Isso não funciona em arquivos maiores que 2 GiB e coloca muita pressão no GC, mesmo em arquivos de tamanho médio. A resposta de Jon é apenas um pouco mais complexa, mas não sofre com esses problemas. Então, eu prefiro a resposta dele à sua.using
s um após o outro sem os primeiros chavetasusing (var md5 = MD5.Create()) using (var stream = File.OpenRead(filename))
proporciona um uso por linha sem recuo desnecessário.using
diretiva". Não era realmente um bom motivo para ler tudo na memória. A abordagem mais eficaz é transmitir os dados paraComputeHash
, e, se possível,using
deve ser usada apenas, mas posso entender totalmente se você deseja evitar o nível extra de indentação.Sei que estou atrasado para a festa, mas realizei o teste antes de realmente implementar a solução.
Eu realizei teste contra a classe MD5 embutida e também o md5sum.exe . No meu caso, a classe incorporada levou 13 segundos, enquanto o md5sum.exe também ficou em torno de 16 a 18 segundos em cada execução.
fonte
E se você precisar calcular o MD5 para verificar se ele corresponde ao MD5 de um blob do Azure, esta pergunta e resposta do SO podem ser úteis: O hash do MD5 do blob carregado no Azure não corresponde ao mesmo arquivo na máquina local
fonte