Ich möchte Java verwenden, um die MD5-Prüfsumme einer Datei abzurufen. Ich war wirklich überrascht, aber ich konnte nichts finden, das zeigt, wie man die MD5-Prüfsumme einer Datei erhält.
Vielleicht dies helfen. Sie könnten auch die Spezifikation nachschlagen, aber das würde mehr Arbeit erfordern, da es kompliziert ist.
Waynecolvin
4
Denken Sie daran, dass laut der jüngsten Forschung "MD5 als kryptografisch defekt und für die weitere Verwendung ungeeignet angesehen werden sollte". en.wikipedia.org/wiki/MD5
Zakharia Stanley
80
MD5 wird nicht mehr als kryptografisch sicher angesehen, reicht jedoch zur Überprüfung der Dateikonsistenz aus und ist schneller als SHA.
Jiggy
2
@ZakhariaStanley Dies ist eine Frage zur Prüfsumme.
iPherian
Die kanonische Verwendung für MD5-Prüfsummen für Dateien besteht darin, das feindliche Ersetzen verteilter Dateien zu vermeiden. Dort ist es unsicher. Aber in einem Szenario, in dem feindliche Exploits keine Rolle spielen, ist es perfekt geeignet.
Keith Tyler
Antworten:
541
Es gibt einen Dekorator für Eingabestreams, java.security.DigestInputStreammit dem Sie den Digest berechnen können, während Sie den Eingabestream wie gewohnt verwenden, anstatt einen zusätzlichen Durchlauf über die Daten durchführen zu müssen.
MessageDigest md =MessageDigest.getInstance("MD5");try(InputStream is =Files.newInputStream(Paths.get("file.txt"));DigestInputStream dis =newDigestInputStream(is, md)){/* Read decorated stream (dis) to EOF as normal... */}byte[] digest = md.digest();
Ich bin damit einverstanden, eine sehr elegante Methode, um die Prüfsumme im laufenden Betrieb zu berechnen, wenn Sie bereits etwas mit den Bytes tun (dh sie über eine HTTP-Verbindung einlesen).
Marc Novakowski
2
@AlPhaba Hast du das isals InputStreamoder oder deklariert FileInputStream? Klingt wie Sie verwendet FileInputStream, was diesen Fehler verursachen würde.
Erickson
1
@barwnikk Es funktioniert gut in Java 8. MethodNotFoundist keine Ausnahme von Standard-Java; Vielleicht sprechen Sie über einen Compilerfehler? In jedem Fall liegt ein lokales Konfigurationsproblem oder ein Problem mit anderem Code vor, wenn es bei Ihnen nicht funktioniert.
Erickson
4
@barwnikk Auch dies ist Ihr lokales Konfigurationsproblem. Dies ist gültiger Java 7- und Java 8-Code. Wenn Sie mit Werkzeugen aus dem Jahr 2006 nicht weiterkommen, müssen Sie sich anpassen.
Erickson
5
@erickson Sie aktualisieren das MessageDigest-Objekt nicht mit dem Dateiinhalt. Rt? Dieser Code gibt immer den gleichen Digest aus.
Funktioniert nicht für mich in meinem Android-Code Ich erhalte diesen Fehler ... java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString bei org.apache.commons.codec.digest.DigestUtils.md5Hex (DigestUtils.java:215)
JPM
@JPM Angenommen, Sie haben das heruntergeladen und commons-codec.jarbereits auf Ihren Klassenpfad gesetzt?
Leif Gruenwoldt
Ja, und ich habe in mein Android-Projekt exportiert. Ich kann den Code durchgehen und die Klasse befindet sich in den Quelldateien. Seltsam, muss ein Android-Eclipse-Problem sein.
JPM
1
Ich hatte das gleiche Problem, aber es wurde durch diesen Code behoben: FileInputStream fis = new FileInputStream (neue Datei (filePath)); Byte-Daten [] = org.apache.commons.codec.digest.DigestUtils.md5 (fis); char md5Chars [] = Hex.encodeHex (Daten); String md5 = String.valueOf (md5Chars); `
Dmitry_L
1
Nett! Bei neuen Projekten denke ich immer zweimal darüber nach, bevor ich eine neue Abhängigkeit hinzufüge, aber bei bestehenden Projekten muss ich nur prüfen, ob die Bibliothek bereits vorhanden ist, um sie zu verwenden. +1
Files.hash()Berechnet für Ihren Anwendungsfall den Digest-Wert für eine Datei und gibt ihn zurück.
Zum Beispiel a sha-1 Digest-Berechnung (SHA-1 in MD5 ändern, um MD5-Digest zu erhalten)
HashCode hc =Files.asByteSource(file).hash(Hashing.sha1());"SHA-1: "+ hc.toString();
Beachten Sie, dass crc32 ist viel schneller als md5, also benutze crc32wenn Sie keine kryptografisch sichere Prüfsumme benötigen. Beachten Sie auch dasmd5 sollte nicht zum Speichern von Passwörtern und dergleichen verwendet werden, da es für die Verwendung von Passwörtern zu einfach ist, Gewalt anzuwenden bcrypt, verschlüsseln oder sha-256 stattdessen.
Für den Langzeitschutz mit Hashes erhöht ein Merkle-Signaturschema die Sicherheit, und die von der Europäischen Kommission geförderte Post Quantum Cryptography Study Group hat die Verwendung dieser Kryptographie zum Langzeitschutz gegen Quantencomputer empfohlen ( Ref ).
Beachten Sie, dass crc32 hat eine höhere Kollisionsrate als die anderen.
@Arash ja absolut - danke. Ich habe die JDK Files-Klasse und die von Guava verwechselt.
Assylias
Ich mag diese Lösung mehr als die von erickson, da sie mit Optionals umwickelt werden kann, um reine funktionale Programmierung zu verwenden
Gabriel Hernandez
2
Bei einer großen Datei wird viel Speicher benötigt, da die gesamte Datei gelesen und dann dem Digest zugeführt wird, anstatt Chunks zu lesen und sie beim Lesen zu "verdauen".
Bernie
39
Guava bietet jetzt eine neue, konsistente Hashing-API, die viel benutzerfreundlicher ist als die verschiedenen im JDK bereitgestellten Hashing-APIs. Siehe Hashing erklärt . Für eine Datei können Sie die MD5-Summe, CRC32 (mit Version 14.0+) oder viele andere Hashes einfach abrufen:
HashCode md5 =Files.hash(file,Hashing.md5());byte[] md5Bytes = md5.asBytes();String md5Hex = md5.toString();HashCode crc32 =Files.hash(file,Hashing.crc32());int crc32Int = crc32.asInt();// the Checksum API returns a long, but it's padded with 0s for 32-bit CRC// this is the value you would get if using that API directlylong checksumResult = crc32.padToLong();
OK. Ich musste hinzufügen. Einzeilige Implementierung für diejenigen, die bereits von Spring und Apache Commons abhängig sind oder diese hinzufügen möchten:
Es istDigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Duleshi
Die auf Commons basierende Lösung von David Onter ist besser, da nicht eine ganze Datei in den Speicher eingelesen wird.
Fran Marzoa
Zumindest müssen Spring 5 Sie DigestUtils.md5Digest(InputStream inputStream)den MD5-Digest und die DigestUtils.md5DigestAsHex(InputStream inputStream)hexadezimale Zeichenfolgendarstellung der MD5-Digest-Methoden berechnen , ohne eine ganze Datei in den Speicher einzulesen.
Mike Shauneu
24
Ein einfacher Ansatz ohne Bibliotheken von Drittanbietern, die Java 7 verwenden
@edgecaseberg nur für die Hex-Zeichenfolge sehen gut aus, während Sie es auf Konsole
drucken
Ich musste toLowerCase () anstelle von toUpperCase () verwenden.
Pracht
14
Ich musste dies kürzlich nur für eine dynamische Zeichenfolge tun, MessageDigestdie den Hash auf vielfältige Weise darstellen kann. Um die Signatur der Datei zu erhalten, wie Sie sie mit dem Befehl md5sum erhalten würden, musste ich Folgendes tun:
Dies beantwortet offensichtlich nicht Ihre Frage, wie es speziell für eine Datei gemacht werden soll. Die obige Antwort behandelt diese Ruhe gut. Ich habe gerade viel Zeit damit verbracht, die Summe so zu gestalten, dass sie wie die meisten Anwendungen aussieht, und dachte, Sie könnten auf die gleichen Probleme stoßen.
Die Signatur ist der Digest im Hexadezimalformat. Ich fand auch, dass die hexadezimale Darstellung dort funktioniert, wo, wie Sie sagen, andere Darstellungen nicht funktionieren. Vielen Dank für das Aufstellen.
Amit
Das ist gut, .toString(16)wirft aber führende Nullen weg. String.format("%032x", ...)vielleicht besser.
Achten Sie jedoch auf die Verwendung BigInteger.toString()hier, da dadurch führende Nullen abgeschnitten werden ... (Beispiel: Versuchen Sie s = "27", die Prüfsumme sollte sein. "02e74f10e0327ad868d138f2b4fdd6f0")
Ich stimme dem Vorschlag zu, Apache Commons Codec zu verwenden, und habe unseren eigenen Code dadurch ersetzt.
Wow, ich habe mich mit einem Problem befasst, bei dem das MD5-Zeug für alles perfekt funktionierte, außer dass eine Datei nur eine 31-hexadezimale Ausgabe lieferte und die md5-Prüfsummen nicht bestanden haben. Das Abschneiden führender Nullen ist ein großer Schmerz ... Vielen Dank für Ihre Notiz.
Mike
8
publicstaticString MD5Hash(String toHash)throwsRuntimeException{try{returnString.format("%032x",// produces lower case 32 char wide hexa left-padded with 0newBigInteger(1,// handles large POSITIVE numbers MessageDigest.getInstance("MD5").digest(toHash.getBytes())));}catch(NoSuchAlgorithmException e){// do whatever seems relevant}}
Hier ist eine einfache Funktion, die den Code von Sunil umschließt, sodass eine Datei als Parameter verwendet wird. Die Funktion benötigt keine externen Bibliotheken, benötigt jedoch Java 7.
import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import javax.xml.bind.DatatypeConverter;publicclassChecksum{/**
* Generates an MD5 checksum as a String.
* @param file The file that is being checksummed.
* @return Hex string of the checksum value.
* @throws NoSuchAlgorithmException
* @throws IOException
*/publicstaticString generate(File file)throwsNoSuchAlgorithmException,IOException{MessageDigest messageDigest =MessageDigest.getInstance("MD5");
messageDigest.update(Files.readAllBytes(file.toPath()));byte[] hash = messageDigest.digest();returnDatatypeConverter.printHexBinary(hash).toUpperCase();}publicstaticvoid main(String argv[])throwsNoSuchAlgorithmException,IOException{File file =newFile("/Users/foo.bar/Documents/file.jar");String hex =Checksum.generate(file);System.out.printf("hex=%s\n", hex);}}
Google Guava bietet eine neue API. Finden Sie die folgende:
publicstaticHashCode hash(File file,HashFunction hashFunction)throwsIOExceptionComputes the hash code of the file using hashFunction.Parameters:
file - the file to read
hashFunction - the hash function to use to hash the data
Returns:
the HashCode of all of the bytes in the file
Throws:IOException-if an I/O error occurs
Since:12.0
Hier ist eine praktische Variante, die InputStream.transferTo()Java 9 und OutputStream.nullOutputStream()Java 11 verwendet. Sie erfordert keine externen Bibliotheken und muss nicht die gesamte Datei in den Speicher laden.
publicstaticString hashFile(String algorithm,File f)throwsIOException,NoSuchAlgorithmException{MessageDigest md =MessageDigest.getInstance(algorithm);try(BufferedInputStream in =newBufferedInputStream((newFileInputStream(f)));DigestOutputStream out =newDigestOutputStream(OutputStream.nullOutputStream(), md)){
in.transferTo(out);}String fx ="%0"+(md.getDigestLength()*2)+"x";returnString.format(fx,newBigInteger(1, md.digest()));}
Antworten:
Es gibt einen Dekorator für Eingabestreams,
java.security.DigestInputStream
mit dem Sie den Digest berechnen können, während Sie den Eingabestream wie gewohnt verwenden, anstatt einen zusätzlichen Durchlauf über die Daten durchführen zu müssen.quelle
is
alsInputStream
oder oder deklariertFileInputStream
? Klingt wie Sie verwendetFileInputStream
, was diesen Fehler verursachen würde.MethodNotFound
ist keine Ausnahme von Standard-Java; Vielleicht sprechen Sie über einen Compilerfehler? In jedem Fall liegt ein lokales Konfigurationsproblem oder ein Problem mit anderem Code vor, wenn es bei Ihnen nicht funktioniert.Verwenden Sie DigestUtils aus der Apache Commons Codec- Bibliothek:
quelle
commons-codec.jar
bereits auf Ihren Klassenpfad gesetzt?In Real's Java-How-to gibt es ein Beispiel für die Verwendung der MessageDigest- Klasse.
Auf dieser Seite finden Sie auch Beispiele für CRC32 und SHA-1.
quelle
read()
gibt nicht Null zurück und ado/while
ist nicht wirklich angemessen.Die API com.google.common.hash bietet:
Lesen Sie das Benutzerhandbuch ( IO Explained , Hashing Explained ).
Files.hash()
Berechnet für Ihren Anwendungsfall den Digest-Wert für eine Datei und gibt ihn zurück.Zum Beispiel a sha-1 Digest-Berechnung (SHA-1 in MD5 ändern, um MD5-Digest zu erhalten)
Beachten Sie, dass crc32 ist viel schneller als md5, also benutze crc32wenn Sie keine kryptografisch sichere Prüfsumme benötigen. Beachten Sie auch dasmd5 sollte nicht zum Speichern von Passwörtern und dergleichen verwendet werden, da es für die Verwendung von Passwörtern zu einfach ist, Gewalt anzuwenden bcrypt, verschlüsseln oder sha-256 stattdessen.
Für den Langzeitschutz mit Hashes erhöht ein Merkle-Signaturschema die Sicherheit, und die von der Europäischen Kommission geförderte Post Quantum Cryptography Study Group hat die Verwendung dieser Kryptographie zum Langzeitschutz gegen Quantencomputer empfohlen ( Ref ).
Beachten Sie, dass crc32 hat eine höhere Kollisionsrate als die anderen.
quelle
Files.hash()
ist als veraltet markiert, der empfohlene Weg ist:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
ist als veraltet markiert. Die FunktionHashing.sha256()
wird stattdessen empfohlen. QuelleVerwenden von nio2 (Java 7+) und ohne externe Bibliotheken:
So vergleichen Sie das Ergebnis mit einer erwarteten Prüfsumme:
quelle
Guava bietet jetzt eine neue, konsistente Hashing-API, die viel benutzerfreundlicher ist als die verschiedenen im JDK bereitgestellten Hashing-APIs. Siehe Hashing erklärt . Für eine Datei können Sie die MD5-Summe, CRC32 (mit Version 14.0+) oder viele andere Hashes einfach abrufen:
quelle
OK. Ich musste hinzufügen. Einzeilige Implementierung für diejenigen, die bereits von Spring und Apache Commons abhängig sind oder diese hinzufügen möchten:
Nur für und Apache Commons Option (credit @duleshi):
Hoffe das hilft jemandem.
quelle
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
SieDigestUtils.md5Digest(InputStream inputStream)
den MD5-Digest und dieDigestUtils.md5DigestAsHex(InputStream inputStream)
hexadezimale Zeichenfolgendarstellung der MD5-Digest-Methoden berechnen , ohne eine ganze Datei in den Speicher einzulesen.Ein einfacher Ansatz ohne Bibliotheken von Drittanbietern, die Java 7 verwenden
Wenn Sie dieses Byte-Array drucken müssen. Verwenden Sie wie unten
Wenn Sie eine Hex-Zeichenfolge aus diesem Digest benötigen. Verwenden Sie wie unten
Dabei ist DatatypeConverter javax.xml.bind.DatatypeConverter
quelle
toUpperCase
?Ich musste dies kürzlich nur für eine dynamische Zeichenfolge tun,
MessageDigest
die den Hash auf vielfältige Weise darstellen kann. Um die Signatur der Datei zu erhalten, wie Sie sie mit dem Befehl md5sum erhalten würden, musste ich Folgendes tun:Dies beantwortet offensichtlich nicht Ihre Frage, wie es speziell für eine Datei gemacht werden soll. Die obige Antwort behandelt diese Ruhe gut. Ich habe gerade viel Zeit damit verbracht, die Summe so zu gestalten, dass sie wie die meisten Anwendungen aussieht, und dachte, Sie könnten auf die gleichen Probleme stoßen.
quelle
.toString(16)
wirft aber führende Nullen weg.String.format("%032x", ...)
vielleicht besser.Oder Sie erhalten weitere Informationen http://www.asjava.com/core-java/java-md5-example/
quelle
quelle
Wir haben Code verwendet, der dem obigen Code in einem früheren Beitrag ähnelt
Achten Sie jedoch auf die Verwendung
BigInteger.toString()
hier, da dadurch führende Nullen abgeschnitten werden ... (Beispiel: Versuchen Sies = "27"
, die Prüfsumme sollte sein."02e74f10e0327ad868d138f2b4fdd6f0"
)Ich stimme dem Vorschlag zu, Apache Commons Codec zu verwenden, und habe unseren eigenen Code dadurch ersetzt.
quelle
quelle
Sehr schnelle und saubere Java-Methode, die nicht auf externen Bibliotheken basiert:
(Ersetzen Sie MD5 einfach durch SHA-1, SHA-256, SHA-384 oder SHA-512, wenn Sie diese möchten.)
quelle
Eine weitere Implementierung: Schnelle MD5-Implementierung in Java
quelle
MD5.asHex()
in JDK 1.8.0 242 nicht finden.Standard Java Runtime Environment Weg :
Das Ergebnis entspricht dem Dienstprogramm linux md5sum.
quelle
Hier ist eine einfache Funktion, die den Code von Sunil umschließt, sodass eine Datei als Parameter verwendet wird. Die Funktion benötigt keine externen Bibliotheken, benötigt jedoch Java 7.
Beispielausgabe:
quelle
Wenn Sie ANT zum Erstellen verwenden, ist dies kinderleicht. Fügen Sie Ihrer build.xml Folgendes hinzu:
Dabei ist jarFile die JAR, für die Sie MD5 generieren möchten, und toDir ist das Verzeichnis, in dem Sie die MD5-Datei ablegen möchten.
Mehr Infos hier.
quelle
Google Guava bietet eine neue API. Finden Sie die folgende:
quelle
Hier ist eine praktische Variante, die
InputStream.transferTo()
Java 9 undOutputStream.nullOutputStream()
Java 11 verwendet. Sie erfordert keine externen Bibliotheken und muss nicht die gesamte Datei in den Speicher laden.und
kehrt zurück
quelle
quelle