Bir dosyanın MD5 sağlama toplamı almak için Java kullanmak arıyorum. Gerçekten şaşırdım ama bir dosyanın MD5 sağlama toplamını nasıl alacağımı gösteren hiçbir şey bulamadım.
Nasıl oldu?
Bir dosyanın MD5 sağlama toplamı almak için Java kullanmak arıyorum. Gerçekten şaşırdım ama bir dosyanın MD5 sağlama toplamını nasıl alacağımı gösteren hiçbir şey bulamadım.
Nasıl oldu?
Yanıtlar:
Bir giriş akışı dekoratörü vardır, java.security.DigestInputStream
böylece giriş akışını normalde yaptığınız gibi kullanırken, veri üzerinde ekstra bir geçiş yapmak yerine özeti hesaplayabilirsiniz.
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
olarak mı ilan ettiniz ? Kullandığınız gibi geliyor , bu da bu hataya neden olacak. InputStream
FileInputStream
FileInputStream
MethodNotFound
. Standart Java'nın bir istisnası değildir; belki bir derleyici hatası hakkında konuşuyorsunuz? Her durumda, sizin için işe yaramazsa, bu bir yerel yapılandırma sorunu veya diğer kodla ilgili bir sorundur.
Kullanım DigestUtils gelen Apache Commons Codec kütüphanesinde:
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
zaten sınıf yolunuza koyduğunuzu varsayın ?
Real'in Java-How- to'da MessageDigest sınıfını kullanma örneği var .
CRC32 ve SHA-1 kullanan örnekler için bu sayfayı kontrol edin.
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()
sıfır döndürmez ve do/while
gerçekten uygun değildir.
Com.google.common.hash API sunar:
Kullanım Kılavuzunu okuyun ( IO Açıklaması , Hashing Açıklaması ).
Kullanım durumunuz Files.hash()
için bir dosyanın özet değerini hesaplar ve döndürür.
Örneğin a SHA-1 özet hesaplaması (MD5 özetini almak için SHA-1'i MD5 olarak değiştirin)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
Bunu not et crc32 daha hızlı md5, öyleyse kullan crc32kriptografik olarak güvenli bir sağlama toplamına ihtiyacınız yoksa. Ayrıca şunu da unutmayınmd5 şifreleri saklamak için kullanılmamalıdır, çünkü şifreleri kullanmak için gücü zorlaştırmak kolaydır bcrypt, scrypt veya SHA-256 yerine.
Karmalarla uzun süreli koruma için, güvenliğe bir Merkle imza şeması eklenir ve Avrupa Komisyonu tarafından desteklenen Post Kuantum Kriptografi Çalışma Grubu, bu kriptografinin kuantum bilgisayarlara karşı uzun süreli koruma için kullanılmasını tavsiye etmiştir ( ref ).
Bunu not et crc32 çarpışma oranı diğerlerine göre daha yüksektir.
Files.hash()
Kullanımdan kaldırıldı olarak işaretlenmiş, tavsiye yoludur:Files.asByteSource(file).hash(Hashing.sha1())
Hashing.sha1()
kullanımdan kaldırıldı. Bunun Hashing.sha256()
yerine işlev önerilir. kaynağı
Nio2 (Java 7+) kullanma ve harici kitaplık kullanma:
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
Sonucu beklenen bir sağlama toplamıyla karşılaştırmak için:
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
Guava şimdi, JDK'da sağlanan çeşitli karma API'lerden çok daha kullanıcı dostu olan yeni, tutarlı bir karma karma API sağlıyor. Bkz. Hashing Açıklaması . Bir dosya için MD5 toplamı, CRC32 (sürüm 14.0+ ile) veya diğer birçok karmayı kolayca alabilirsiniz:
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();
Tamam. Eklemek zorundaydım. Zaten Spring ve Apache Commons bağımlılığı olan veya eklemeyi planlayanlar için bir satır uygulama:
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
Yalnızca ve Apache ortak seçeneği (credit @duleshi):
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Umarım bu birine yardımcı olur.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
size sahip DigestUtils.md5Digest(InputStream inputStream)
MD5 ve hesaplamak için DigestUtils.md5DigestAsHex(InputStream inputStream)
belleğe bir bütün dosyayı okumak olmadan MD5 özeti yöntemlerden onaltılık dize gösterimi için.
Java 7 kullanan üçüncü taraf kitaplıkları olmayan basit bir yaklaşım
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
Bu bayt dizisini yazdırmanız gerekiyorsa. Aşağıdaki gibi kullanın
System.out.println(Arrays.toString(digest));
Bu özetten hex dizgeye ihtiyacınız varsa. Aşağıdaki gibi kullanın
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
burada DatatypeConverter javax.xml.bind.DatatypeConverter
toUpperCase
?
Son zamanlarda bunu sadece dinamik bir dize için yapmak zorunda kaldım MessageDigest
, hash'ı çeşitli şekillerde temsil edebilir. Md5sum komutu ile alacağınız gibi dosyanın imzasını almak için böyle bir şey yapmak zorunda kaldım:
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();
}
Bu açıkça bir dosya için özel olarak nasıl yapılacağı ile ilgili sorunuza cevap vermez, yukarıdaki cevap bu sessizle güzelce ilgilenir. Sadece çoğu uygulamanın görüntülediği gibi görünmesi için çok zaman harcadım ve aynı sorunla karşılaşabileceğinizi düşündüm.
.toString(16)
baştaki sıfırları atacak. String.format("%032x", ...)
belki daha iyi.
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());
}
Veya daha fazla bilgi alabilirsiniz http://www.asjava.com/core-java/java-md5-example/
String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
Önceki bir yazıda yukarıdaki koda benzeyen bir kod kullanıyorduk
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
Ancak, BigInteger.toString()
önde gelen sıfırları keseceği için burada kullanmaya dikkat edin ... (örneğin, deneyin s = "27"
, sağlama toplamı olmalıdır "02e74f10e0327ad868d138f2b4fdd6f0"
)
Apache Commons Codec'i kullanma önerisini ikinci olarak, kendi kodumuzu bununla değiştirdim.
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
}
}
Harici kütüphanelere dayanmayan çok hızlı ve temiz Java yöntemi:
(İsterseniz MD5'i SHA-1, SHA-256, SHA-384 veya SHA-512 ile değiştirmeniz yeterlidir)
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);
}
Başka bir uygulama: Java'da Hızlı MD5 Uygulaması
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
JDK 1.8.0
Standart Java Çalışma Zamanı Ortamı yolu :
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;
}
}
Sonuç linux md5sum yardımcı programına eşittir.
Sunil kodunu saran basit bir işlevdir, böylece bir dosyayı parametre olarak alır. İşlev herhangi bir harici kütüphaneye ihtiyaç duymaz, ancak Java 7 gerektirir.
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);
}
}
Örnek çıktı:
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
Eğer inşa etmek için ANT kullanıyorsanız, bu son derece basittir. Build.xml dosyanıza aşağıdakileri ekleyin:
<checksum file="${jarFile}" todir="${toDir}"/>
JarFile, MD5'i oluşturmak istediğiniz JAR ve toDir, MD5 dosyasını yerleştirmek istediğiniz dizindir.
Google guava yeni bir API sunuyor. Aşağıdakini bulun:
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
İşte InputStream.transferTo()
Java 9 ve OutputStream.nullOutputStream()
Java 11'den yararlanan kullanışlı bir varyasyon. Harici kitaplık gerektirmez ve tüm dosyayı belleğe yüklemeye gerek yoktur.
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()));
}
ve
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
İadeler
"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();
}