Saya mencari untuk menggunakan Java untuk mendapatkan MD5 checksum dari suatu file. Saya benar-benar terkejut tetapi saya belum dapat menemukan apa pun yang menunjukkan cara mendapatkan MD5 checksum dari suatu file.
Bagaimana ini dilakukan?
Saya mencari untuk menggunakan Java untuk mendapatkan MD5 checksum dari suatu file. Saya benar-benar terkejut tetapi saya belum dapat menemukan apa pun yang menunjukkan cara mendapatkan MD5 checksum dari suatu file.
Bagaimana ini dilakukan?
Jawaban:
Ada dekorator aliran input java.security.DigestInputStream
,, sehingga Anda dapat menghitung intisari menggunakan aliran input seperti biasa, alih-alih harus membuat data tambahan.
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
sebagai InputStream
atau a FileInputStream
? Kedengarannya seperti yang Anda gunakan FileInputStream
, yang akan menyebabkan kesalahan ini.
MethodNotFound
tidak terkecuali dari Java standar; mungkin Anda berbicara tentang kesalahan kompiler? Bagaimanapun, jika itu tidak berhasil untuk Anda, itu adalah masalah konfigurasi lokal, atau masalah dengan kode lain.
Gunakan DigestUtils dari pustaka Codec Apache Commons :
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
di classpath Anda?
Ada contoh di Java-How-to Real menggunakan kelas MessageDigest .
Periksa halaman itu untuk contoh menggunakan CRC32 dan SHA-1 juga.
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()
tidak akan mengembalikan nol, dan a do/while
tidak terlalu tepat.
The com.google.common.hash menawarkan API:
Baca Panduan Pengguna ( Dijelaskan IO , Dijelaskan Hashing ).
Untuk kasus penggunaan Anda Files.hash()
menghitung dan mengembalikan nilai digest untuk file.
Misalnya a sha-1 digest digest (ubah SHA-1 ke MD5 untuk mendapatkan MD5 digest)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Catat itu crc32 jauh lebih cepat daripada md5, jadi gunakan crc32jika Anda tidak memerlukan checksum yang aman secara kriptografis. Perhatikan juga itumd5 tidak boleh digunakan untuk menyimpan kata sandi dan sejenisnya karena mudah untuk memaksa, untuk penggunaan kata sandi bcrypt, scrypt atau sha-256 sebagai gantinya.
Untuk perlindungan jangka panjang dengan hash, skema tanda tangan Merkle menambah keamanan dan The Post Quantum Cryptography Study Group yang disponsori oleh Komisi Eropa merekomendasikan penggunaan kriptografi ini untuk perlindungan jangka panjang terhadap komputer kuantum ( ref ).
Catat itu crc32 memiliki tingkat tabrakan yang lebih tinggi daripada yang lain.
Files.hash()
ditandai sebagai usang, cara yang direkomendasikan adalah:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
ditandai usang. Fungsi Hashing.sha256()
ini direkomendasikan sebagai gantinya. sumber
Menggunakan nio2 (Java 7+) dan tidak ada perpustakaan eksternal:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
Untuk membandingkan hasilnya dengan checksum yang diharapkan:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava sekarang menyediakan API hashing baru yang konsisten, yang jauh lebih ramah pengguna daripada berbagai API hashing yang disediakan di JDK. Lihat Hashing Dijelaskan . Untuk file, Anda bisa mendapatkan jumlah MD5, CRC32 (dengan versi 14.0+) atau banyak hash lainnya dengan mudah:
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();
Baik. Saya harus menambahkan. Implementasi satu baris untuk mereka yang sudah memiliki ketergantungan Spring dan Apache Commons atau berencana untuk menambahkannya:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Opsi hanya untuk dan Apache commons (kredit @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Semoga ini bisa membantu seseorang.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
Anda harus DigestUtils.md5Digest(InputStream inputStream)
menghitung MD5 digest dan DigestUtils.md5DigestAsHex(InputStream inputStream)
untuk representasi string heksadesimal dari metode digest MD5 tanpa membaca seluruh file ke dalam memori.
Pendekatan sederhana tanpa perpustakaan pihak ketiga menggunakan Java 7
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Jika Anda perlu mencetak array byte ini. Gunakan seperti di bawah ini
System.out.println(Arrays.toString(digest));
Jika Anda membutuhkan string hex keluar dari intisari ini. Gunakan seperti di bawah ini
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
di mana DatatypeConverter adalah javax.xml.bind.DatatypeConverter
toUpperCase
?
Saya baru-baru ini harus melakukan ini hanya untuk string dinamis, MessageDigest
dapat mewakili hash dengan berbagai cara. Untuk mendapatkan tanda tangan dari file seperti yang Anda dapatkan dengan perintah md5sum saya harus melakukan sesuatu seperti ini:
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();
}
Ini jelas tidak menjawab pertanyaan Anda tentang bagaimana melakukannya secara khusus untuk file, jawaban di atas berkaitan dengan tenang itu. Saya hanya menghabiskan banyak waktu untuk mendapatkan jumlah agar terlihat seperti kebanyakan aplikasi menampilkannya, dan berpikir Anda mungkin mengalami masalah yang sama.
.toString(16)
akan membuang angka nol di depan. String.format("%032x", ...)
mungkin lebih baik.
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());
}
Atau Anda bisa mendapatkan info lebih lanjut http://www.asjava.com/core-java/java-md5-example/
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Kami menggunakan kode yang menyerupai kode di atas dalam posting sebelumnya menggunakan
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Namun, berhati-hatilah untuk menggunakannya di BigInteger.toString()
sini, karena akan memotong nol di depan ... (misalnya, coba s = "27"
, checksum seharusnya "02e74f10e0327ad868d138f2b4fdd6f0"
)
Saya saran kedua untuk menggunakan Apache Commons Codec, saya mengganti kode kita sendiri dengan itu.
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
}
}
Metode Java yang sangat cepat & bersih yang tidak bergantung pada pustaka eksternal:
(Cukup ganti MD5 dengan SHA-1, SHA-256, SHA-384 atau SHA-512 jika Anda menginginkannya)
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);
}
Implementasi lain: Implementasi MD5 Cepat di Jawa
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
di JDK 1.8.0 242.
Cara Java Runtime Environment standar :
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;
}
}
Hasilnya sama dengan utilitas linux md5sum.
Berikut adalah fungsi sederhana yang membungkus kode Sunil sehingga mengambil File sebagai parameter. Fungsi ini tidak memerlukan pustaka eksternal, tetapi membutuhkan 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);
}
}
Contoh output:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Jika Anda menggunakan ANT untuk membangun, ini sangat sederhana. Tambahkan yang berikut ke build.xml Anda:
<checksum file="${jarFile}" todir="${toDir}"/>
Di mana jarFile adalah JAR yang ingin Anda hasilkan MD5, dan toDir adalah direktori tempat Anda ingin meletakkan file MD5.
Google jambu menyediakan API baru. Temukan yang di bawah ini:
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
Berikut ini adalah variasi praktis yang memanfaatkan InputStream.transferTo()
dari Java 9, dan OutputStream.nullOutputStream()
dari Java 11. Tidak memerlukan pustaka eksternal dan tidak perlu memuat seluruh file ke dalam memori.
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()));
}
dan
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
kembali
"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();
}