当前位置: 首页 > 面试题库 >

Java摘要与外部实用程序的结果不同

阚允晨
2023-03-14
问题内容

我编写了一个简单的Java类来生成Windows计算器文件的哈希值。我正在使用Windows 7 Professional with SP1。我曾尝试Java 6.0.29Java 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


 类似资料:
  • 问题内容: 我想从Java应用程序启动外部第三方应用程序。我的Java应用程序运行时,此外部应用程序应始终运行。 从时间到时间(这取决于用户交互)我的Java应用程序应该能够通过阅读和写这个外部应用程序和。 我怎样才能做到这一点? 问题答案: 是前应用程序本机代码还是其他Java程序?如果是本机代码,请查看http://download.oracle.com/javase/1.5.0/docs/a

  • 问题内容: 我是java的新手,我的问题是,按下键后输出显示2个数字,但我不明白为什么。 这是代码: 问题答案: 尽管我不能重现该问题:(请参阅此处),但我的建议是也打印出字符(作为整数)。这将帮助您调试:

  • 问题内容: 我知道这个问题在前面已经问过了,但是我仍然无法弄清楚Jmeter摘要报告中参数的意义是什么? 这是JMeter的设置: 那么这是否意味着我的5k请求完成了738毫秒(0.7 s)的时间?还是意味着每个请求都需要0.7秒才能完成?类似地,最小和最大参数的解释是什么。 问题答案: 大约平均值-738或0.7s意味着,例如,如果您有一个带有两个线程的请求,而第一个线程在0.9s内完成,第二个

  • 问题内容: 我试图制作一个调用外部程序的应用程序,我必须传递两个参数。它没有任何错误。用c ++编写的program.exe可以拍照并修改txt文件的内容。Java程序可以运行,但是什么也没做 这是我的示例代码 问题答案: 从这里可耻地借来的

  • 问题内容: 我可能很快就会教“ Java速成课程”。虽然可以很安全地假设受众成员知道Big-O表示法,但是假设他们将知道各种集合实现上的各种操作的顺序可能是不安全的。 我可能会花一些时间自己生成一个摘要矩阵,但是如果它已经存在于公共领域中的某个地方,我肯定会重用它(当然要有适当的信誉)。 有人有指针吗? 问题答案: 我可能很快就会教“ Java速成课程”。虽然可以很安全地假设受众成员知道Big-O

  • Hash 算法 定义 Hash (哈希或散列)算法是信息技术领域非常基础也非常重要的技术。它能任意长度的二进制值(明文)映射为较短的固定长度的二进制值(Hash 值),并且不同的明文很难映射为相同的 Hash 值。 例如计算一段话“hello blockchain world, this is yeasy@github”的 MD5 hash 值为 89242549883a2ef85dc81b90f