确定性地创建.jar文件(每次都相同)

时间:2016-09-18 04:34:49

标签: java ant jar zip md5

我使用jar命令来构建jar文件。在尝试使用md5签名缓存jar文件时,我发现从完全相同的源构建的jar具有不同的md5签名。经过仔细检查,我发现每次创建jar时内容都完全相同(diff -qr为空)。事实证明,创建的时间戳在jar文件中编码,该文件抛出了md5签名。其他人发现了相同的内容:Java/zip: Why are .jar files non-deterministically created?

甚至还有关于如何使用maven创建jar文件的博客文章:http://gary-rowe.com/agilestack/2013/08/08/how-to-create-a-deterministic-jar。但是,我想要一个简单的解决方案,使用命令行使用现成的命令,如jar和zip(可能必须在没有安装权限的服务器上执行此操作),可能导致与我目前使用的相同的“功能”jar jar命令。

编辑:就我的目的而言,快速找到md5也足以让它在整个版本中相同,即使这些jar不相同也是如此。到目前为止,我找到的唯一方法是提取jar中的文件和md5所有组件文件。但我担心大罐子的速度会慢,并且会打破缓存它们的目的,以避免首先构建它们。有更好更快的解决方案吗?

2 个答案:

答案 0 :(得分:0)

主要问题是jar命令总是用当前时间创建META-INF\MANIFEST.MF。 文件时间保存在zip条目标题中。这就是 MD5 值不同的原因,即使jar中的所有文件内容都保持不变: 不同的zip条目标题生成不同的zip文件。

对于jar命令,唯一的解决方案是选项-M:不为条目创建清单文件。

答案 1 :(得分:0)

Jar命令始终使用当前时间创建META-INF \ MANIFEST.MF。 Zip存储带有时间戳和文件属性的文件,这是因为两个工件的sha256或MD5会有所不同。

我们需要确保创建,最后修改,访问的时间戳和文件属性始终与创建jar或zip所需的所有文件相同。

我创建了下面的脚本,该脚本可以获取jar或zip文件,并通过使时间戳记恒定并设置正确的压缩级别和偏移来使其具有确定性。

#!/bin/bash

usage() {
    echo "Usage : ./createDeterministicArtifact.sh <zip/jar file name>"
    exit 1
}

info() {
    echo "$1"
}

strip_artifact() {
    if [ -z ${file} ]; then
        usage
    fi
    if [ -f ${file} -a -s ${file} ]; then
        mkdir -p ${file}.tmp
        unzip -oq -d ${file}.tmp ${file}
        find ${file}.tmp -follow -exec touch -a -m -t 201912010000.00 {} \+
        if [ "$UNAME" == "Linux" ] ; then
            find ${file}.tmp -follow -exec chattr -a {} \+
        elif [[ "$UNAME" == CYGWIN* || "$UNAME" == MINGW* ]] ; then
            find ${file}.tmp -follow -exec attrib -A {} \+
        fi
        cd ${file}.tmp
        zip -rq -D -X -9 -A --compression-method deflate  ../${file}.new . 
        cd -
        rm -rf ${file}.tmp
        info "Recreated deterministic artifact: ${file}.new"
    else 
        info "Input file is empty. Please validate the file and try again"
    fi
}

file=$1