2727import java .util .jar .JarEntry ;
2828import java .util .jar .JarFile ;
2929import java .util .jar .JarOutputStream ;
30+ import java .util .jar .Manifest ;
3031import java .util .stream .Collectors ;
3132
3233import static org .objectweb .asm .ClassWriter .COMPUTE_FRAMES ;
@@ -61,7 +62,7 @@ public String toString() {
6162 }
6263
6364 public static void patchJar (File inputJar , File outputJar , Collection <PatcherInfo > patchers ) {
64- patchJar (inputJar , outputJar , patchers , true );
65+ patchJar (inputJar , outputJar , patchers , false );
6566 }
6667
6768 /**
@@ -73,10 +74,11 @@ public static void patchJar(File inputJar, File outputJar, Collection<PatcherInf
7374 * @param inputFile the JAR file to patch
7475 * @param outputFile the output (patched) JAR file
7576 * @param patchers list of patcher info (classes to patch (jar entry name + optional SHA256 digest) and ASM visitor to transform them)
76- * @param preserveManifest whether to include the manifest file from the input JAR; set this to false when patching a signed JAR,
77- * otherwise the patched classes will fail to load at runtime due to mismatched signatures
77+ * @param unsignJar whether to remove class signatures from the JAR Manifest; set this to true when patching a signed JAR,
78+ * otherwise the patched classes will fail to load at runtime due to mismatched signatures.
79+ * @see <a href="https://docs.oracle.com/javase/tutorial/deployment/jar/intro.html">Understanding Signing and Verification</a>
7880 */
79- public static void patchJar (File inputFile , File outputFile , Collection <PatcherInfo > patchers , boolean preserveManifest ) {
81+ public static void patchJar (File inputFile , File outputFile , Collection <PatcherInfo > patchers , boolean unsignJar ) {
8082 var classPatchers = patchers .stream ().collect (Collectors .toMap (PatcherInfo ::jarEntryName , Function .identity ()));
8183 var mismatchedClasses = new ArrayList <MismatchInfo >();
8284 try (JarFile jarFile = new JarFile (inputFile ); JarOutputStream jos = new JarOutputStream (new FileOutputStream (outputFile ))) {
@@ -107,7 +109,11 @@ public static void patchJar(File inputFile, File outputFile, Collection<PatcherI
107109 );
108110 }
109111 } else {
110- if (preserveManifest || entryName .equals ("META-INF/MANIFEST.MF" ) == false ) {
112+ if (unsignJar && entryName .equals ("META-INF/MANIFEST.MF" )) {
113+ var manifest = new Manifest (jarFile .getInputStream (entry ));
114+ manifest .getEntries ().clear ();
115+ manifest .write (jos );
116+ } else if (unsignJar == false || entryName .matches ("META-INF/.*\\ .SF" ) == false ) {
111117 // Read the entry's data and write it to the new JAR
112118 try (InputStream is = jarFile .getInputStream (entry )) {
113119 is .transferTo (jos );
0 commit comments