web-dev-qa-db-fra.com

Résultats différents avec le résumé de Java par rapport aux utilitaires externes

J'ai écrit une classe Java simple pour générer les valeurs de hachage du fichier Windows Calculator. J'utilise Windows 7 Professional with SP1. J'ai essayé Java 6.0.29 Et Java 7.0.03. Quelqu'un peut-il me dire pourquoi j'obtiens des valeurs de hachage différentes de Java par rapport à (beaucoup!) D'utilitaires externes et/ou de sites Web? Tout ce qui est externe correspond, seul Java renvoie des résultats différents.

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

}
195
Mike Viens

Je l'ai. Le système de fichiers Windows se comporte différemment selon l'architecture de votre processus. Ceci l'article explique tout - en particulier:

Mais qu'en est-il des applications 32 bits dont le chemin système est codé en dur et qui s'exécutent dans un Windows 64 bits? Comment peuvent-ils trouver le nouveau dossier SysWOW64 sans changements dans le code du programme, vous pourriez penser. La réponse est que l'émulateur redirige les appels vers le dossier System32 vers le dossier SysWOW64 de manière transparente, donc même si le dossier est codé en dur vers le dossier System32 (comme C:\Windows\System32), l'émulateur s'assurera que le dossier SysWOW64 est utilisé à la place . Par conséquent, le même code source, qui utilise le dossier System32, peut être compilé en code de programme 32 bits et 64 bits sans aucune modification.

Essayez de copier calc.exe vers ailleurs ... puis exécutez à nouveau les mêmes outils. Vous obtiendrez les mêmes résultats que Java. Quelque chose sur le système de fichiers Windows donne aux outils des données différentes de celles qu'ils donnent à Java ... Je suis sûr que c'est quelque chose à voir avec cela dans le répertoire Windows, et donc probablement traité "différemment".

De plus, je l'ai reproduit en C # ... et j'ai découvert que cela dépend de l'architecture du processus que vous exécutez . Voici donc un exemple de programme:

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

Et voici une session de console (sans bavardage du compilateur):

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
240
Jon Skeet