Получить контрольную сумму файла java

Быстрый алгоритм подсчёта контрольной суммы для больших JAR файлов

Использовать MD5 дайджест для всего содержимого файла.

MessageDigest digest = MessageDigest . getInstance ( «MD5» ) ;

byte [ ] buf = new byte [ 1024 ] ;

int len = 0 ;

InputStream stream = new BufferedInputStream ( new FileInputStream ( new File ( «/path/to/jar/file» ) ) ) ;

while ( ( len = stream. read ( buf ) ) > 0 ) < digest. update ( buf, 0 , len ) ; >

stream. close ( ) ;

byte [ ] md5sum = digest. digest ( ) ;

Но, можно воспользоваться тем фактом что JAR уже содержит CRC для каждого из файла в архиве.
Используем MD5 дайджест только для CRC последовательности.

Финальная версия

import java.io.* ;

import java.math.* ;

import java.security.* ;

import java.util.* ;

import java.util.jar.* ;

public class JarFileChecksum < private final File jarFile ; public JarFileChecksum ( File jarFile ) < this . jarFile = jarFile ; >

public String getChecksum ( ) throws Exception < MessageDigest digest = MessageDigest . getInstance ( «MD5» ) ; JarFile jar = new JarFile ( jarFile ) ; int crc ; byte [ ] buf = new byte [ 4 ] ; for ( Enumeration < JarEntry >e=jar. entries ( ) ; e. hasMoreElements ( ) ; ) < JarEntry entry = e. nextElement ( ) ; // CRC на самом деле integer crc = ( int ) entry. getCrc ( ) ; // split crc to bytes buf [ 0 ] = ( byte ) ( ( crc >> 24 ) & 0xFF ) ;

buf [ 1 ] = ( byte ) ( ( crc >> 16 ) & 0xFF ) ;

buf [ 2 ] = ( byte ) ( ( crc >> 8 ) & 0xFF ) ;

buf [ 3 ] = ( byte ) ( crc & 0xFF ) ;

digest. update ( buf ) ;

>

jar. close ( ) ;

byte [ ] md5sum = digest. digest ( ) ;

// превратим в String

BigInteger bigInt = new BigInteger ( 1 , md5sum ) ;

return bigInt. toString ( 16 ) ;

>

>

Тесты

Для тестирования был выбран JAR файл размером 1.6G, 37000 файлов и 1500 директорий.

Первый способ:140 секунды
Второй способ: 0.5 секунды

Источник

Вычисление контрольной суммы файла

Контрольная сумма от набора байт позволяет убедиться в том, что данные на клиенте, полученные от сервера, являются корректными. Для этого вместе с файлом сервер может предоставлять контрольную сумму для проверки на клиентской стороне. Существует несколько алгоритмов вычисления контрольной суммы, рассмотрим самые популярные: md5, sha-256, sha-512 и crc-32.

Вычисление md5 с помощью MessageDigest

В пакете java.security есть такой класс как MessageDigest. Он позволяет получить одну из встроенных реализаций алгоритма вычисления контрольных сумм. Поэтому сначала реализуем метод, который абстрагирован от конкретного алгоритма и работает с любым MessageDigest одинаково.

private static String checksumForDigest(String filename, MessageDigest md) throws IOException <
try (
var fis = new FileInputStream(filename);
var bis = new BufferedInputStream(fis);
var dis = new DigestInputStream(bis, md)
) <
while (dis.read() != — 1 ) ;
md = dis.getMessageDigest();
>

Метод checksumForDigest() получает два параметра: полное имя файла и объект MessageDigest. Затем используем конструкцию try-with-resources, в котором последовательно создаём три потока, «оборачивая» один в другой. По выходу из блока try эти потоки будут закрыты автоматически.

Сначала создаётся поток FileInputStream, связанный непосредственно с целевым файлом, для которого считаем контрольную сумму.

Затем этот поток обрачиваем в BufferedInputStream, чтобы добавить буфер потока и значительно ускорить работу с файловой системой. Оптимизация работает за счёт того, что мы не грузим массив байт из файла целиком в память, а читаем его небольшими порциями. Таким образом мы можем читать сколь угодно большой файл, не боясь исчерпать всю оперативную память.

Наконец, этот второй буферизованный поток оборачиваем в DigestInputStream, который и реализует механизм подсчёта контрольной сумму в соответствии с заданным в MessageDigest алгоритмом.

Вы можете убедиться, что если убрать BufferedInputStream из этой цепочки, то при работе с большими файлами задержка окажется довольно заметной.

Кстати, такая «матрёшка» из потоков является типичным примером паттерна «Декоратор», который позволяет наращивать функциональность объекта, не меняя исходный интерфейс.

Затем в цикле читаем файл. Тело цикла при этом должно быть пустым, т.к. каких-то специальных действий на каждой итерации нам делать не нужно – всё необходимое делает DigestInputStream.

После завершения чтения файла получаем новый объект MessageDigest с помощью метода getMessageDigest(). Чтобы получить шестандцатеричную строку хеша, выполним следующее преобразование:

// bytes to hex
var result = new StringBuilder();
for ( byte b : md.digest()) result.append(String.format( «%02x» , b));
>
return result.toString();

Теперь осталось передать абсолютный путь до целевого файла и требуемую реализацию алгоритма md-5.

public static void main(String[] args) throws IOException, NoSuchAlgorithmException <
var filename = «/home/user/test.txt» ;
var messageDigest = MessageDigest.getInstance( «MD5» );
System.out.println(checksumForDigest(filename, messageDigest));
>

Объект messageDigest получаем с помощью метода getInstance(). Теперь запустим наш пример и в консоли увидим строку в шестандцатеричном формате. Для проверки в linux-системах можно использовать консольную утилиту md5sum. В результате в консоли увидим нечто подобное:

Вычисление sha-256 и sha-512

Семейство алгоритмов SHA-2 (Secure Hash Algorithm Version 2 – безопасный алгоритм хеширования, версия 2) включает в себя наиболее популярные sha-256 и sha-512. Мы также можем вычислять их с помощью метода, рассмотренного выше.

public static void main(String[] args) throws IOException, NoSuchAlgorithmException <
var filename = «/home/user/test.txt» ;
var messageDigest = MessageDigest.getInstance( «SHA-256» ); // или «SHA-512»
System.out.println(checksumForDigest(filename, messageDigest));
>

Как видите, метод main() почти не изменился. Мы просто поменяли параметр getInstance() на «SHA-256». Вычисление SHA-512 происходит аналогично.

Для проверки полученных значений в консоли можем воспользоваться утилитами sha256sum и sha512sum соответственно:

sha256sum test.txt
24c5e1ce2476011f59fc89c98c221370f424d12c7eac5eaeeea5bcda9b5ae1df test.txt

sha512sum test.txt
d8f41a39aed21317d92ea86e3c71e6b2f1db4732847914ae11628e2d357e32
28d67c9c559cdc18d2cc6f3c9789cab443e1b33cf6d97e88fc694bdb593076591b test.txt

Как видите, хэш SHA-512 длинее, а потому безопаснее и рекомендуется использовать именно его.

Вычисление crc-32

Теперь перейдём к хэшу crc-32 (Cyclic redundancy check). Метод его вычисления ещё проще:

private static String getCrc32(String filename, Checksum checksum) throws IOException <
try (
var fis = new FileInputStream(filename);
var bis = new BufferedInputStream(fis);
var cis = new CheckedInputStream(bis, checksum);
) <
while (cis.read() >= 0 ) ;
return Long .toHexString(cis.getChecksum().getValue());
>
>

Метод на вход получает абсолютное имя файла и объект с интерфейсом Checksum из пакета java.util.zip. Java предлагает несколько реализаций Checksum, одной из которых является класс CRC32.

Здесь мы также используем конструкцию try-with-resources из трёх потоков, как и в предыдущем примере. FileInputStream связан с целевым файлом, BufferedInputStream обеспечивает буферизацию для ускорения обработки больших файлов, а CheckedInputStream как раз позволяет вычислять контрольную сумму с помощью объекта Checksum.

Тут у нас также используется пустой цикл, который считывает файл до конца. После завершения чтения файла мы получаем контрольную сумму в виде целого числа с помощью метода getChecksum().getValue(). Для того, чтобы привести это число в шестнадцатеричный формат, воспользуемся методом Long.toHexString().

Наш метод main() для вычисления контрольной суммы crc-32 будет выглядеть так:

public static void main(String[] args) throws IOException <
var filename = «/home/user/test.txt» ;
System.out.println(getCrc32(filename, new CRC32 ())); // или CRC32C()
>

Второй реализацией интерфейса Checksum является класс CRC32C – одна из разновидностей алгоритма CRC.

Теперь запустим наш пример и получим контрольную сумму в шестнадцатеричном формате. Для её проверки воспользуемся консольной утилитой crc32:

Как видите, в данном случае код довольно компактный.

Выводы

Мы увидели, что «из коробки» Java предоставляет реализации всех популярных алгоритмов для вычисления контрольных сумм, причём от нас не требуется разбираться в их внутреннем устройстве – достаточно лишь использовать соотвествующий поток. Также для ускорения обработки больших файлов нужно не забывать про буферизацию.

Источник

Java File Checksum – MD5 and SHA-256 Hash Examples

A checksum hash is an encrypted sequence of characters obtained after applying specific algorithms and manipulations on user-provided content. In this Java hashing tutorial, we will learn to generate the checksum hash for the files.

1. Why Generate a File’s Checksum?

Any serious file provider provides a mechanism to have a checksum on their downloadable files. A checksum is a form of mechanism to ensure that the file we downloaded is correctly downloaded.

Checksum acts like a proof of the validity of a file so if a file gets corrupted this checksum will change and thus let us know that this file is not the same file or the file has been compromised between the transfer for any reason.

We can also create the file’s checksum to detect any possible change in the file by third parties e.g. license files. We provide licenses to clients which they may upload to their servers. We can cross-verify the file’s checksum to verify that the license file has not been modified after creation.

To create checksum for a file, we will need to read the file’s content, and then generate the hash for it using one of the following methods. Note that both approaches support all types of algorithms so we can use the same code for other algorithms such as HmacMd5, SHA, SHA-512 etc.

2. Generate File Checksum with MessageDigest

MessageDigest class provides applications with the functionality of a message digest algorithm, such as MD5 or SHA-256. Its getInstance() method returns a MessageDigest object that implements the specified digest algorithm.

Example 1: Generate MD5 Hash for a File in Java

Path filePath = Path.of("c:/temp/testOut.txt"); byte[] data = Files.readAllBytes(Paths.get(filePath)); byte[] hash = MessageDigest.getInstance("MD5").digest(data); String checksum = new BigInteger(1, hash).toString(16);

Example 2: Generate SHA-256 Hash for a File in Java

Path filePath = Path.of("c:/temp/testOut.txt"); byte[] data = Files.readAllBytes(Paths.get(filePath)); byte[] hash = MessageDigest.getInstance("SHA-256").digest(data); String checksum = new BigInteger(1, hash).toString(16);

3. Generate File Checksum with Guava

In Google Guava, ByteSource.hash() method hashes the contents with the specified hash function as method argument.

Start with adding the latest version of Guava to the project’s classpath.

 com.google.guava guava 31.1-jre  

Now we can use the hash() function as follows.

Example 1: Generate MD5 Hash for a File in Java

File file = new File("c:/temp/test.txt"); ByteSource byteSource = com.google.common.io.Files.asByteSource(file); HashCode hc = byteSource.hash(Hashing.md5()); String checksum = hc.toString();

Example 2: Generate SHA-256 Hash for a File in Java

File file = new File("c:/temp/test.txt"); ByteSource byteSource = com.google.common.io.Files.asByteSource(file); HashCode hc = byteSource.hash(Hashing.sha256()); String checksum = hc.toString();

Drop me a comment if something needs more explanation.

Источник

Java — Создать контрольную сумму файла с SHA и MD5

В этой статье мы покажем вам, как использовать алгоритм SHA-256 и MD5 для генерации контрольной суммы для файла.

1. Дайджест сообщения

1.1 Generate a file checksum with a SHA256 algorithm.

package com.example.hashing; import java.io.FileInputStream; import java.io.IOException; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class FileCheckSumSHA < public static void main(String[] args) throws NoSuchAlgorithmException, IOException < MessageDigest md = MessageDigest.getInstance("SHA-256"); //SHA, MD2, MD5, SHA-256, SHA-384. String hex = checksum("d:\\server.log", md); System.out.println(hex); >private static String checksum(String filepath, MessageDigest md) throws IOException < // file hashing with DigestInputStream try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) < while (dis.read() != -1) ; //empty loop to clear the data md = dis.getMessageDigest(); >// bytes to hex StringBuilder result = new StringBuilder(); for (byte b : md.digest()) < result.append(String.format("%02x", b)); >return result.toString(); > >
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

1.2 Generate a file checksum with a MD5 algorithm.

package com.example.hashing; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class FileCheckSumMD5 < public static void main(String[] args) throws NoSuchAlgorithmException, IOException < MessageDigest md = MessageDigest.getInstance("MD5"); String hex = checksum("d:\\server.log", md); System.out.println(hex); >private static String checksum(String filepath, MessageDigest md) throws IOException < // DigestInputStream is better, but you also can hash file like this. try (InputStream fis = new FileInputStream(filepath)) < byte[] buffer = new byte[1024]; int nread; while ((nread = fis.read(buffer)) != -1) < md.update(buffer, 0, nread); >> // bytes to hex StringBuilder result = new StringBuilder(); for (byte b : md.digest()) < result.append(String.format("%02x", b)); >return result.toString(); > >
5eb63bbbe01eeed093cb22bb8f5acdc3

Источник

Читайте также:  Php curl set ssl
Оцените статью