Quick background: We release a webstart application, which includes our own application jars and numerous third-party jars. Webstart requires that all distrib
Seems like a bug in the JRE. Personally I'm assuming the old default signing algorithm (DSA with SHA1 digest) is less secure than the new one (RSA with SHA256 digest), so it's best not to use the "-digestalg SHA1" option.
I solved this problem by using a custom Ant task in my build script to 'unsign' my jars before signing them. That way there is only one signature for each jar.
Here's my Ant task:
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 filesets = new ArrayList();
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);
}
}