Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify a jar signed with jarsigner programmatically

I'm wanting to sign a jar using jarsigner, then verify it using a Java application which does not have the signed jar as part of it's classpath (i.e. just using a filesystem location of the jar)

Now my problem is getting the signature file out of the jar, is there a simple way to do this?

I've had a play with the Inflater and Jar InputStreams with no luck.

Or is this something that can be accomplished in a better way?

Thanks

like image 313
James Carr Avatar asked Sep 03 '09 15:09

James Carr


People also ask

Is a JAR file signed?

You use the JAR Signing and Verification Tool to sign JAR files and time stamp the signature. You invoke the JAR Signing and Verification Tool by using the jarsigner command, so we'll refer to it as "Jarsigner" for short. To sign a JAR file, you must first have a private key.

How do I know what version of Jacob jar I have?

Decompress the JAR file and look for the manifest file ( META-INF\MANIFEST. MF ). The manifest file of JAR file might contain a version number (but not always a version is specified).


2 Answers

You can simply open the JAR with java.util.jar.JarFile and tell it to verify the JAR file. If the JAR is signed, then JarFile has the option to verify it (which is on by default). However, JarFile will also open unsigned JARs happily, therefore you must also check, whether or not the file is signed. You can do so by checking the JAR's manifest for *-Digest attributes: Elements with such an attribute attribute are signed.

Example:

JarFile jar = new JarFile(new File("path/to/your/jar-file"));  // This call will throw a java.lang.SecurityException if someone has tampered // with the signature of _any_ element of the JAR file. // Alas, it will proceed without a problem if the JAR file is not signed at all InputStream is = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF")); Manifest man = new Manifest(is); is.close();  Set<String> signed = new HashSet(); for(Map.Entry<String, Attributes> entry: man.getEntries().entrySet()) {     for(Object attrkey: entry.getValue().keySet()) {         if (attrkey instanceof Attributes.Name &&             ((Attributes.Name)attrkey).toString().indexOf("-Digest") != -1)             signed.add(entry.getKey());     } }  Set<String> entries = new HashSet<String>(); for(Enumeration<JarEntry> entry = jar.entries(); entry.hasMoreElements(); ) {     JarEntry je = entry.nextElement();     if (!je.isDirectory())         entries.add(je.getName()); }  // contains all entries in the Manifest that are not signed. // Ususally, this contains: //  * MANIFEST.MF itself //  * *.SF files containing the signature of MANIFEST.MF //  * *.DSA files containing public keys of the signer  Set<String> unsigned = new HashSet<String>(entries); unsigned.removeAll(signed);  // contains all the entries with a signature that are not present in the JAR Set<String> missing = new HashSet<String>(signed); missing.removeAll(entries); 
like image 120
nd. Avatar answered Sep 23 '22 00:09

nd.


The security Provider implementation guide outlines the process of verifying JARs. Although these instructions are for a JCA cryptographic service provider to verify itself, they should be applicable to your problem.

Specifically, check out the verify(X509Certificate targetCert) method in the sample code, "MyJCE.java".

like image 37
erickson Avatar answered Sep 23 '22 00:09

erickson