Я написал простой Java-класс для генерации хеш-значений файла Windows Calculator. Я использую 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();
}
}
int newElement = ((int) element) & 0xff
и используете вместо этого, это решит вашу проблему?Ответы:
Понял. Файловая система Windows ведет себя по-разному в зависимости от архитектуры вашего процесса. Эта статья объясняет все это, в частности:
Попробуйте скопировать
calc.exe
в другое место ... затем снова запустите те же инструменты. Вы получите те же результаты, что и Java. Что-то в файловой системе Windows дает инструментам данные, отличные от данных для Java ... Я уверен, что это связано с тем, что они находятся в каталоге Windows, и поэтому, вероятно, обрабатываются «по-другому».Кроме того, я воспроизвел его на C # ... и обнаружил, что это зависит от архитектуры процесса, который вы запускаете . Итак, вот пример программы:
А вот консольный сеанс (без болтовни от компилятора):
источник
calc.exe
: 64bit вC:\Windows\system32` and 32bit in
C: \ Windows \ SysWOW64`. Для совместимости в 32-C:\Windows\system32` is mapped to
битном процессе C: \ Windows \ SysWOW64`. 64-разрядные процессы запустят 64-разрядные вычисления, 32-разрядные процессы - 32-разрядные вычисления. Не удивительно, что их контрольные суммы разные. Если вы держите файл открытым и просматриваете с помощьюhandles.exe
или Process Explorer, вы увидите другой путь.