Я хочу использовать Java для получения контрольной суммы MD5 файла. Я был очень удивлен, но я не смог найти ничего, что показывает, как получить контрольную сумму MD5 файла.
Как это сделать?
Я хочу использовать Java для получения контрольной суммы MD5 файла. Я был очень удивлен, но я не смог найти ничего, что показывает, как получить контрольную сумму MD5 файла.
Как это сделать?
Там есть декоратор потока ввода, java.security.DigestInputStream
, так что вы можете вычислить дайджест при использовании входного потока, как обычно, вместо того, чтобы делать дополнительный проход по данным.
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();
Используйте DigestUtils из библиотеки кодеков Apache Commons:
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
Вот пример в Real Java-How-to с использованием класса MessageDigest.
Проверьте эту страницу на примерах, используя CRC32 и 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();
}
}
}
API com.google.common.hash предлагает:
Прочтите Руководство пользователя (Разъяснение ввода-вывода, Hashing Explained).
Для вашего прецедента Files.hash()
вычисляет и возвращает значение дайджеста для файла.
Например, расчет дайджеста sha-1 (изменение SHA-1 на MD5 для получения дайджест MD5)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Обратите внимание, что crc32 намного быстрее, чем md5, поэтому используйте crc32, если вам не нужна криптографически безопасная контрольная сумма. Также обратите внимание на то, что md5 не следует использовать для хранения паролей и т.п., Поскольку это просто для принудительной перебора, для паролей вместо этого используются bcrypt, scrypt или sha-256.
Для долгосрочной защиты с помощью хэшей схема подписи Merkle добавляет безопасность, а Исследовательская группа Post Quantum Cryptography, спонсируемая Европейской комиссией, рекомендовала использовать эту криптографию для долгосрочной защиты от квантовых компьютеров (ref).
Обратите внимание, что crc32 имеет более высокую скорость столкновения, чем другие.
Использование nio2 (Java 7+) и внешних библиотек:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
Чтобы сравнить результат с ожидаемой контрольной суммой:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava теперь предоставляет новый, последовательный хэширующий API, который намного удобнее, чем различные хеширующие API, предоставленные в JDK. См. Hashing Explained. Для файла вы можете легко получить сумму MD5, CRC32 (с версией 14.0+) или многие другие хэши:
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 padded with 0s for 32-bit CRC
// this is the value you would get if using that API directly
long checksumResult = crc32.padToLong();
Ok. Я должен был добавить. Реализация одной строки для тех, у кого уже есть зависимость Spring и Apache Commons или планируется добавить ее:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Только для и Apache - только опция (credit @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Надеюсь, это поможет кому-то.
Простой подход без сторонних библиотек с использованием Java 7
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Если вам нужно напечатать этот массив байтов. Используйте как ниже
System.out.println(Arrays.toString(digest));
Если вам нужна шестнадцатеричная строка из этого дайджеста. Используйте как ниже
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
где DatatypeConverter - javax.xml.bind.DatatypeConverter
Я недавно должен был сделать это только для динамической строки, MessageDigest
может представлять хеш различными способами. Чтобы получить подпись файла, как вы могли бы получить с помощью команды md5sum, мне пришлось сделать что-то вроде это:
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();
}
Это, очевидно, не отвечает на ваш вопрос о том, как сделать это специально для файла, вышеупомянутый ответ имеет дело с этим тихим приятным образом. Я просто потратил много времени на то, чтобы получить сумму, чтобы она выглядела так, как показано на большинстве приложений, и подумала, что вы столкнулись с такой же проблемой.
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());
}
Или вы можете получить больше информации http://www.asjava.com/core-java/java-md5-example/
Мы использовали код, похожий на код выше в предыдущем сообщении, используя
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Однако не забудьте использовать BigInteger.toString()
здесь, так как он обрезает ведущие нули...
(например, попробуйте s = "27"
, контрольная сумма должна быть "02e74f10e0327ad868d138f2b4fdd6f0"
)
Во-вторых, предложение использовать Apache Commons Codec, я заменил наш собственный код тем.
Очень быстрый и чистый Java-метод, который не полагается на внешние библиотеки:
(Просто замените MD5 на SHA-1, SHA-256, SHA-384 или SHA-512, если вы этого хотите)
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));
Другая реализация: быстрая реализация MD5 в Java
String hash = MD5.asHex(MD5.getHash(new File(filename)));
Стандартная среда 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;
}
}
Результат равен утилите linux md5sum.
Вот простая функция, которая обертывает код суннита так, что он принимает файл как параметр. Функция не нуждается в каких-либо внешних библиотеках, но для нее требуется 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);
}
}
Пример вывода:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Если вы используете ANT для сборки, это просто невозможно. Добавьте в свой файл build.xml следующее:
<checksum file="${jarFile}" todir="${toDir}"/>
Где jarFile - JAR, вы хотите сгенерировать MD5, а toDir - это каталог, в который вы хотите поместить файл MD5.
Google guava предоставляет новый API. Найдите ниже:
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();
}
Вот удобный вариант, который использует InputStream.transferTo()
из Java 9 и OutputStream.nullOutputStream()
из Java 11. Он не требует внешних библиотек и не требует загрузки всего файла в память.
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()));
}
а также
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
возвращается
"e30fa2784ba15be37833d569280e2163c6f106506dfb9b07dde67a24bfb90da65c661110cf2c5c6f71185754ee5ae3fd83a5465c92f72abd888b03187229da29"