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.
Wie wird es gemacht?
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.
Wie wird es gemacht?
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.
MessageDigest md = MessageDigest.getInstance("MD5");
try (InputStream is = Files.newInputStream(Paths.get("file.txt"));
DigestInputStream dis = new DigestInputStream(is, md))
{
/* Read decorated stream (dis) to EOF as normal... */
}
byte[] digest = md.digest();
is
als InputStream
oder oder deklariert FileInputStream
? Klingt wie Sie verwendet FileInputStream
, 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:
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
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.
import java.io.*;
import java.security.MessageDigest;
public class MD5Checksum {
public static byte[] createChecksum(String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++) {
result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}
public static void main(String args[]) {
try {
System.out.println(getMD5Checksum("apache-tomcat-5.5.17.exe"));
// output :
// 0bb2827c5eacf570b6064e24e0e6653b
// ref :
// http://www.apache.org/dist/
// tomcat/tomcat-5/v5.5.17/bin
// /apache-tomcat-5.5.17.exe.MD5
// 0bb2827c5eacf570b6064e24e0e6653b *apache-tomcat-5.5.17.exe
}
catch (Exception e) {
e.printStackTrace();
}
}
}
read()
gibt nicht Null zurück und a do/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)
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.
Files.hash()
ist als veraltet markiert, der empfohlene Weg ist:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
ist als veraltet markiert. Die Funktion Hashing.sha256()
wird stattdessen empfohlen. Quelle
Verwenden von nio2 (Java 7+) und ohne externe Bibliotheken:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
So vergleichen Sie das Ergebnis mit einer erwarteten Prüfsumme:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
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 directly
long 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:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Nur für und Apache Commons Option (credit @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Hoffe das hilft jemandem.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
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.
Ein einfacher Ansatz ohne Bibliotheken von Drittanbietern, die Java 7 verwenden
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Wenn Sie dieses Byte-Array drucken müssen. Verwenden Sie wie unten
System.out.println(Arrays.toString(digest));
Wenn Sie eine Hex-Zeichenfolge aus diesem Digest benötigen. Verwenden Sie wie unten
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
Dabei ist DatatypeConverter javax.xml.bind.DatatypeConverter
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:
try {
String s = "TEST STRING";
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(s.getBytes(),0,s.length());
String signature = new BigInteger(1,md5.digest()).toString(16);
System.out.println("Signature: "+signature);
} catch (final NoSuchAlgorithmException e) {
e.printStackTrace();
}
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.
.toString(16)
wirft aber führende Nullen weg. String.format("%032x", ...)
vielleicht besser.
public static void main(String[] args) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream("c:\\apache\\cxf.jar");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
}
Oder Sie erhalten weitere Informationen http://www.asjava.com/core-java/java-md5-example/
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Wir haben Code verwendet, der dem obigen Code in einem früheren Beitrag ähnelt
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
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.
public static String MD5Hash(String toHash) throws RuntimeException {
try{
return String.format("%032x", // produces lower case 32 char wide hexa left-padded with 0
new BigInteger(1, // handles large POSITIVE numbers
MessageDigest.getInstance("MD5").digest(toHash.getBytes())));
}
catch (NoSuchAlgorithmException e) {
// do whatever seems relevant
}
}
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.)
public String calcMD5() throws Exception{
byte[] buffer = new byte[8192];
MessageDigest md = MessageDigest.getInstance("MD5");
DigestInputStream dis = new DigestInputStream(new FileInputStream(new File("Path to file")), md);
try {
while (dis.read(buffer) != -1);
}finally{
dis.close();
}
byte[] bytes = md.digest();
// bytesToHex-method
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
Eine weitere Implementierung: Schnelle MD5-Implementierung in Java
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
in JDK 1.8.0 242 nicht finden.
Standard Java Runtime Environment Weg :
public String checksum(File file) {
try {
InputStream fin = new FileInputStream(file);
java.security.MessageDigest md5er =
MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int read;
do {
read = fin.read(buffer);
if (read > 0)
md5er.update(buffer, 0, read);
} while (read != -1);
fin.close();
byte[] digest = md5er.digest();
if (digest == null)
return null;
String strDigest = "0x";
for (int i = 0; i < digest.length; i++) {
strDigest += Integer.toString((digest[i] & 0xff)
+ 0x100, 16).substring(1).toUpperCase();
}
return strDigest;
} catch (Exception e) {
return null;
}
}
Das Ergebnis entspricht dem Dienstprogramm linux md5sum.
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;
public class Checksum {
/**
* 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
*/
public static String generate(File file) throws NoSuchAlgorithmException,IOException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(Files.readAllBytes(file.toPath()));
byte[] hash = messageDigest.digest();
return DatatypeConverter.printHexBinary(hash).toUpperCase();
}
public static void main(String argv[]) throws NoSuchAlgorithmException, IOException {
File file = new File("/Users/foo.bar/Documents/file.jar");
String hex = Checksum.generate(file);
System.out.printf("hex=%s\n", hex);
}
}
Beispielausgabe:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Wenn Sie ANT zum Erstellen verwenden, ist dies kinderleicht. Fügen Sie Ihrer build.xml Folgendes hinzu:
<checksum file="${jarFile}" todir="${toDir}"/>
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.
Google Guava bietet eine neue API. Finden Sie die folgende:
public static HashCode hash(File file,
HashFunction hashFunction)
throws IOException
Computes 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.
public static String hashFile(String algorithm, File f) throws IOException, NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(algorithm);
try(BufferedInputStream in = new BufferedInputStream((new FileInputStream(f)));
DigestOutputStream out = new DigestOutputStream(OutputStream.nullOutputStream(), md)) {
in.transferTo(out);
}
String fx = "%0" + (md.getDigestLength()*2) + "x";
return String.format(fx, new BigInteger(1, md.digest()));
}
und
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
kehrt zurück
"e30fa2784ba15be37833d569280e2163c6f106506dfb9b07dde67a24bfb90da65c661110cf2c5c6f71185754ee5ae3fd83a5465c92f72abd888b03187229da29"
public static String getMd5OfFile(String filePath)
{
String returnVal = "";
try
{
InputStream input = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
MessageDigest md5Hash = MessageDigest.getInstance("MD5");
int numRead = 0;
while (numRead != -1)
{
numRead = input.read(buffer);
if (numRead > 0)
{
md5Hash.update(buffer, 0, numRead);
}
}
input.close();
byte [] md5Bytes = md5Hash.digest();
for (int i=0; i < md5Bytes.length; i++)
{
returnVal += Integer.toString( ( md5Bytes[i] & 0xff ) + 0x100, 16).substring( 1 );
}
}
catch(Throwable t) {t.printStackTrace();}
return returnVal.toUpperCase();
}