Obtenir la sum de contrôle MD5 d’un fichier en Java

Je cherche à utiliser Java pour obtenir la sum de contrôle MD5 d’un fichier. J’ai été très surpris, mais je n’ai rien trouvé qui montre comment obtenir la sum de contrôle MD5 d’un fichier.

Comment est-il fait?

Il existe un décorateur de stream d’entrée, java.security.DigestInputStream , de sorte que vous pouvez calculer le résumé en utilisant le stream d’entrée comme vous le feriez normalement, au lieu d’avoir à effectuer un passage supplémentaire sur les données.

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

Utilisez DigestUtils de la bibliothèque Apache Commons Codec :

 FileInputStream fis = new FileInputStream(new File("foo")); Ssortingng md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(fis); fis.close(); 

Il y a un exemple au Java-How-to de Real utilisant la classe MessageDigest .

Consultez également cette page pour des exemples d’utilisation de CRC32 et SHA-1.

 import java.io.*; import java.security.MessageDigest; public class MD5Checksum { public static byte[] createChecksum(Ssortingng 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 ssortingng public static Ssortingng getMD5Checksum(Ssortingng filename) throws Exception { byte[] b = createChecksum(filename); Ssortingng 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(); } } } 

L’API com.google.common.hash propose:

  • Une API unifiée et conviviale pour toutes les fonctions de hachage
  • Implémentations 32 et 128 bits de murmur3
  • Les adaptateurs md5 (), sha1 (), sha256 (), sha512 () modifient une seule ligne de code pour basculer entre ceux-ci et murmur.
  • goodFastHash (int bits), quand vous ne vous souciez pas de quel algorithme vous utilisez
  • Utilitaires généraux pour les instances HashCode, comme combineOrdered / combineUnordered

Lisez le guide de l’utilisateur ( IO Explained , Hashing Explained ).

Pour votre cas d’utilisation, Files.hash() calcule et renvoie la valeur de résumé pour un fichier.

Par exemple, un calcul de résumé sha-1 (changez SHA-1 en MD5 pour obtenir le résumé MD5)

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

Notez que crc32 est beaucoup plus rapide que md5 , utilisez donc crc32 si vous n’avez pas besoin d’une sum de contrôle sécurisée par cryptographie. Notez également que md5 ne doit pas être utilisé pour stocker des mots de passe, car il est facile de forcer, car les mots de passe utilisent plutôt bcrypt , scrypt ou sha-256 .

Pour la protection à long terme avec hachage, un schéma de signature Merkle ajoute à la sécurité et le groupe d’étude sur la cryptographie post-quantique sponsorisé par la Commission européenne a recommandé l’utilisation de cette cryptographie pour la protection à long terme contre les ordinateurs quantiques ( réf .).

Notez que crc32 a un taux de collision plus élevé que les autres.

Utiliser nio2 (Java 7+) et aucune bibliothèque externe:

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

Pour comparer le résultat avec une sum de contrôle attendue:

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

Guava fournit désormais une nouvelle API de hachage cohérente, beaucoup plus conviviale que les différentes API de hachage fournies dans le JDK. Voir Hashing Explained . Pour un fichier, vous pouvez obtenir la sum MD5, CRC32 (avec la version 14.0+) ou de nombreux autres hachages facilement:

 HashCode md5 = Files.hash(file, Hashing.md5()); byte[] md5Bytes = md5.asBytes(); Ssortingng md5Hex = md5.toSsortingng(); 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(); 

D’accord. Je devais append Implémentation en une ligne pour ceux qui ont déjà une dépendance à Spring et à Apache Commons ou qui prévoient de l’append:

 DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file)) 

Pour l’option Apache commons uniquement (crédit @duleshi):

 DigestUtils.md5Hex(FileUtils.readFileToByteArray(file)) 

J’espère que cela aide quelqu’un.

Une approche simple sans bibliothèques tierces utilisant Java 7

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

Si vous avez besoin d’imprimer ce tableau d’octets. Utilisez comme ci-dessous

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

Si vous avez besoin de la chaîne hexadécimale de ce résumé. Utilisez comme ci-dessous

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

où DatatypeConverter est javax.xml.bind.DatatypeConverter

J’ai récemment dû le faire pour une chaîne dynamic, MessageDigest peut représenter le hachage de nombreuses manières. Pour obtenir la signature du fichier comme avec la commande md5sum, je devais faire quelque chose comme ceci:

 try { Ssortingng s = "TEST STRING"; MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(s.getBytes(),0,s.length()); Ssortingng signature = new BigInteger(1,md5.digest()).toSsortingng(16); System.out.println("Signature: "+signature); } catch (final NoSuchAlgorithmException e) { e.printStackTrace(); } 

Cela ne répond évidemment pas à votre question sur la façon de le faire spécifiquement pour un fichier, la réponse ci-dessus traite de ce calme gentiment. Je viens de passer beaucoup de temps à faire en sorte que la sum ressemble à celle de la plupart des applications, et j’ai pensé que vous pourriez rencontrer le même problème.

 public static void main(Ssortingng[] 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(); SsortingngBuffer sb = new SsortingngBuffer(); 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()); } 

Ou vous pouvez obtenir plus d'informations http://www.asjava.com/core-java/java-md5-example/

Nous utilisions le code qui ressemble au code ci-dessus dans un post précédent en utilisant

 ... Ssortingng signature = new BigInteger(1,md5.digest()).toSsortingng(16); ... 

Cependant, BigInteger.toSsortingng() attention à utiliser BigInteger.toSsortingng() ici, car il va tronquer les zéros en tête … (pour un exemple, essayez s = "27" , la sum de contrôle devrait être "02e74f10e0327ad868d138f2b4fdd6f0" )

J’appuie la suggestion d’utiliser Apache Commons Codec, j’ai remplacé notre propre code par celui-là.

 public static Ssortingng MD5Hash(Ssortingng toHash) throws RuntimeException { try{ return Ssortingng.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 } } 

Méthode Java très rapide et propre qui ne repose pas sur des bibliothèques externes:

(Remplacez simplement MD5 par SHA-1, SHA-256, SHA-384 ou SHA-512 si vous le souhaitez)

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

Autre implémentation: Implémentation rapide de MD5 en Java

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

Standard Java Runtime Environment :

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

Le résultat est égal à l'utilitaire linux md5sum.

 Ssortingng checksum = DigestUtils.md5Hex(new FileInputStream(filePath)); 

Voici une fonction simple qui entoure le code de Sunil pour qu’il prenne un fichier comme paramètre. La fonction ne nécessite aucune bibliothèque externe, mais nécessite 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 Ssortingng. * @param file The file that is being checksummed. * @return Hex ssortingng of the checksum value. * @throws NoSuchAlgorithmException * @throws IOException */ public static Ssortingng 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(Ssortingng argv[]) throws NoSuchAlgorithmException, IOException { File file = new File("/Users/foo.bar/Documents/file.jar"); Ssortingng hex = Checksum.generate(file); System.out.printf("hex=%s\n", hex); } } 

Exemple de sortie:

 hex=B117DD0C3CBBD009AC4EF65B6D75C97B 

Si vous utilisez ANT pour construire, c’est simple. Ajoutez ce qui suit à votre build.xml:

  

Où jarFile est le JAR contre lequel vous voulez générer le MD5, et toDir est le répertoire dans lequel vous voulez placer le fichier MD5.

Plus d’infos ici.

Google Guava fournit une nouvelle API. Trouvez celui ci-dessous:

 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 Ssortingng getMd5OfFile(Ssortingng filePath) { Ssortingng 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(); }