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.
Mungkin ini akan membantu. Anda juga bisa melihat speknya tetapi itu akan lebih sulit karena rumit.
waynecolvin
4
Perlu diingat bahwa menurut penelitian terbaru "MD5 harus dianggap rusak secara kriptografis dan tidak cocok untuk penggunaan lebih lanjut". en.wikipedia.org/wiki/MD5
Zakharia Stanley
80
MD5 tidak lagi dianggap aman secara kriptografis, tetapi masih cukup untuk memvalidasi konsistensi file dan lebih cepat daripada SHA.
jiggy
2
@ZakhariaStanley Ini adalah pertanyaan tentang checksumming.
iPherian
Penggunaan kanonik untuk checksum MD5 pada file adalah untuk menghindari penggantian file yang didistribusikan secara bermusuhan. Di situlah tidak aman. Tetapi dalam skenario di mana eksploitasi yang bermusuhan tidak menjadi perhatian, itu sangat cocok.
Keith Tyler
Jawaban:
541
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 =newDigestInputStream(is, md)){/* Read decorated stream (dis) to EOF as normal... */}byte[] digest = md.digest();
Saya setuju, cara yang sangat elegan untuk menghitung checksum dengan cepat jika Anda sudah melakukan sesuatu dengan byte (yaitu membacanya dari koneksi HTTP).
Marc Novakowski
2
@AlPhaba Apakah Anda menyatakan issebagai InputStreamatau a FileInputStream? Kedengarannya seperti yang Anda gunakan FileInputStream, yang akan menyebabkan kesalahan ini.
erickson
1
@barwnikk berfungsi dengan baik di Java 8. MethodNotFoundtidak 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.
erickson
4
@barwnikk Sekali lagi, itu adalah masalah konfigurasi lokal Anda. Ini adalah kode Java 7 dan Java 8 yang valid. Jika Anda terjebak dengan alat dari tahun 2006, Anda harus beradaptasi.
erickson
5
@erickson Anda tidak memperbarui objek MessageDigest dengan konten file. Rt? Kode ini akan mencetak intisari yang selalu sama.
Tidak berfungsi untuk saya dalam kode android saya, saya mendapatkan kesalahan ini ... java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString di org.apache.commons.codec.digest.DigestUtils.md5Hex (DigestUtils.java .: 15)
JPM
@ JPM Anggap Anda sudah mengunduh dan meletakkannya commons-codec.jardi classpath Anda?
Leif Gruenwoldt
ya di sana dan saya diekspor di proyek android saya .. Saya bisa melangkah melalui kode dan kelas ada di file sumber ... aneh, pasti ada masalah Android Eclipse.
JPM
1
Saya memiliki masalah yang sama, tetapi diperbaiki dengan kode ini `FileInputStream fis = FileInputStream baru (File baru (filePath)); data byte [] = org.apache.commons.codec.digest.DigestUtils.md5 (fis); char md5Chars [] = Hex.encodeHex (data); String md5 = String.valueOf (md5Chars); `
Dmitry_L
1
Bagus! Untuk proyek baru, saya selalu berpikir dua kali sebelum menambahkan ketergantungan baru tetapi untuk proyek yang sudah ada saya hanya perlu memeriksa apakah perpustakaan sudah ada untuk menggunakannya. +1
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.
@Arash ya benar - terima kasih. Saya mencampur kelas File JDK dan Guava.
assylias
Saya suka solusi ini lebih dari erickson karena dapat dibungkus dengan Opsional untuk menggunakan pemrograman gaya Fungsional murni
Gabriel Hernandez
2
Untuk file besar ini akan menggunakan banyak memori karena seluruh file dibaca dan kemudian diumpankan ke digest daripada membaca potongan dan "mencerna" mereka saat mereka membaca.
bernie
39
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 directlylong checksumResult = crc32.padToLong();
Baik. Saya harus menambahkan. Implementasi satu baris untuk mereka yang sudah memiliki ketergantungan Spring dan Apache Commons atau berencana untuk menambahkannya:
Solusi berbasis David Onter commons lebih baik karena tidak membaca seluruh file ke dalam memori.
Fran Marzoa
Setidaknya bagi 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.
Mike Shauneu
24
Pendekatan sederhana tanpa perpustakaan pihak ketiga menggunakan Java 7
@edgecaseberg hanya untuk string hex terlihat bagus saat mencetaknya ke konsol
sunil
Saya merasa perlu menggunakan toLowerCase () alih-alih toUpperCase ().
Kemegahan
14
Saya baru-baru ini harus melakukan ini hanya untuk string dinamis, MessageDigestdapat mewakili hash dengan berbagai cara. Untuk mendapatkan tanda tangan dari file seperti yang Anda dapatkan dengan perintah md5sum saya harus melakukan sesuatu seperti ini:
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.
Tanda tangan adalah intisari dalam format heksadesimal. Saya juga menemukan representasi heksadesimal untuk bekerja di mana, seperti yang Anda katakan, representasi lain tidak berfungsi. Terima kasih telah menyiapkan ini.
amit
Ini bagus, tetapi .toString(16)akan membuang angka nol di depan. String.format("%032x", ...)mungkin lebih baik.
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.
Wow, saya sedang mencari masalah di mana hal-hal MD5 bekerja dengan sempurna untuk semuanya, kecuali file hanya memberi kita 31 hex output, dan gagal pada md5checksums. bahwa memotong 0s memimpin adalah rasa sakit yang sangat besar ... Terima kasih atas catatan Anda.
Mike
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}}
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;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 jambu menyediakan API baru. Temukan yang di bawah ini:
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
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.
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()));}
Jawaban:
Ada dekorator aliran input
java.security.DigestInputStream
,, sehingga Anda dapat menghitung intisari menggunakan aliran input seperti biasa, alih-alih harus membuat data tambahan.sumber
is
sebagaiInputStream
atau aFileInputStream
? Kedengarannya seperti yang Anda gunakanFileInputStream
, 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 :
sumber
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.
sumber
read()
tidak akan mengembalikan nol, dan ado/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)
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.
sumber
Files.hash()
ditandai sebagai usang, cara yang direkomendasikan adalah:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
ditandai usang. FungsiHashing.sha256()
ini direkomendasikan sebagai gantinya. sumberMenggunakan nio2 (Java 7+) dan tidak ada perpustakaan eksternal:
Untuk membandingkan hasilnya dengan checksum yang diharapkan:
sumber
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:
sumber
Baik. Saya harus menambahkan. Implementasi satu baris untuk mereka yang sudah memiliki ketergantungan Spring dan Apache Commons atau berencana untuk menambahkannya:
Opsi hanya untuk dan Apache commons (kredit @duleshi):
Semoga ini bisa membantu seseorang.
sumber
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
Anda harusDigestUtils.md5Digest(InputStream inputStream)
menghitung MD5 digest danDigestUtils.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
Jika Anda perlu mencetak array byte ini. Gunakan seperti di bawah ini
Jika Anda membutuhkan string hex keluar dari intisari ini. Gunakan seperti di bawah ini
di mana DatatypeConverter adalah javax.xml.bind.DatatypeConverter
sumber
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: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.
sumber
.toString(16)
akan membuang angka nol di depan.String.format("%032x", ...)
mungkin lebih baik.Atau Anda bisa mendapatkan info lebih lanjut http://www.asjava.com/core-java/java-md5-example/
sumber
sumber
Kami menggunakan kode yang menyerupai kode di atas dalam posting sebelumnya menggunakan
Namun, berhati-hatilah untuk menggunakannya di
BigInteger.toString()
sini, karena akan memotong nol di depan ... (misalnya, cobas = "27"
, checksum seharusnya"02e74f10e0327ad868d138f2b4fdd6f0"
)Saya saran kedua untuk menggunakan Apache Commons Codec, saya mengganti kode kita sendiri dengan itu.
sumber
sumber
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)
sumber
Implementasi lain: Implementasi MD5 Cepat di Jawa
sumber
MD5.asHex()
di JDK 1.8.0 242.Cara Java Runtime Environment standar :
Hasilnya sama dengan utilitas linux md5sum.
sumber
Berikut adalah fungsi sederhana yang membungkus kode Sunil sehingga mengambil File sebagai parameter. Fungsi ini tidak memerlukan pustaka eksternal, tetapi membutuhkan Java 7.
Contoh output:
sumber
Jika Anda menggunakan ANT untuk membangun, ini sangat sederhana. Tambahkan yang berikut ke build.xml Anda:
Di mana jarFile adalah JAR yang ingin Anda hasilkan MD5, dan toDir adalah direktori tempat Anda ingin meletakkan file MD5.
Info lebih lanjut di sini.
sumber
Google jambu menyediakan API baru. Temukan yang di bawah ini:
sumber
Berikut ini adalah variasi praktis yang memanfaatkan
InputStream.transferTo()
dari Java 9, danOutputStream.nullOutputStream()
dari Java 11. Tidak memerlukan pustaka eksternal dan tidak perlu memuat seluruh file ke dalam memori.dan
kembali
sumber
sumber