Java를 사용하여 파일의 MD5 체크섬을 얻으려고합니다. 정말 놀랐지 만 파일의 MD5 체크섬을 얻는 방법을 보여주는 것을 찾을 수 없었습니다.
어떻게 되나요?
Java를 사용하여 파일의 MD5 체크섬을 얻으려고합니다. 정말 놀랐지 만 파일의 MD5 체크섬을 얻는 방법을 보여주는 것을 찾을 수 없었습니다.
어떻게 되나요?
답변:
입력 스트림 데코레이터 java.security.DigestInputStream
가있어 데이터를 추가로 전달하지 않고 입력 스트림을 정상적으로 사용하면서 다이제스트를 계산할 수 있습니다.
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
로 선언 했습니까 ? 사용한 것처럼 들리므로이 오류가 발생합니다. InputStream
FileInputStream
FileInputStream
MethodNotFound
에서는 제대로 작동합니다 . 표준 Java에서는 예외가 아닙니다. 아마도 컴파일러 오류에 대해 이야기하고 있습니까? 어쨌든 작동하지 않으면 로컬 구성 문제 또는 다른 코드 문제입니다.
Apache Commons 코덱 라이브러리 에서 DigestUtils 를 사용하십시오 .
try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}
commons-codec.jar
클래스 경로에 이미 넣었다고 가정 하십니까?
MessageDigest 클래스 를 사용 하는 Real의 Java-How-to 예제가 있습니다 .
CRC32 및 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()
0을 반환하지 않으며 a do/while
는 실제로 적절하지 않습니다.
com.google.common.hash의 API 제공 :
사용자 안내서 ( IO Explained , Hashing Explained )를 읽으십시오 .
사용 사례의 경우 Files.hash()
파일의 다이제스트 값을 계산하고 반환합니다.
예를 들어 샤 -1 다이제스트 계산 (MD-1 다이제스트를 얻기 위해 SHA-1을 MD5로 변경)
HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();
참고 crc32 보다 훨씬 빠르다 md5그래서 사용하십시오 crc32암호로 안전한 체크섬이 필요하지 않은 경우 또한md5 암호 사용을 위해 무차별 대입하기 쉽기 때문에 암호 등을 저장하는 데 사용해서는 안됩니다 막다, 암호화 또는 샤 -256 대신에.
해시를 사용한 장기 보호의 경우 Merkle 서명 체계 가 보안에 추가되며 유럽위원회가 후원하는 Post Quantum Cryptography Study Group은 양자 컴퓨터 ( ref ) 에 대한 장기 보호를 위해이 암호화를 사용할 것을 권장했습니다 .
참고 crc32 다른 것보다 충돌 률이 높습니다.
Files.hash()
되지 않는 것으로 표시되면, 권장되는 방법은 다음과 같습니다Files.asByteSource(file).hash(Hashing.sha1())
외부 라이브러리없이 nio2 (Java 7+) 사용 :
byte[] b = Files.readAllBytes(Paths.get("/path/to/file"));
byte[] hash = MessageDigest.getInstance("MD5").digest(b);
결과를 예상 체크섬과 비교하려면
String expected = "2252290BC44BEAD16AA1BF89948472E8";
String actual = DatatypeConverter.printHexBinary(hash);
System.out.println(expected.equalsIgnoreCase(actual) ? "MATCH" : "NO MATCH");
구아바는 이제 JDK에서 제공되는 다양한 해싱 API보다 훨씬 사용자 친화적 인 새롭고 일관된 해싱 API를 제공합니다. 해싱 설명을 참조하십시오 . 파일의 경우 MD5 합계, CRC32 (버전 14.0 이상) 또는 기타 여러 해시를 쉽게 얻을 수 있습니다.
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();
확인. 나는 추가해야했다. Spring과 Apache Commons에 이미 의존하거나 추가 할 계획 인 사람들을위한 한 줄 구현 :
DigestUtils.md5DigestAsHex(FileUtils.readFileToByteArray(file))
For Apache Apache Commons Only 옵션 (credit @duleshi) :
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
이것이 누군가를 돕기를 바랍니다.
DigestUtils.md5Hex(FileUtils.readFileToByteArray(file))
Spring 5
당신이 DigestUtils.md5Digest(InputStream inputStream)
는 MD5 다이제스트 계산하기 위해 DigestUtils.md5DigestAsHex(InputStream inputStream)
메모리에 전체 파일을 읽을없이 MD5 다이제스트 방법의 진수 문자열 표현을.
Java 7을 사용하는 타사 라이브러리가없는 간단한 접근 방식
String path = "your complete file path";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(Files.readAllBytes(Paths.get(path)));
byte[] digest = md.digest();
이 바이트 배열을 인쇄해야하는 경우 아래와 같이 사용
System.out.println(Arrays.toString(digest));
이 다이제스트에서 16 진수 문자열이 필요한 경우. 아래와 같이 사용
String digestInHex = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println(digestInHex);
여기서 DatatypeConverter는 javax.xml.bind.DatatypeConverter입니다.
toUpperCase
?
나는 최근에 동적 문자열에 대해이 작업을 수행해야 MessageDigest
했으며 여러 가지 방법으로 해시를 나타낼 수 있습니다. md5sum 명령 을 사용하여 파일의 서명을 얻으려면 다음과 같이해야합니다.
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();
}
이것은 분명히 파일에 대해 구체적으로 수행하는 방법에 대한 귀하의 질문에 대답하지는 않지만 위의 대답은 그 조용히 잘 처리합니다. 방금 대부분의 응용 프로그램이 표시하는 것처럼 합계를 얻는 데 많은 시간을 보냈으며 동일한 문제가 발생할 수 있다고 생각했습니다.
.toString(16)
선행 0을 버릴 것입니다. String.format("%032x", ...)
더 나을 수 있습니다.
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());
}
또는 더 많은 정보를 얻을 수 있습니다 http://www.asjava.com/core-java/java-md5-example/
우리는 이전 게시물에서 위의 코드와 유사한 코드를 사용했습니다.
...
String signature = new BigInteger(1,md5.digest()).toString(16);
...
그러나 BigInteger.toString()
앞에 0을 자르므로 여기에서 사용 하십시오. (예를 들어, try s = "27"
, checksum이어야 함 "02e74f10e0327ad868d138f2b4fdd6f0"
)
Apache Commons Codec을 사용하라는 제안을 두 번째로, 우리 자신의 코드를 그 코드로 대체했습니다.
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
}
}
외부 라이브러리에 의존하지 않는 매우 빠르고 깨끗한 Java 메소드 :
(원하는 경우 MD5를 SHA-1, SHA-256, SHA-384 또는 SHA-512로 간단히 교체하십시오)
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);
}
다른 구현 : Java에서 빠른 MD5 구현
String hash = MD5.asHex(MD5.getHash(new File(filename)));
MD5.asHex()
JDK 1.8.0 242에서 방법 을 찾을 수 없습니다.
표준 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;
}
}
결과는 Linux md5sum 유틸리티와 같습니다.
다음은 Sunil의 코드를 감싸서 File을 매개 변수로 사용하는 간단한 함수입니다. 이 함수에는 외부 라이브러리가 필요하지 않지만 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);
}
}
출력 예 :
hex=B117DD0C3CBBD009AC4EF65B6D75C97B
ANT를 사용하여 빌드하는 경우 이는 매우 간단합니다. build.xml에 다음을 추가하십시오.
<checksum file="${jarFile}" todir="${toDir}"/>
여기서 jarFile은 MD5를 생성하려는 JAR이고 toDir은 MD5 파일을 배치하려는 디렉토리입니다.
구글 구아바는 새로운 API를 제공합니다. 아래에서 하나를 찾으십시오.
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
다음은 InputStream.transferTo()
Java 9 및 OutputStream.nullOutputStream()
Java 11 을 사용하는 편리한 변형입니다 . 외부 라이브러리가 필요하지 않으며 전체 파일을 메모리에로드 할 필요가 없습니다.
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()));
}
과
hashFile("SHA-512", Path.of("src", "test", "resources", "some.txt").toFile());
보고
"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();
}