有没有办法从 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();
}
}
我可以 运行 同一个 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();
}
}