Using the example below, I obtained the expected result for a correctly signed JAR (true
) and an altered JAR (false
). One simple way to trigger the effect for testing is to change one of the digests listed in META-INF/MANIFEST.MF
.
Note that this approach ignores entries that are not listed in the manifest. Using jarsigner -verify
reports, "This jar contains unsigned entries which have not been integrity-checked." After reading the stream completely, entry.getCodeSigners()
may be used to determine if an entry has any signers.
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/** @see http://stackoverflow.com/questions/5587656 */
public class Verify {
public static void main(String[] args) throws IOException {
System.out.println(verify(new JarFile(args[0])));
}
private static boolean verify(JarFile jar) throws IOException {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
try {
byte[] buffer = new byte[8192];
InputStream is = jar.getInputStream(entry);
while ((is.read(buffer, 0, buffer.length)) != -1) {
// We just read. This will throw a SecurityException
// if a signature/digest check fails.
}
} catch (SecurityException se) {
return false;
}
}
return true;
}
}
Note: For JDK 8, its not enough to merely get the input stream. As in jarsigner
, the stream must be read from, too. In the code above, a loop adapted from the jar signer
source has been added after getting the input stream.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…