Programing

Java에서 파일의 MD5 체크섬 가져 오기

lottogame 2020. 2. 14. 21:53
반응형

Java에서 파일의 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();

Apache Commons 코덱 라이브러리 에서 DigestUtils사용하십시오 .

try (InputStream is = Files.newInputStream(Paths.get("file.zip"))) {
    String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is);
}

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();
       }
   }
}

com.google.common.hash의 API 제공 :

  • 모든 해시 함수를위한 통합 된 사용자 친화적 API
  • murmur3의 시드 가능한 32 비트 및 128 비트 구현
  • md5 (), sha1 (), sha256 (), sha512 () 어댑터는 한 줄의 코드 만 변경하여 이들 사이를 전환합니다.
  • goodFastHash (int bits), 사용하는 알고리즘에 신경 쓰지 않을 때
  • CombineOrdered / CombineUnorder와 같은 HashCode 인스턴스의 일반 유틸리티

사용자 안내서 ( IO Explained , Hashing Explained )를 읽으십시오 .

유스 케이스의 경우 Files.hash()파일의 다이제스트 값을 계산하고 리턴합니다.

예를 들어 다이제스트 계산 (MD5 다이제스트를 얻으려면 SHA-1을 MD5로 변경)

HashCode hc = Files.asByteSource(file).hash(Hashing.sha1());
"SHA-1: " + hc.toString();

참고 것보다 훨씬 빠르기 때문에 를 사용하므로, 당신이 암호 보안 검사가 필요하지 않은 경우. 또한 를 사용하면 암호를 쉽게 입력 할 수 있으므로 암호를 저장하는 데 사용해서는 안됩니다. 암호의 경우 , 또는 대신 사용하십시오.

해시를 사용한 장기 보호의 경우 Merkle 서명 체계 가 보안에 추가되며 유럽위원회가 후원하는 Post Quantum Cryptography Study Group은 양자 컴퓨터 ( ref ) 에 대한 장기 보호를 위해이 암호화를 사용할 것을 권장했습니다 .

참고 다른 사람보다 높은 충돌 속도를 가지고있다.


외부 라이브러리없이 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))

이것이 누군가를 돕기를 바랍니다.


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입니다.


나는 최근에 동적 문자열에 대해이 작업을 수행해야 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();
}

이것은 분명히 파일에 대해 구체적으로 수행하는 방법에 대한 귀하의 질문에 대답하지는 않지만 위의 대답은 그 조용히 잘 처리합니다. 방금 대부분의 응용 프로그램에서 표시되는 것처럼 합계를 얻는 데 많은 시간을 보냈으며 동일한 문제가 발생할 수 있다고 생각했습니다.


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);
}

String checksum = DigestUtils.md5Hex(new FileInputStream(filePath));

다른 구현 : Java에서 빠른 MD5 구현

String hash = MD5.asHex(MD5.getHash(new File(filename)));

표준 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 유틸리티와 같습니다.


다음은 File을 매개 변수로 사용하도록 Sunil의 코드를 감싸는 간단한 함수입니다. 이 함수에는 외부 라이브러리가 필요하지 않지만 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

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();
}

다음은 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"

참고 URL : https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java



반응형