2012-03-15 24 views
192

Napisałem prostą klasę Java, aby wygenerować wartości mieszania pliku kalkulatora Windows. Używam Windows 7 Professional with SP1. Próbowałem Java 6.0.29 i Java 7.0.03. Czy ktoś może mi powiedzieć, dlaczego otrzymuję różne wartości mieszania z Java w porównaniu do (wielu!) Zewnętrznych narzędzi i/lub stron internetowych? Wszystko zewnętrzne pasuje do siebie, tylko Java zwraca różne wyniki.Różne wyniki z wykorzystaniem języka Java w porównaniu z narzędziami zewnętrznymi

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

Chyba Twój toHex jest źle. Jeśli użyjesz 'int newElement = ((int) element) & 0xff' i użyjesz zamiast tego, że to rozwiąże twój problem? – zapl

+0

@zapl: To niczego nie zmieniłoby. –

+63

Równolegle do obliczania sumy kontrolnej, skopiuj plik do jakiegoś pliku tymczasowego, abyś mógł porównać to, co Java uzyska z tym, co otrzymujesz, kiedy używasz innych narzędzi. Windows może być dziwny ... Nigdy nie widziałem, żeby Java popełniła błąd, obliczając hasze ... –

Odpowiedz

238

Rozumiem. System plików Windows zachowuje się inaczej w zależności od architektury procesu. To article explains it all - w szczególności:

Ale co z aplikacjami 32-bitowymi, które mają ścieżkę systemową zakodowaną na stałe i działającą w 64-bitowym systemie Windows? Jak mogą znaleźć nowy folder SysWOW64 bez zmian w kodzie programu, możesz pomyśleć. Odpowiedź jest taka, że ​​emulator przekierowuje wywołania do folderu System32 do folderu SysWOW64 w sposób przezroczysty, więc nawet jeśli folder jest zakodowany na stałe w folderze System32 (jak C: \ Windows \ System32), emulator upewni się, że zamiast niego używany jest folder SysWOW64 . Tak samo kod źródłowy, który używa folderu System32, może być kompilowany zarówno do 32-bitowego, jak i 64-bitowego kodu programu bez żadnych zmian.

Spróbuj skopiować calc.exe gdzie indziej ... a następnie uruchom ponownie te same narzędzia. Otrzymasz te same wyniki co Java. Coś o o systemie plików Windows daje inne dane narzę dzia niż daje Java ... Jestem pewien, że ma to jakĘ ... zwiĘ ... zek z tym, że jest w katalogu Windows, a wię c prawdopodobnie obsługiwane "inaczej".

Co więcej, udało mi się go odtworzyć w języku C# ... i odkryłem, że to zależy od architektury procesu, który używasz,. Więc oto przykładowy program:

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

A oto sesja konsoli (minus gadać od kompilatora):

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 ... więc użytkownik * "Paweł Veselov" * miał rację;) – TacticalCoder

+0

@ TacticalCoder: Tak, wygląda na to. –

+63

Istnieją dwie wersje 'calc.exe': 64-bitowe w' C: \ Windows \ system32 \ 'i 32-bitowe w' C: \ Windows \ SysWOW64 \ '. Dla kompatybilności w procesie 32-bitowym 'C: \ Windows \ system32 \' jest zamapowany na 'C: \ Windows \ SysWOW64 \'. Procesy 64-bitowe uruchamiają 64-bitowy calc, 32-bitowy przetwarza 32-bitowy calc. Nic dziwnego, że ich sumy kontrolne są różne. Jeśli trzymasz plik otwarty i wyglądasz za pomocą 'handles.exe' lub Process Explorer zobaczysz inną ścieżkę. – Richard