Domanda

Sto cercando di usare Java per ottenere il checksum MD5 di un file. Sono stato davvero sorpreso, ma non sono stato in grado di trovare nulla che mostri come ottenere il checksum MD5 di un file.

Come è fatto?

È stato utile?

Soluzione

Esiste un decoratore di flussi di input, java.security.DigestInputStream , in modo che tu possa calcolare il digest mentre usi il flusso di input come faresti normalmente, invece di dover fare un passaggio extra sui dati .

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();

Altri suggerimenti

Usa DigestUtils dalla libreria Apache Commons Codec :

try (InputStream is = Files.newInputStream(Paths.get("file.txt"))) {
    String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}

C'è un esempio in Java-How-to reale usando il MessageDigest class.

Controlla quella pagina per esempi usando anche CRC32 e 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();
       }
   }
}

La com .google.common.hash Offerte API:

  • Un'API unificata di facile utilizzo per tutte le funzioni hash
  • Implementazioni a 32 e 128 bit con seeding di murmur3
  • adattatori md5 (), sha1 (), sha256 (), sha512 (), cambia solo una riga di codice per passare da una all'altra e mormora.
  • goodFastHash (int bit), per quando non ti interessa quale algoritmo usi
  • Utilità generali per istanze di HashCode, come combinare / Ordinato / CombinareUnordinato

Leggi la Guida per l'utente ( Spiegazione IO , Hashing Explained ).

Per il tuo caso d'uso Files.hash () calcola e restituisce il valore digest per un file.

Ad esempio una calcolo digest (modifica SHA-1 in MD5 per ottenere digest MD5)

HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();

Nota che è molto più veloce di < a class = "post-tag" href = "/ questions / tagged / md5" title = "mostra le domande taggate 'md5'" rel = "tag"> md5 , quindi usa se non hai bisogno di un checksum crittograficamente sicuro. Si noti inoltre che non devono essere utilizzate per memorizzare le password e simili poiché è facile forzare la forza, poiché le password usano , o

Per la protezione a lungo termine con gli hash, Schema di firma Merkle aggiunge sicurezza e The Post Quantum Il gruppo di studio sulla crittografia sponsorizzato dalla Commissione europea ha raccomandato l'uso di questa crittografia per la protezione a lungo termine contro i computer quantistici ( ref ).

Nota che ha un tasso di collisione più elevato rispetto agli altri.

Uso di nio2 (Java 7+) e nessuna libreria esterna:

byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);

Per confrontare il risultato con un checksum previsto:

String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");

Guava ora fornisce una nuova e coerente API di hash che è molto più user-friendly rispetto ai vari hash API fornite nel JDK. Vedi Hashing Explained . Per un file, puoi ottenere facilmente la somma MD5, CRC32 (con la versione 14.0+) o molti altri hash:

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. Ho dovuto aggiungere. Una linea di implementazione per coloro che hanno già la dipendenza da Spring e Apache Commons o hanno intenzione di aggiungerlo:

DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))

Solo opzione per i beni comuni di Apache (credit @duleshi):

DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))

Spero che questo aiuti qualcuno.

Un approccio semplice senza librerie di terze parti che utilizzano Java 7

String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();

Se è necessario stampare questo array di byte. Utilizzare come di seguito

System.out.println(Arrays.toString(digest));

Se hai bisogno di una stringa esadecimale per questo digest. Utilizzare come di seguito

String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);

dove DatatypeConverter è javax.xml.bind.DatatypeConverter

Di recente ho dovuto farlo solo per una stringa dinamica, MessageDigest può rappresentare l'hash in numerosi modi. Per ottenere la firma del file come faresti con md5sum comando dovevo fare qualcosa del genere:

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();
}

Questo ovviamente non risponde alla tua domanda su come farlo specificatamente per un file, la risposta di cui sopra si occupa bene di ciò. Ho appena trascorso molto tempo a fare in modo che la somma assomigliasse alla maggior parte delle applicazioni, e ho pensato che potresti avere lo stesso problema.

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());
}

Oppure potresti ottenere maggiori informazioni http://www.asjava.com/core-java/java-md5-example/

Usavamo il codice che ricorda il codice sopra in un post precedente usando

...
String signature = new BigInteger(1,md5.digest()).toString(16);
...

Tuttavia, fai attenzione a utilizzare BigInteger.toString () qui, poiché troncerà gli zeri iniziali ... (ad esempio, prova s = " 27 " , il checksum dovrebbe essere " 02e74f10e0327ad868d138f2b4fdd6f0 " )

Secondo il suggerimento di utilizzare Apache Commons Codec, ho sostituito il nostro codice con quello.

Molto veloce & amp; metodo Java pulito che non si basa su librerie esterne:

(Sostituisci semplicemente MD5 con SHA-1, SHA-256, SHA-384 o SHA-512 se vuoi quelli)

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);
}
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
   }
}
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));

Un'altra implementazione: Implementazione veloce di MD5 in Java

String hash = MD5.asHex(MD5.getHash(new File(filename)));

Modo Java Runtime Environment standard :

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;
  }
}

Il risultato è uguale all'utility linux md5sum.

Ecco una semplice funzione che avvolge il codice di Sunil in modo che prenda un file come parametro. La funzione non richiede librerie esterne, ma richiede 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);            
    }


}

Esempio di output:

hex=B117DD0C3CBBD009AC4EF65B6D75C97B

Se stai usando ANT per costruire, questo è semplicissimo. Aggiungi quanto segue a build.xml:

<checksum file="${jarFile}" todir="${toDir}"/>

Dove jarFile è il JAR su cui si desidera generare MD5 e toDir è la directory in cui si desidera posizionare il file MD5.

Maggiori informazioni qui.

Google guava fornisce una nuova API. Trova quello qui sotto:

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
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();
}

Ecco una pratica variante che utilizza InputStream.transferTo () da Java 9 e OutputStream.nullOutputStream () da Java 11. Non richiede librerie esterne e non è necessario caricare l'intero file in memoria.

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()));
}

e

hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());

ritorna

"e30fa2784ba15be37833d569280e2163c6f106506dfb9b07dde67a24bfb90da65c661110cf2c5c6f71185754ee5ae3fd83a5465c92f72abd888b03187229da29"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top