Estoy buscando utilizar Java para obtener la suma de comprobación MD5 de un archivo. Me sorprendió mucho, pero no he podido encontrar nada que muestre cómo obtener la suma de comprobación MD5 de un archivo.
Como se hace
Estoy buscando utilizar Java para obtener la suma de comprobación MD5 de un archivo. Me sorprendió mucho, pero no he podido encontrar nada que muestre cómo obtener la suma de comprobación MD5 de un archivo.
Como se hace
Respuestas:
Hay un decorador de flujo de entrada java.security.DigestInputStream
, para que pueda calcular el resumen mientras usa el flujo de entrada como lo haría normalmente, en lugar de tener que hacer un pase adicional sobre los datos.
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
como un InputStream
o un FileInputStream
? Suena como lo usaste FileInputStream
, lo que causaría este error.
MethodNotFound
no es una excepción de Java estándar; tal vez estás hablando de un error del compilador? En cualquier caso, si no funciona para usted, es un problema de configuración local o un problema con otro código.
Utilice DigestUtils de la biblioteca de códecs de Apache Commons :
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
en tu classpath ya?
Hay un ejemplo en Real-Java-How-to usando el MessageDigest clase .
Consulte esa página para ver ejemplos de uso de CRC32 y SHA-1 también.
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()
no devolverá cero, y a do/while
no es realmente apropiado.
La API com.google.common.hash ofrece:
Lea la Guía del usuario ( IO explicado , Hash explicado ).
Para su caso de uso Files.hash()
calcula y devuelve el valor de resumen para un archivo.
Por ejemplo un sha-1 Cálculo del resumen (cambie SHA-1 a MD5 para obtener el resumen MD5)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Tenga en cuenta que crc32 es mucho más rápido que md5, entonces usa crc32si no necesita una suma de verificación criptográficamente segura. Tenga en cuenta también quemd5 no debe usarse para almacenar contraseñas y similares, ya que es fácil de aplicar fuerza bruta, para el uso de contraseñas brypt, scrypt o sha-256 en lugar.
Para la protección a largo plazo con hashes, un esquema de firma Merkle se suma a la seguridad y el Grupo de Estudio de Criptografía Post Quantum patrocinado por la Comisión Europea ha recomendado el uso de esta criptografía para la protección a largo plazo contra las computadoras cuánticas ( ref ).
Tenga en cuenta que crc32 tiene una tasa de colisión más alta que las demás.
Files.hash()
está marcado como obsoleto, la forma recomendada es:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
está marcado como obsoleto. La función Hashing.sha256()
se recomienda en su lugar. fuente
Usando nio2 (Java 7+) y sin bibliotecas externas:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
Para comparar el resultado con una suma de verificación esperada:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava ahora proporciona una nueva API de hashing coherente que es mucho más fácil de usar que las diversas API de hashing proporcionadas en el JDK. Ver Hashing explicado . Para un archivo, puede obtener fácilmente la suma MD5, CRC32 (con la versión 14.0+) o muchos otros hashes:
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();
Okay. Tuve que agregar. Implementación de una línea para aquellos que ya tienen dependencia de Spring y Apache Commons o planean agregarla:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Opción para los comunes comunes de Apache (crédito @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Espero que esto ayude a alguien.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
, DigestUtils.md5Digest(InputStream inputStream)
debe calcular el resumen MD5 y la DigestUtils.md5DigestAsHex(InputStream inputStream)
representación de cadena hexadecimal de los métodos de resumen MD5 sin leer un archivo completo en la memoria.
Un enfoque simple sin bibliotecas de terceros que utilizan Java 7
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Si necesita imprimir esta matriz de bytes. Use como a continuación
System.out.println(Arrays.toString(digest));
Si necesita una cadena hexadecimal fuera de este resumen. Use como a continuación
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
donde DatatypeConverter es javax.xml.bind.DatatypeConverter
toUpperCase
?
Recientemente tuve que hacer esto solo para una cadena dinámica, MessageDigest
puede representar el hash de numerosas maneras. Para obtener la firma del archivo como lo haría con el comando md5sum , tuve que hacer algo como esto:
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();
}
Obviamente, esto no responde a su pregunta sobre cómo hacerlo específicamente para un archivo, la respuesta anterior se ocupa muy bien de eso. Acabo de pasar mucho tiempo haciendo que la suma se vea como la mayoría de las aplicaciones lo muestran, y pensé que podría tener el mismo problema.
.toString(16)
arrojará ceros a la izquierda. String.format("%032x", ...)
quizás mejor.
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());
}
O puede obtener más información http://www.asjava.com/core-java/java-md5-example/
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Estábamos usando un código que se parece al código anterior en una publicación anterior usando
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Sin embargo, BigInteger.toString()
tenga cuidado al usar aquí, ya que truncará los ceros a la izquierda ... (por ejemplo, intente s = "27"
, la suma de verificación debería ser "02e74f10e0327ad868d138f2b4fdd6f0"
)
Secundo la sugerencia de usar Apache Commons Codec, reemplacé nuestro propio código con eso.
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
}
}
Método Java muy rápido y limpio que no se basa en bibliotecas externas:
(Simplemente reemplace MD5 con SHA-1, SHA-256, SHA-384 o SHA-512 si lo desea)
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);
}
Otra implementación: Implementación rápida de MD5 en Java
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
en JDK 1.8.0 242.
Forma estándar de Java Runtime Environment :
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;
}
}
El resultado es igual a la utilidad linux md5sum.
Aquí hay una función simple que envuelve el código de Sunil para que tome un archivo como parámetro. La función no necesita ninguna biblioteca externa, pero sí requiere 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);
}
}
Salida de ejemplo:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Si está utilizando ANT para construir, esto es muy simple. Agregue lo siguiente a su build.xml:
<checksum file="${jarFile}" todir="${toDir}"/>
Donde jarFile es el JAR en el que desea generar el MD5 y toDir es el directorio donde desea colocar el archivo MD5.
Google guava ofrece una nueva API. Encuentra el siguiente:
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
Aquí hay una variación práctica que utiliza InputStream.transferTo()
Java 9 y OutputStream.nullOutputStream()
Java 11. No requiere bibliotecas externas y no necesita cargar todo el archivo en la 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()));
}
y
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
devoluciones
"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();
}