2012-03-15 24 views
192

Tôi đã viết một lớp Java đơn giản để tạo ra các giá trị băm của tệp Máy tính Windows. Tôi đang sử dụng Windows 7 Professional with SP1. Tôi đã thử Java 6.0.29Java 7.0.03. Ai đó có thể cho tôi biết lý do tại sao tôi nhận được các giá trị băm khác nhau từ Java so với (nhiều!) Tiện ích bên ngoài và/hoặc các trang web? Mọi thứ bên ngoài khớp với nhau, chỉ có Java trả về các kết quả khác nhau.Các kết quả khác nhau với thông báo của Java so với các tiện ích bên ngoài

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

} 
+0

Tôi đoán toHex của bạn là sai. Nếu bạn làm 'int newElement = ((int) phần tử) & 0xff' và sử dụng thay vào đó sẽ giải quyết vấn đề của bạn? – zapl

+0

@zapl: Điều đó sẽ không thay đổi bất cứ điều gì. –

+63

Song song với tính toán tổng kiểm tra, sao chép tệp vào một tệp tạm thời nào đó, để bạn có thể so sánh những gì Java nhận được với những gì bạn nhận được khi bạn sử dụng các công cụ khác. Windows có thể kỳ quặc như thế ... Tôi chưa bao giờ thấy Java thực hiện một lỗi tính toán băm ... –

Trả lời

238

OK. Hệ thống tệp Windows hoạt động khác nhau tùy thuộc vào kiến ​​trúc của quy trình của bạn. Điều này article explains it all - cụ thể:

Nhưng ứng dụng 32 bit có đường dẫn hệ thống mã hóa cứng và đang chạy trong Windows 64 bit thì sao? Làm thế nào họ có thể tìm thấy thư mục SysWOW64 mới mà không có thay đổi trong mã chương trình, bạn có thể nghĩ. Câu trả lời là giả lập chuyển hướng cuộc gọi đến thư mục System32 đến thư mục SysWOW64 một cách minh bạch để ngay cả khi thư mục được mã hóa cứng vào thư mục System32 (như C: \ Windows \ System32), trình mô phỏng sẽ đảm bảo rằng thư mục SysWOW64 được sử dụng thay thế . Vì vậy, cùng một mã nguồn, sử dụng thư mục System32, có thể được biên dịch thành cả mã chương trình 32 bit và 64 bit mà không có bất kỳ thay đổi nào.

Hãy thử sao chép calc.exe sang một nơi khác ... sau đó chạy lại các công cụ tương tự. Bạn sẽ nhận được kết quả tương tự như Java. Cái gì đó về hệ thống tệp Windows đang cung cấp dữ liệu khác nhau cho các công cụ hơn là cho Java ... Tôi chắc chắn nó liên quan đến nó trong thư mục Windows, và do đó có thể xử lý "khác".

Hơn nữa, tôi đã sao chép nó trong C# ... và phát hiện ra rằng nó phụ thuộc vào kiến ​​trúc của quá trình bạn đang chạy. Vì vậy, đây là một chương trình mẫu:

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

Và đây là một phiên giao diện điều khiển (trừ huyên thuyên từ trình biên dịch):

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 
+9

+1 ... nên người dùng * "Pawel Veselov" * đã đúng;) – TacticalCoder

+0

@TacticalCoder: Yup, có vẻ như vậy. –

+63

Có hai phiên bản 'calc.exe': 64 bit trong' C: \ Windows \ system32 \ 'và 32 bit trong' C: \ Windows \ SysWOW64 \ '. Để tương thích trong quy trình 32 bit, 'C: \ Windows \ system32 \' được ánh xạ tới 'C: \ Windows \ SysWOW64 \'. Các quá trình 64bit sẽ khởi chạy các bit 64bit, 32 bit xử lý các bit 32bit. Không ngạc nhiên khi tổng kiểm tra của họ khác nhau. Nếu bạn giữ tập tin mở và tìm bằng 'handles.exe' hoặc Process Explorer bạn sẽ thấy đường dẫn khác. – Richard

Các vấn đề liên quan