似乎是 JRE 中的一个错误。就我个人而言,我假设旧的默认签名算法(带有 SHA1 摘要的 DSA)不如新的(带有 SHA256 摘要的 RSA)安全,所以最好不要使用“-digestalg SHA1”选项。
我通过在我的构建脚本中使用自定义 Ant 任务在签署之前对我的 jar 进行“取消签名”,从而解决了这个问题。这样每个罐子只有一个签名。
这是我的 Ant 任务:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.ResourceUtils;
public class UnsignJar extends Task {
protected List<FileSet> filesets = new ArrayList<FileSet>();
protected File todir;
public void addFileset(final FileSet set) {
filesets.add(set);
}
public void setTodir(File todir) {
this.todir = todir;
}
@Override
public void execute() throws BuildException {
if (todir == null) {
throw new BuildException("todir attribute not specified");
}
if (filesets.isEmpty()) {
throw new BuildException("no fileset specified");
}
Path path = new Path(getProject());
for (FileSet fset : filesets) {
path.addFileset(fset);
}
for (Resource r : path) {
FileResource from = ResourceUtils.asFileResource(r
.as(FileProvider.class));
File destFile = new File(todir, from.getName());
File fromFile = from.getFile();
if (!isUpToDate(destFile, fromFile)) {
unsign(destFile, fromFile);
}
}
}
private void unsign(File destFile, File fromFile) {
log("Unsigning " + fromFile);
try {
ZipInputStream zin = new ZipInputStream(
new FileInputStream(fromFile));
ZipOutputStream zout = new ZipOutputStream(
new FileOutputStream(destFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
if (!entry.getName().startsWith("META-INF")) {
copyEntry(zin, zout, entry);
}
zin.closeEntry();
entry = zin.getNextEntry();
}
zin.close();
zout.close();
} catch (IOException e) {
throw new BuildException(e);
}
}
private void copyEntry(ZipInputStream zin, ZipOutputStream zout,
ZipEntry entry) throws IOException {
zout.putNextEntry(entry);
byte[] buffer = new byte[1024 * 16];
int byteCount = zin.read(buffer);
while (byteCount != -1) {
zout.write(buffer, 0, byteCount);
byteCount = zin.read(buffer);
}
zout.closeEntry();
}
private boolean isUpToDate(File destFile, File fromFile) {
return FileUtils.getFileUtils().isUpToDate(fromFile, destFile);
}
}