Chcę użyć Java, aby uzyskać sumę kontrolną MD5 pliku. Byłem naprawdę zaskoczony, ale nie byłem w stanie znaleźć niczego, co pokazuje, jak uzyskać sumę kontrolną MD5 pliku.
Jak to jest zrobione?
Chcę użyć Java, aby uzyskać sumę kontrolną MD5 pliku. Byłem naprawdę zaskoczony, ale nie byłem w stanie znaleźć niczego, co pokazuje, jak uzyskać sumę kontrolną MD5 pliku.
Jak to jest zrobione?
Odpowiedzi:
Istnieje dekorator strumienia wejściowego java.security.DigestInputStream
, dzięki czemu można obliczyć podsumowanie podczas korzystania ze strumienia wejściowego w normalny sposób, bez konieczności dodatkowego przekazywania danych.
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
jako InputStream
a FileInputStream
? Wygląda na to, że został użyty FileInputStream
, co spowodowałoby ten błąd.
MethodNotFound
nie jest wyjątkiem od standardowej Java; może mówisz o błędzie kompilatora? W każdym razie, jeśli to nie działa, oznacza to lokalny problem z konfiguracją lub problem z innym kodem.
Użyj DigestUtils z biblioteki kodeków Apache Commons :
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
na ścieżce klasy?
Jest przykład w Javie Real'a dotyczącej korzystania z klasy MessageDigest .
Sprawdź na tej stronie również przykłady użycia CRC32 i 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()
nie zwróci zera, a a do/while
nie jest naprawdę właściwe.
W com.google.common.hash oferty API:
Przeczytaj Podręcznik użytkownika ( wyjaśnienie IO , wyjaśnienie skrótu ).
Dla twojego przypadku użycia Files.hash()
oblicza i zwraca wartość skrótu dla pliku.
Na przykład sha-1 obliczanie skrótu (zmień SHA-1 na MD5, aby uzyskać skrót MD5)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Zauważ, że crc32 jest znacznie szybszy niż md5, więc użyj crc32jeśli nie potrzebujesz kryptograficznie bezpiecznej sumy kontrolnej. Zauważ też, żemd5 nie powinny być używane do przechowywania haseł i tym podobnych, ponieważ łatwo jest użyć siły, do użycia haseł bcrypt, scrypt lub sha-256 zamiast.
W celu zapewnienia długoterminowej ochrony za pomocą skrótów program sygnatury Merkle zwiększa bezpieczeństwo, a sponsorowana przez Komisję Europejską grupa analityczna ds. Kryptografii post kwantowej zaleciła stosowanie tej kryptografii w celu długoterminowej ochrony przed komputerami kwantowymi ( zob .).
Zauważ, że crc32 ma wyższy współczynnik kolizji niż inne.
Files.hash()
Jest oznaczony jako przestarzałe, zalecanym sposobem jest:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
Jest oznaczony jako przestarzały. Hashing.sha256()
Zamiast tego zalecana jest funkcja . źródło
Korzystanie z nio2 (Java 7+) i bez bibliotek zewnętrznych:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
Aby porównać wynik z oczekiwaną sumą kontrolną:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava udostępnia teraz nowy, spójny interfejs API mieszania, który jest o wiele bardziej przyjazny dla użytkownika niż różne interfejsy API mieszania dostępne w JDK. Zobacz Wyjaśnienie skrótu . W przypadku pliku można łatwo uzyskać sumę MD5, CRC32 (z wersją 14.0+) lub wiele innych skrótów:
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();
Ok. Musiałem dodać. Jednowierszowa implementacja dla tych, którzy mają już zależność Spring i Apache Commons lub planują ją dodać:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Dla i tylko wspólne opcje Apache (kredyt @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Mam nadzieję, że to komuś pomoże.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
musisz DigestUtils.md5Digest(InputStream inputStream)
obliczyć skrót MD5 i DigestUtils.md5DigestAsHex(InputStream inputStream)
szesnastkową reprezentację ciągu metod skrótu MD5 bez wczytywania całego pliku do pamięci.
Proste podejście bez bibliotek stron trzecich korzystających z Java 7
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Jeśli musisz wydrukować tę tablicę bajtów. Użyj jak poniżej
System.out.println(Arrays.toString(digest));
Jeśli potrzebujesz ciągu szesnastkowego z tego skrótu. Użyj jak poniżej
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
gdzie DatatypeConverter to javax.xml.bind.DatatypeConverter
toUpperCase
?
Niedawno musiałem to zrobić tylko dla dynamicznego ciągu, MessageDigest
może reprezentować skrót na wiele sposobów. Aby uzyskać podpis pliku, tak jak w przypadku polecenia md5sum , musiałem zrobić coś takiego:
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();
}
To oczywiście nie odpowiada na twoje pytanie, jak to zrobić specjalnie dla pliku, powyższa odpowiedź ładnie radzi sobie z tym spokojem. Spędziłem dużo czasu, aby suma wyglądała tak, jakby wyświetlała ją większość aplikacji, i pomyślałem, że możesz mieć takie same problemy.
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());
}
Lub możesz uzyskać więcej informacji http://www.asjava.com/core-java/java-md5-example/
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Używaliśmy kodu, który przypomina kod powyżej w poprzednim poście przy użyciu
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Uważaj jednak na użycie BigInteger.toString()
tutaj, ponieważ spowoduje to obcięcie wiodących zer ... (na przykład spróbuj s = "27"
, suma kontrolna powinna wynosić"02e74f10e0327ad868d138f2b4fdd6f0"
)
Popieram sugestię użycia kodeka Apache Commons, zastąpiłem tym kodem.
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
}
}
Bardzo szybka i czysta metoda Java, która nie polega na bibliotekach zewnętrznych:
(Po prostu zamień MD5 na SHA-1, SHA-256, SHA-384 lub SHA-512, jeśli chcesz)
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);
}
Kolejna implementacja: szybka implementacja MD5 w Javie
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
w JDK 1.8.0 242.
Standardowy sposób 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;
}
}
Wynik jest równy narzędziu Linux md5sum.
Oto prosta funkcja, która owija się wokół kodu Sunila, dzięki czemu przyjmuje parametr File jako parametr. Ta funkcja nie wymaga żadnych zewnętrznych bibliotek, ale wymaga 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);
}
}
Przykładowe dane wyjściowe:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Jeśli używasz ANT do budowania, jest to bardzo proste. Dodaj następujące elementy do pliku build.xml:
<checksum file="${jarFile}" todir="${toDir}"/>
Gdzie jarFile to plik JAR, dla którego chcesz wygenerować MD5, a toDir to katalog, w którym chcesz umieścić plik MD5.
Google guava zapewnia nowy interfejs API. Znajdź ten poniżej:
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
Oto przydatna odmiana, która korzysta InputStream.transferTo()
z Java 9 i OutputStream.nullOutputStream()
Java 11. Nie wymaga zewnętrznych bibliotek i nie musi ładować całego pliku do pamięci.
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()));
}
i
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
zwroty
"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();
}