有没有办法从 Maven 构建中获得一致的 MD5 哈希?

Is there any way to get a consistent MD5 Hash from a maven build?

我可以 运行 同一个 Maven 在一组 jar/war 文件上连续构建 5 次,而无需对它们中的任何一个进行任何更改,但我在每个文件上得到了不同的 MD5 哈希值每次 jar/war 个文件。我希望 java 编译器每次都生成相同的散列。是否有任何文件会影响我可以排除的哈希值,以便每次都给我相同的哈希值?还是编译器不是每次都以相同的方式编译相同的代码?

正在使用以下代码生成哈希:

public static String getHash(File file) throws FileNotFoundException, IOException {
    if(file == null || !file.isFile()) {
        return "";
    }
    FileInputStream in = null;
    try {
        in = new FileInputStream(file);
        byte [] bytes = toByteArray(in);
        return getHash(bytes);
    } catch(Exception e) {
        Logging.log("Unable to get MD5 hash for file: " + ile.getName());
    } finally {
        StreamUtils.close(in);
    }
    return "";
}

public static String getHash(byte[] bytes) {
    MessageDigest digest = getMessageDigest();
    byte[] hash = digest.digest(bytes);
    StringBuilder builder = new StringBuilder();
    for (int val : hash) {
        builder.append(Integer.toHexString(val & 0xff));
    }
    return builder.toString();
}

private static MessageDigest getMessageDigest() {
    try {
        return MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

jar 或 war 文件是 zip 文件。一个 zip 文件包含 zip 条目。 zip 条目包含有关文件的元数据,例如创建和修改时间。

您应该将生成的 jar/war 文件的每个文件的内容传递给您的散列,始终以相同的顺序。

试试这个代码,它扫描 jar 中的每个文件并生成一个 MD5 签名

虽然没有优化好

import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class MD5forjar {
    public static String getMD5forjar(String fileName) throws IOException, NoSuchAlgorithmException {
        ZipFile zipFile = new ZipFile(fileName);

        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        MessageDigest sha = MessageDigest.getInstance("md5");

        Map<String, String> fileMap = new HashMap<String, String>();

        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            System.out.println(entry.getName());
            InputStream stream = zipFile.getInputStream(entry);
            DigestInputStream dig = new DigestInputStream(stream, sha);
            byte[] buffer = new byte[4096];
            int count = 0;
            while (dig.read(buffer) > -1) {
                count++;
            }
            MessageDigest digest = dig.getMessageDigest();
            dig.close();
            byte[] md5 = digest.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : md5) {
                sb.append(String.format("%02X", b));
            }
            String checkSum = sb.toString();
            fileMap.put(entry.getName(), checkSum);
        }
        SortedSet<String> sorted = new TreeSet<String>(fileMap.keySet());
        StringBuffer buff = new StringBuffer();
        for (String key : sorted) {
            System.out.println(key);
            if (!key.endsWith("pom.properties"))
                buff.append(fileMap.get(key));
        }
        MessageDigest md = MessageDigest.getInstance("md5");
        md.update(buff.toString().getBytes());

        byte[] digest = md.digest();
        StringBuffer sb = new StringBuffer();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }

        return sb.toString();
    }
}