Я ищу использовать Java для получения контрольной суммы MD5 файла. Я был действительно удивлен, но я не смог найти ничего, что показывает, как получить контрольную сумму MD5 файла.
Может быть, это поможет. Вы также можете посмотреть спецификации, но это займет больше времени, потому что это сложно.
Уэйнколвин
4
Имейте в виду, что согласно недавнему исследованию «MD5 следует считать криптографически взломанным и непригодным для дальнейшего использования». en.wikipedia.org/wiki/MD5
Захария Стэнли
80
MD5 больше не считается криптографически безопасным, но его все же достаточно для проверки согласованности файлов и он быстрее, чем SHA.
Джигги
2
@ZakhariaStanley Это вопрос о контрольной сумме.
iPherian
Каноническое использование контрольных сумм MD5 для файлов состоит в том, чтобы избежать враждебных замен распределенных файлов. Вот где это небезопасно. Но в сценарии, где враждебные подвиги не являются проблемой, это идеально подходит.
Кит Тайлер
Ответы:
541
Есть декоратор входного потока java.security.DigestInputStream, так что вы можете вычислить дайджест, используя входной поток, как обычно, вместо того, чтобы делать дополнительный проход по данным.
MessageDigest md =MessageDigest.getInstance("MD5");try(InputStream is =Files.newInputStream(Paths.get("file.txt"));DigestInputStream dis =newDigestInputStream(is, md)){/* Read decorated stream (dis) to EOF as normal... */}byte[] digest = md.digest();
Я согласен, очень элегантный способ вычислить контрольную сумму на лету, если вы уже что-то делаете с байтами (то есть считываете их с HTTP-соединения).
Марк Новаковски
2
@AlPhaba Вы объявили isкак InputStreamили FileInputStream? Похоже, вы использовали FileInputStream, что приведет к этой ошибке.
Эриксон
1
@barwnikk Отлично работает в Java 8. MethodNotFoundНе является исключением из стандартной Java; возможно вы говорите об ошибке компилятора? В любом случае, если это не работает для вас, это проблема локальной конфигурации или проблема с другим кодом.
Эриксон
4
@barwnikk Опять же, это ваша локальная проблема конфигурации. Это действительный код Java 7 и Java 8. Если вы застряли с инструментами с 2006 года, вам придется адаптироваться.
Эриксон
5
@erickson Вы не обновляете объект MessageDigest содержимым файла. Рт? Этот код будет печатать всегда один и тот же дайджест.
У меня не работает в моем коде Android я получаю эту ошибку ... java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString at org.apache.commons.codec.digest.DigestUtils.md5Hex (DigestUtils.java:215)
JPM
@JPM Предположим, что вы уже загрузили и поместили в commons-codec.jarсвой путь к классам?
Лейф Грюнволдт
да, и я экспортировал в свой проект Android .. Я могу пройти через код и класс есть в исходных файлах ... странно, должно быть, некоторые проблемы Android Eclipse.
JPM
1
У меня была та же проблема, но она была исправлена этим кодом `FileInputStream fis = new FileInputStream (new File (filePath)); байтовые данные [] = org.apache.commons.codec.digest.DigestUtils.md5 (fis); char md5Chars [] = Hex.encodeHex (data); String md5 = String.valueOf (md5Chars); `
Dmitry_L
1
Ницца! Для новых проектов я всегда думаю дважды перед добавлением новой зависимости, но для существующего проекта мне просто нужно проверить, есть ли библиотека, чтобы использовать ее. +1
Для вашего 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 повышает безопасность, а Исследовательская группа по постквантовой криптографии, спонсируемая Европейской комиссией, рекомендовала использовать эту криптографию для долговременной защиты от квантовых компьютеров ( см. ).
Обратите внимание, что crc32 имеет более высокий уровень столкновений, чем другие.
@ Араш, да, конечно, спасибо. Я перепутал класс JDK Files и Guava.
assylias
Мне нравится это решение больше, чем решение erickson, так как оно может быть обернуто с помощью Optionals для использования чисто функционального программирования
Габриэль Эрнандес,
2
Для большого файла это будет использовать много памяти, так как весь файл читается и затем подается в дайджест вместо чтения кусков и «переваривания» их во время чтения.
Берни
39
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 directlylong checksumResult = crc32.padToLong();
Лучше решение, основанное на общедоступных файлах David Onter, поскольку оно не считывает весь файл в память.
Фран Марсоа
По крайней мере, Spring 5 вам нужно DigestUtils.md5Digest(InputStream inputStream)рассчитать дайджест MD5 и DigestUtils.md5DigestAsHex(InputStream inputStream)шестнадцатеричное строковое представление методов дайджеста MD5 без чтения всего файла в память.
Майк Шонё,
24
Простой подход без сторонних библиотек с использованием Java 7
@edgecaseberg только для шестнадцатеричной строки хорошо смотрится при печати на консоли
sunil
Я обнаружил, что мне нужно использовать toLowerCase () вместо toUpperCase ().
Великолепие
14
Мне недавно пришлось сделать это только для динамической строки, которая MessageDigestможет представлять хеш различными способами. Чтобы получить сигнатуру файла, как вы получили бы с помощью команды md5sum, мне нужно было сделать что-то вроде этого:
Это, очевидно, не отвечает на ваш вопрос о том, как сделать это специально для файла, приведенный выше ответ прекрасно с этим справляется. Я просто потратил много времени на то, чтобы сумма выглядела так, как показывает большинство приложений, и подумал, что вы можете столкнуться с той же проблемой.
Подпись представляет собой дайджест в шестнадцатеричном формате. Я также нашел шестнадцатеричное представление, чтобы работать там, где, как вы говорите, другие представления не работают. Спасибо, что подняли это.
Амит
Это хорошо, но .toString(16)выбросит ведущие нули. String.format("%032x", ...)может быть лучше.
Однако, следите за использованием BigInteger.toString()здесь, так как оно усекает ведущие нули ... (например, попробуйте s = "27", контрольная сумма должна быть "02e74f10e0327ad868d138f2b4fdd6f0")
Второе предложение использовать кодек Apache Commons, я заменил наш собственный код на него.
Ух ты, я искал проблему, в которой материал MD5 работал идеально для всего, кроме файла, который давал нам только 31 шестнадцатеричный вывод, и не выполнял md5checksums. урезание ведущих нулей - огромная боль ... Спасибо за ваше замечание.
Майк
8
publicstaticString MD5Hash(String toHash)throwsRuntimeException{try{returnString.format("%032x",// produces lower case 32 char wide hexa left-padded with 0newBigInteger(1,// handles large POSITIVE numbers MessageDigest.getInstance("MD5").digest(toHash.getBytes())));}catch(NoSuchAlgorithmException e){// do whatever seems relevant}}
Вот простая функция, которая оборачивает код Sunil, так что он принимает File в качестве параметра. Функция не нуждается во внешних библиотеках, но требует 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;publicclassChecksum{/**
* 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
*/publicstaticString generate(File file)throwsNoSuchAlgorithmException,IOException{MessageDigest messageDigest =MessageDigest.getInstance("MD5");
messageDigest.update(Files.readAllBytes(file.toPath()));byte[] hash = messageDigest.digest();returnDatatypeConverter.printHexBinary(hash).toUpperCase();}publicstaticvoid main(String argv[])throwsNoSuchAlgorithmException,IOException{File file =newFile("/Users/foo.bar/Documents/file.jar");String hex =Checksum.generate(file);System.out.printf("hex=%s\n", hex);}}
Google guava предоставляет новый API. Найдите один ниже:
publicstaticHashCode hash(File file,HashFunction hashFunction)throwsIOExceptionComputes 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. Он не требует внешних библиотек и не должен загружать весь файл в память.
publicstaticString hashFile(String algorithm,File f)throwsIOException,NoSuchAlgorithmException{MessageDigest md =MessageDigest.getInstance(algorithm);try(BufferedInputStream in =newBufferedInputStream((newFileInputStream(f)));DigestOutputStream out =newDigestOutputStream(OutputStream.nullOutputStream(), md)){
in.transferTo(out);}String fx ="%0"+(md.getDigestLength()*2)+"x";returnString.format(fx,newBigInteger(1, md.digest()));}
Ответы:
Есть декоратор входного потока
java.security.DigestInputStream
, так что вы можете вычислить дайджест, используя входной поток, как обычно, вместо того, чтобы делать дополнительный проход по данным.источник
is
какInputStream
илиFileInputStream
? Похоже, вы использовалиFileInputStream
, что приведет к этой ошибке.MethodNotFound
Не является исключением из стандартной Java; возможно вы говорите об ошибке компилятора? В любом случае, если это не работает для вас, это проблема локальной конфигурации или проблема с другим кодом.Используйте DigestUtils из библиотеки кодеков Apache Commons :
источник
commons-codec.jar
свой путь к классам?В Java-How-to Real есть пример использования класса MessageDigest .
Посмотрите на этой странице примеры использования CRC32 и SHA-1.
источник
read()
не вернет ноль, иdo/while
не очень подходит.В com.google.common.hash API предлагает:
Прочитайте Руководство пользователя ( IO Разъяснения , хеширование Разъяснения ).
Для вашего
Files.hash()
варианта использования вычисляет и возвращает значение дайджеста для файла.Например, SHA-1 расчет дайджеста (измените SHA-1 на MD5, чтобы получить дайджест MD5)
Обратите внимание, что crc32 намного быстрее чем md5так что пользуйтесь crc32если вам не нужна криптографически безопасная контрольная сумма. Обратите внимание, чтоmd5 не следует использовать для хранения паролей и тому подобного, так как это просто для грубой силы, для использования паролей Bcrypt, Scrypt или SHA-256 вместо.
Для долгосрочной защиты с помощью хэшей схема подписи Merkle повышает безопасность, а Исследовательская группа по постквантовой криптографии, спонсируемая Европейской комиссией, рекомендовала использовать эту криптографию для долговременной защиты от квантовых компьютеров ( см. ).
Обратите внимание, что crc32 имеет более высокий уровень столкновений, чем другие.
источник
Files.hash()
Помечен как устаревший, рекомендуемым способом является:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
отмечен как устаревший. ФункцияHashing.sha256()
рекомендуется вместо этого. источникИспользование nio2 (Java 7+) и отсутствие внешних библиотек:
Чтобы сравнить результат с ожидаемой контрольной суммой:
источник
Guava теперь предоставляет новый, согласованный API-интерфейс хэширования, который намного удобнее для пользователя, чем различные API-интерфейсы хэширования, предоставляемые в JDK. См. Хеширование объяснено . Для файла вы можете легко получить сумму MD5, CRC32 (с версией 14.0+) или многие другие хэши:
источник
Хорошо. Я должен был добавить. Однострочная реализация для тех, кто уже имеет зависимость от Spring и Apache Commons или планирует добавить ее:
Параметр «Только для общего доступа» и Apache (credit @duleshi):
Надеюсь, это кому-нибудь поможет.
источник
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
вам нужноDigestUtils.md5Digest(InputStream inputStream)
рассчитать дайджест MD5 иDigestUtils.md5DigestAsHex(InputStream inputStream)
шестнадцатеричное строковое представление методов дайджеста MD5 без чтения всего файла в память.Простой подход без сторонних библиотек с использованием Java 7
Если вам нужно распечатать этот байтовый массив. Используйте как ниже
Если вам нужна шестнадцатеричная строка из этого дайджеста. Используйте как ниже
где DatatypeConverter является javax.xml.bind.DatatypeConverter
источник
toUpperCase
?Мне недавно пришлось сделать это только для динамической строки, которая
MessageDigest
может представлять хеш различными способами. Чтобы получить сигнатуру файла, как вы получили бы с помощью команды md5sum, мне нужно было сделать что-то вроде этого:Это, очевидно, не отвечает на ваш вопрос о том, как сделать это специально для файла, приведенный выше ответ прекрасно с этим справляется. Я просто потратил много времени на то, чтобы сумма выглядела так, как показывает большинство приложений, и подумал, что вы можете столкнуться с той же проблемой.
источник
.toString(16)
выбросит ведущие нули.String.format("%032x", ...)
может быть лучше.Или вы можете получить больше информации http://www.asjava.com/core-java/java-md5-example/
источник
источник
Мы использовали код, который похож на код выше в предыдущем посте, используя
Однако, следите за использованием
BigInteger.toString()
здесь, так как оно усекает ведущие нули ... (например, попробуйтеs = "27"
, контрольная сумма должна быть"02e74f10e0327ad868d138f2b4fdd6f0"
)Второе предложение использовать кодек Apache Commons, я заменил наш собственный код на него.
источник
источник
Очень быстрый и чистый Java-метод, который не зависит от внешних библиотек:
(Просто замените MD5 на SHA-1, SHA-256, SHA-384 или SHA-512, если хотите)
источник
Другая реализация: быстрая реализация MD5 в Java
источник
MD5.asHex()
в JDK 1.8.0 242.Стандартный способ Java Runtime Environment :
Результат равен утилите linux md5sum.
источник
Вот простая функция, которая оборачивает код Sunil, так что он принимает File в качестве параметра. Функция не нуждается во внешних библиотеках, но требует Java 7.
Пример вывода:
источник
Если вы используете ANT для сборки, это очень просто. Добавьте следующее в свой build.xml:
Где jarFile - это JAR, для которого вы хотите сгенерировать MD5, а toDir - это каталог, куда вы хотите поместить файл MD5.
Больше информации здесь.
источник
Google guava предоставляет новый API. Найдите один ниже:
источник
Вот удобный вариант, который использует
InputStream.transferTo()
Java 9 иOutputStream.nullOutputStream()
Java 11. Он не требует внешних библиотек и не должен загружать весь файл в память.а также
возвращается
источник
источник