Is there a way to unsign a java jar file? I have some signed jars I'm trying to use in my development environment, but I get security exceptions, so I want to unsign those jars and I can sign them later when I'm ready to deploy.
-
You checked e.g. this: https://www.chemaxon.com/forum/ftopic65.html? – home Oct 13 '11 at 16:16
-
Where do the jars in question come from? Why can't you sign in your development environment? – Karl Knechtel Oct 13 '11 at 16:20
-
2Apparently there's a way. ;-) However, why not just avoid signing the JAR during development? If you're the one in control of the JAR this should be in your power; if you're not the one in control of the JAR you're probably not meant to be tampering with it (or the original developer wouldn't have signed it). – Greg Pettit Oct 13 '11 at 16:33
-
So yeah, the jars are mine or unsigned jars from Maven and other sources. I have since modified my build system, so it is unclear if this is still a problem... I certainly haven't encountered a need to do this in over a year. – Jason Sep 18 '15 at 13:51
7 Answers
I don't know the answer, but here is what I would do:
- Unzip the jar file or files in question (jars are just zips)
- Look in the META-INF directory for something that was not MANIFEST-MF.
- Delete that stuff.
- Open the MANIFEST-MF and remove stuff that looked like it was signature related.
- rejar.

- 37,124
- 11
- 56
- 82
-
-
That's what I had to do and I never found a way to just remove the signature without unzipping. I would like, however, if this answer was more specific about steps 2,3,4 because sometimes there are things other than MANIFEST-MF that are required and not signature related. Like APPLICATION.JNLP! – Jason Oct 21 '13 at 17:15
-
For googlers, Netbeans said : "Not adding security attributes into library", "the library is already signed", so unsign and sign it, this answer solved the problem! – Hernán Eche Feb 18 '15 at 15:01
-
I posted an answer in this thread, containing a sourcecode to do this for you. Hope it helps. Cheers – Houtman Dec 18 '15 at 09:41
-
If you look at the jarsigner tool and what it does, it generates 3 things: 1) the .SF file (signature file), 2) a signature block file based on the algorithm used (e.g. .RSA, .DSA, etc.) 3) modification or creation of a MANIFEST.MF file So, if you delete EVERYTHING in the META-INF directory you run the risk of deleting other resources of the jar that might be needed (i.e. property files, etc.) see here: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html – atom88 May 23 '17 at 19:07
To remove the signature from a jar file, remove the META-INF
directory from it. A jar file is a zip file so on Linux you can do this:
zip -d file.jar 'META-INF/*.SF' 'META-INF/*.RSA'
If you have many jar files to unsign, the following command performs this on every jar file in the current directory and below:
find . -name '*.jar' -exec zip -d '{}' 'META-INF/*.SF' 'META-INF/*.RSA' ';'

- 1,133
- 8
- 18
-
1I think you also have to edit `META-INF/MANIFEST.MF` don't you? Or can you leave the signatures in that file and have the jar still work as unsigned? – Jason Sep 17 '15 at 13:57
-
1
-
Thanks for checking, I up-voted. I have not verified this for myself and am still skeptical that it works in all cases. I hope you don't mind my skepticism :-) The solution is nice and would be a more satisfactory answer to my question if it works in my case... whenever I come across this again I will test it and update this answer. – Jason Sep 18 '15 at 13:48
-
Both these commands worked in my case for all the 3rd party jars referenced by my build file. I tweaked the `find` command with `-not -path` to exclude certain directories. – amos Mar 07 '16 at 14:48
-
1This solution does not work. It is important to delete the signing information in `META-INF/MANIFEST.MF` – Jason Jun 22 '16 at 19:56
-
1From the jarsigner tool documentation it does this: 1) the .SF file (signature file) 2) a signature block file based on the algorithm used (e.g. .RSA, .DSA, etc.) 3) modification (or creation of if it doesn't yet exist) a MANIFEST.MF file Summary: just delete the first 2 files and either delete the MANIFEST.MF file, or open it up and delete all of the Hashes listed for each files listed there). Otherwise you will delete other needed files (i.e. property files, etc.). References: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html – atom88 May 23 '17 at 19:28
I see an answer is already accepted, but i think this might be usefull anyway:
i've cooked up something (partly from other posts) to automate the task.
Comes with No warranty whatsoever, but it works for me :)
Copies the Jar file while removing the signature information.
Note, the MANIFEST is only left with the MAIN section!
Use javac JarUnsigner.java
to create the .class file
Use java -cp <class dir> JarUnsigner <inJar> <outJar>
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class JarUnsigner {
private static final String MANIFEST = "META-INF/MANIFEST.MF";
public static void main(String[] args){
if (args.length!=2){
System.out.println("Arguments: <infile.jar> <outfile.jar>");
System.exit(1);
}
String infile = args[0];
String outfile = args[1];
if ((new File(outfile)).exists()){
System.out.println("Output file already exists:" + outfile);
System.exit(1);
}
try{
ZipFile zipFile = new ZipFile(infile);
final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outfile));
for (Enumeration e = zipFile.entries(); e.hasMoreElements();) {
ZipEntry entryIn = (ZipEntry) e.nextElement();
if (! exclude_file( entryIn.getName() ) ) {
/* copy the entry as-is */
zos.putNextEntry( new ZipEntry( entryIn.getName() ));
InputStream is = zipFile.getInputStream(entryIn);
byte[] buf = new byte[1024];
int len;
while ((len = (is.read(buf))) > 0) {
zos.write(buf, 0, len);
}
zos.closeEntry();
} else {
if (MANIFEST.equals(entryIn.getName())){
/* if MANIFEST, adjust the entry */
zos.putNextEntry(new ZipEntry(MANIFEST));
// manifest entries until first empty line. i.e. the 'MainAttributes' section
// (this method is used so to keep the formatting exactly the same)
InputStream mIS = zipFile.getInputStream(entryIn);
BufferedReader in = new BufferedReader(new InputStreamReader(mIS));
String line = in.readLine();
byte[] mNL = "\n".getBytes("UTF-8");
while( line != null && !line.trim().isEmpty() ) {
zos.write( line.getBytes("UTF-8"));
zos.write( mNL );
line = in.readLine();
}
zos.write( mNL );
zos.closeEntry();
}else{
/* else: Leave out the Signature files */
}
}
}
zos.close();
System.out.println("Successfully unsigned " + outfile);
}catch(IOException ex){
System.err.println("Error for file: " + infile);
ex.printStackTrace();
System.exit(1);
}
}
/**
* Exclude .SF signature file
* Exclude .RSA and DSA (signed version of .SF file)
* Exclude SIG- files (unknown sign types for signed .SF file)
* Exclude Manifest file
* @param filename
* @return
*/
public static boolean exclude_file(String filename){
return filename.equals("META-INF/MANIFEST.MF") ||
filename.startsWith("META-INF/SIG-") ||
filename.startsWith("META-INF/") && ( filename.endsWith(".SF") || filename.endsWith(".RSA") || filename.endsWith(".DSA") );
}
}
Use in ANT to unsign a bunch of jars as follows:
<apply executable="java" dest="${output-dir}">
<arg value="-cp" />
<arg value="${dev-dir}" />
<arg value="JarUnsigner" />
<srcfile/>
<targetfile/>
<fileset dir="${input-dir}" includes="*.jar"/>
<mapper type="glob" from="*.jar" to="*.jar"/> <!-- uses "dest"-->
</apply>

- 2,534
- 1
- 28
- 25

- 2,819
- 2
- 24
- 34
-
Great idea! I haven't tested it, but I'm upvoting to draw some attention and see if someone else has the time to test this solution. This would be exactly what I'd want. – Jason Jun 22 '16 at 19:39
-
I successfully verified DwB's answer with small modification: As Is there a quick way to delete a file from a Jar / war without having to extract the jar and recreate it? states, deleting just from jar tool is not possible. I needed to make only small change in proprietary build script and I didn't want to rejar whole jar.
I realized unsign was possible when I only made important .RSA file zero-sized. This can be accomplished only with jar u
command:
cd %JAR_DIR%
jar xvf myapp.jar META-INF/MYAPP.RSA
type nul > META-INF/MYAPP.RSA
jar uvf myapp.jar META-INF/MYAPP.RSA
rmdir /S/Q META-INF

- 1
- 1

- 10,735
- 2
- 36
- 64
-
-
From the jarsigner tool documentation it does this: 1) the .SF file (signature file) 2) a signature block file based on the algorithm used (e.g. .RSA, .DSA, etc.) 3) modification (or creation of if it doesn't yet exist) a MANIFEST.MF file Summary: just delete the first 2 files and either delete the MANIFEST.MF file, or open it up and delete all of the Hashes listed for each files listed there). Otherwise you will delete other needed files (i.e. property files, etc.). References: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html – atom88 May 23 '17 at 19:28
If you look at the jarsigner tool and what it does, it generates 3 things: 1) the .SF file (signature file) 2) a signature block file based on the algorithm used (e.g. .RSA, .DSA, etc.) 3) modification or creation of a MANIFEST.MF file
Summary: To "unsign a jar" just delete the first 2 files (.sf and .dsa/rsa FILE). Either delete the MANIFEST.MF file, or open it up and delete all of the Hashes listed for each .class and other file listed there).
So, if you delete EVERYTHING in the META-INF directory you run the risk of deleting other resources of the jar that might be needed (i.e. property files, etc.). This "shotgun approach" of deleting everything that "looks signature related" is harmful and doesn't follow the principle of: 1st do no harm (to your .jar).
see here: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html
https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html
Understanding Signing and Verification
"...When you sign a JAR file your public key is placed inside the archive along with an associated certificate so that it's easily available for use by anyone wanting to verify your signature.... Digests and the Signature File
When you sign a JAR file, each file in the archive is given a digest entry in the archive's manifest. Here's an example of what such an entry might look like:
Name: test/classes/ClassOne.class SHA1-Digest: TD1GZt8G11dXY2p4olSZPc5Rj64=
When a JAR file is signed, a signature file is automatically generated and placed in the JAR file's META-INF directory, the same directory that contains the archive's manifest. Signature files have filenames with an .SF extension.
The Signature Block File
In addition to the signature file, a signature block file is automatically placed in the META-INF directory when a JAR file is signed. Unlike the manifest file or the signature file, signature block files are not human-readable.
The signature block file contains two elements essential for verification:
The digital signature for the JAR file that was generated with the signer's private key The certificate containing the signer's public key, to be used by anyone wanting to verify the signed JAR file Signature block filenames typically will have a .DSA extension indicating that they were created by the default Digital Signature Algorithm. Other filename extensions are possible if keys associated with some other standard algorithm are used for signing.

- 1,449
- 3
- 22
- 32
Another variant, that edits MANIFEST.MF too, ie deletes everything from the first empty line (edit the 'jarlocation' and 'signer' parts to your case):
Tmpdir=tmp.$$
mkdir -p "$Tmpdir"
cd "$Tmpdir"
for i in <jarlocation>/*.jar; do \
printf 'Doing %s\n' "$i"
unzip "$i" 'META-INF/*'
sed -i '/^[[:space:]]*$/,$d' META-INF/MANIFEST.MF
zip -r "$i" META-INF/MANIFEST.MF
test -f META-INF/<signer>.SF && zip -d "$i" 'META-INF/<signer>.*'
rm -rf META-INF
done
cd ..
rm -rf "$Tmpdir"
printf 'Unsigning finished\n'

- 1,749
- 1
- 14
- 21
If the jars were developed by you then, they can be trusted and you probably do not need to sign them. However, if you got them from outside then, you should investigate why the security exception is coming, before using them.

- 4,974
- 3
- 26
- 32
-
I am doing the same thing. I am working as a contractor to modify small parts of a large app, their build server automates signing. I need to develop and override classes in the supplied jars for testing. They hold the certs dear ( it's a bank ) so I have to work with the output of their build on their terms. – peterk Sep 18 '12 at 17:11
-
The jars are ones I'm developing and I do not need to sign them to begin with until I deploy... but occasionally I want to use the production jars in my dev environment or use an already signed jar that I'm about to deploy. In this case, it's a pain to unzip all the jars, remove the signature, and re-zip. I've since reworked my build system so this doesn't come up frequently anymore. My build system now keeps the unsigned jars and signed jars in the build directory so that I can switch between them at my leisure. – Jason Jan 22 '15 at 15:12