[java] Java의 다이제스트와 외부 유틸리티의 다른 결과

Windows 계산기 파일의 해시 값을 생성하는 간단한 Java 클래스를 작성했습니다. 사용하고 Windows 7 Professional with SP1있습니다. 나는 시도 Java 6.0.29하고 Java 7.0.03. 누군가 Java와 외부 유틸리티 및 / 또는 웹 사이트와 다른 해시 값을 얻는 이유를 말해 줄 수 있습니까? 외부의 모든 것이 서로 일치하며 Java 만 다른 결과를 반환합니다.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.CRC32;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Checksum
{
    private static int size = 65536;
    private static File calc = new File("C:/Windows/system32/calc.exe");

    /*
        C:\Windows\System32\calc.exe (verified via several different utilities)
        ----------------------------
        CRC-32b = 8D8F5F8E
        MD5     = 60B7C0FEAD45F2066E5B805A91F4F0FC
        SHA-1   = 9018A7D6CDBE859A430E8794E73381F77C840BE0
        SHA-256 = 80C10EE5F21F92F89CBC293A59D2FD4C01C7958AACAD15642558DB700943FA22
        SHA-384 = 551186C804C17B4CCDA07FD5FE83A32B48B4D173DAC3262F16489029894FC008A501B50AB9B53158B429031B043043D2
        SHA-512 = 68B9F9C00FC64DF946684CE81A72A2624F0FC07E07C0C8B3DB2FAE8C9C0415BD1B4A03AD7FFA96985AF0CC5E0410F6C5E29A30200EFFF21AB4B01369A3C59B58


        Results from this class
        -----------------------
        CRC-32  = 967E5DDE
        MD5     = 10E4A1D2132CCB5C6759F038CDB6F3C9
        SHA-1   = 42D36EEB2140441B48287B7CD30B38105986D68F
        SHA-256 = C6A91CBA00BF87CDB064C49ADAAC82255CBEC6FDD48FD21F9B3B96ABF019916B
    */

    public static void main(String[] args)throws Exception {
        Map<String, String> hashes = getFileHash(calc);
        for (Map.Entry<String, String> entry : hashes.entrySet()) {
            System.out.println(String.format("%-7s = %s", entry.getKey(), entry.getValue()));
        }
    }

    private static Map<String, String> getFileHash(File file) throws NoSuchAlgorithmException, IOException {
        Map<String, String> results = new LinkedHashMap<String, String>();

        if (file != null && file.exists()) {
            CRC32 crc32 = new CRC32();
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");

            FileInputStream fis = new FileInputStream(file);
            byte data[] = new byte[size];
            int len = 0;
            while ((len = fis.read(data)) != -1) {
                crc32.update(data, 0, len);
                md5.update(data, 0, len);
                sha1.update(data, 0, len);
                sha256.update(data, 0, len);
            }
            fis.close();

            results.put("CRC-32", toHex(crc32.getValue()));
            results.put(md5.getAlgorithm(), toHex(md5.digest()));
            results.put(sha1.getAlgorithm(), toHex(sha1.digest()));
            results.put(sha256.getAlgorithm(), toHex(sha256.digest()));
        }
        return results;
    }

    private static String toHex(byte[] bytes) {
        String result = "";
        if (bytes != null) {
            StringBuilder sb = new StringBuilder(bytes.length * 2);
            for (byte element : bytes) {
                if ((element & 0xff) < 0x10) {
                    sb.append("0");
                }
                sb.append(Long.toString(element & 0xff, 16));
            }
            result = sb.toString().toUpperCase();
        }
        return result;
    }

    private static String toHex(long value) {
        return Long.toHexString(value).toUpperCase();
    }

}



답변

알았다. 프로세스의 아키텍처에 따라 Windows 파일 시스템이 다르게 작동합니다. 이 기사는 특히 다음을 설명합니다 .

그러나 시스템 경로가 하드 코딩되어 있고 64 비트 Windows에서 실행중인 32 비트 응용 프로그램은 어떻습니까? 프로그램 코드를 변경하지 않고 새로운 SysWOW64 폴더를 찾는 방법은 무엇입니까? 대답은 에뮬레이터가 System32 폴더에 대한 호출을 투명하게 SysWOW64 폴더로 리디렉션하므로 폴더가 System32 폴더 (예 : C : \ Windows \ System32)로 하드 코딩 된 경우에도 에뮬레이터는 SysWOW64 폴더가 대신 사용되도록합니다 . 따라서 System32 폴더를 사용하는 동일한 소스 코드를 변경하지 않고 32 비트 및 64 비트 프로그램 코드로 컴파일 할 수 있습니다.

calc.exe다른 곳으로 복사 한 다음 같은 도구를 다시 실행하십시오. Java와 동일한 결과를 얻을 수 있습니다. Windows 파일 시스템에 대해 무언가 가 Java에 제공하는 것과 다른 데이터를 도구에 제공하고 있습니다. Windows 디렉토리에있는 것과 관련이있을 것이므로 아마도 “서로”처리되었을 것입니다.

또한 C #으로 재현했으며 실행중인 프로세스아키텍처에 따라 다릅니다 . 샘플 프로그램은 다음과 같습니다.

using System;
using System.IO;
using System.Security.Cryptography;

class Test
{
    static void Main()
    {
        using (var md5 = MD5.Create())
        {
            string path = "c:/Windows/System32/Calc.exe";
            var bytes = md5.ComputeHash(File.ReadAllBytes(path));
            Console.WriteLine(BitConverter.ToString(bytes));
        }
    }
}

다음은 콘솔 세션입니다 (컴파일러의 채터 빼기).

c:\users\jon\Test>csc /platform:x86 Test.cs

c:\users\jon\Test>test
60-B7-C0-FE-AD-45-F2-06-6E-5B-80-5A-91-F4-F0-FC

c:\users\jon\Test>csc /platform:x64 Test.cs

c:\users\jon\Test>test
10-E4-A1-D2-13-2C-CB-5C-67-59-F0-38-CD-B6-F3-C9


답변