Я хочу використовувати 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();
is
як InputStream
або як FileInputStream
? Звучить так, як ви раніше FileInputStream
, що може спричинити цю помилку.
MethodNotFound
Не є винятком зі стандартної Java; можливо, ви говорите про помилку компілятора? У будь-якому випадку, якщо це не працює для вас, це локальна проблема конфігурації або проблема з іншим кодом.
Використовуйте DigestUtils з бібліотеки кодеків Apache Commons :
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
на свій класний шлях ?
На прикладі Java-How-to для Real із класу 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();
}
}
}
read()
не поверне нуль, і do/while
справді не підходить.
У com.google.common.hash API пропонує:
Прочитайте Керівництво користувача ( IO Роз'яснення , хешування Роз'яснення ).
Для ваших випадків використання Files.hash()
обчислює і повертає дайджест значення для файлу.
Наприклад a ша-1 підрахунок дайджесту (змініть SHA-1 на MD5, щоб отримати дайджест MD5)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Зауважте, що crc32 набагато швидше, ніж md5, тому використовуйте crc32якщо вам не потрібна криптографічно захищена контрольна сума. Зауважте також, щоmd5 не слід використовувати для зберігання паролів тощо, оскільки це легко піддавати грубій силі для використання паролів криптовалюта, скрипт або ша-256 замість цього.
Для довготривалого захисту хешами схема підпису Меркле додає безпеку, а група досліджень квантової криптографії, спонсорована Європейською Комісією, рекомендує використовувати цю криптографію для довгострокового захисту від квантових комп'ютерів ( посилання ).
Зауважте, що crc32 має більш високу швидкість зіткнення, ніж інші.
Files.hash()
Позначений як застарілий, рекомендованим способом є:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
відзначається застарілим. Функція Hashing.sha256()
рекомендується замість цього. джерело
Використання 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. Див. Роз'яснення хешингу . Для файлу ви можете легко отримати суму 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's padded with 0s for 32-bit CRC
// this is the value you would get if using that API directly
long checksumResult = crc32.padToLong();
Добре. Довелося додати. Реалізація одного рядка для тих, хто вже має залежність від Spring та Apache Commons або планує її додати:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Для і лише Apache доступний варіант (кредит @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Сподіваюся, що це комусь допоможе.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
вас DigestUtils.md5Digest(InputStream inputStream)
слід обчислити дайджест MD5 і DigestUtils.md5DigestAsHex(InputStream inputStream)
для шістнадцяткового представлення рядків методів перебору MD5 без зчитування цілого файлу в пам'яті.
Простий підхід без використання сторонніх бібліотек, що використовують 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
toUpperCase
?
Нещодавно мені довелося це зробити лише для динамічної струни, 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 checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Ми використовували код, який нагадує код вище в попередній публікації
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Однак слідкуйте за використанням BigInteger.toString()
тут, оскільки це вріже провідні нулі ... (наприклад, спробуйте s = "27"
, контрольна сума повинна бути "02e74f10e0327ad868d138f2b4fdd6f0"
)
Я вдруге пропоную використовувати кодек Apache Commons, я замінив власний код цим.
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
}
}
Дуже швидкий і чистий 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);
}
Інша реалізація: Швидка реалізація MD5 на Java
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
у JDK 1.8.0 242.
Стандартний спосіб середовища виконання Java :
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.
Ось проста функція, яка обертається навколо коду Sunil, щоб він взяв файл як параметр. Функція не потребує жодних зовнішніх бібліотек, але для цього потрібна 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
Ось зручна версія, яка використовує як 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"
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();
}