Loading... (original) (raw)
A DESCRIPTION OF THE REQUEST :
When a JAR with invalid signatures is loaded, you get this error:
java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
JUSTIFICATION :
This is OK for small projects but if you have > 20 JARs on the classpath, it would be nice to know *which* JAR contains the problem.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Please wrap the method java.util.jar.JarFile.initializeVerifier() in in a try-catch and in the catch, wrap the SecurityException in one with the message
"Error loading JAR " + this.name
---------- BEGIN SOURCE ----------
package com.oracle.tests;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class JarSigningBug {
public void testJarSigningBug() throws Exception {
File archive = new File( "demo.jar" );
ZipOutputStream zip = new ZipOutputStream( new FileOutputStream( archive ) );
String path = "com/oracle/tests/JarSigningBug.class";
ZipEntry e;
e = new ZipEntry( "META-INF/MANIFEST.MF" );
zip.putNextEntry( e );
write( zip,
"Manifest-Version: 1.0\r\n" +
"\r\n" +
"Name: com/oracle/tests/JarSigningBug.class\r\n" +
"SHA1-Digest: 00AoNNgGbDkb+UqFQID0V6AWbRo=\r\n" +
"\r\n"
);
e = new ZipEntry( "META-INF/DEMO.DSA" );
zip.putNextEntry( e );
zip.write( hexToBytes( DSA_KEY ) );
e = new ZipEntry( "META-INF/DEMO.SF" );
zip.putNextEntry( e );
write( zip,
"Signature-Version: 1.0\r\n" +
"SHA1-Digest-Manifest-Main-Attributes: eeM91S699hXmaWrmmt2Ry5kNgeI=\r\n" +
"Created-By: 1.6.0_26 (Sun Microsystems Inc.)\r\n" +
"SHA1-Digest-Manifest: ydVkxxE9pXpLi1rTc2uacXnWenQ=\r\n" +
"\r\n" +
"Name: com/oracle/tests/JarSigningBug.class\r\n" +
"SHA1-Digest: PUJaOXXZPSxNKf83C40lHCMiEdg=\r\n" +
"\r\n"
);
e = new ZipEntry( path );
zip.putNextEntry( e );
copy( getClass().getClassLoader().getResourceAsStream( path ), zip );
zip.close();
URL[] urls = { archive.toURI().toURL() };
System.out.println( "urls=" + Arrays.toString( urls ) );
URLClassLoader cl = new URLClassLoader( urls, getClass().getClassLoader().getParent() );
Class type1 = getClass(); Class type2 = cl.loadClass( getClass().getName() );
System.out.println( type1.hashCode() );
System.out.println( type2.hashCode() );
}
private byte[] hexToBytes( String data ) {
data = data
.replaceAll( "\\S{7}", "" )
.replaceAll( "\\s", "" );
byte[] bytes = new byte[data.length() / 2];
for( int i=0; i<data.length(); i+=2) {
bytes[i/2] = (byte) Integer.parseInt( data.substring( i, i+2 ), 16 );
}
return bytes;
}
private String DSA_KEY =
"0000000 30 82 04 11 06 09 2a 86 48 86 f7 0d 01 07 02 a0\n" +
"0000020 82 04 02 30 82 03 fe 02 01 01 31 0b 30 09 06 05\n" +
"0000040 2b 0e 03 02 1a 05 00 30 0b 06 09 2a 86 48 86 f7\n" +
"0000060 0d 01 07 01 a0 82 03 15 30 82 03 11 30 82 02 cf\n" +
"0000100 a0 03 02 01 02 02 04 4e 3a ac 12 30 0b 06 07 2a\n" +
"0000120 86 48 ce 38 04 03 05 00 30 6c 31 10 30 0e 06 03\n" +
"0000140 55 04 06 13 07 55 6e 6b 6e 6f 77 6e 31 10 30 0e\n" +
"0000160 06 03 55 04 08 13 07 55 6e 6b 6e 6f 77 6e 31 10\n" +
"0000200 30 0e 06 03 55 04 07 13 07 55 6e 6b 6e 6f 77 6e\n" +
"0000220 31 10 30 0e 06 03 55 04 0a 13 07 55 6e 6b 6e 6f\n" +
"0000240 77 6e 31 10 30 0e 06 03 55 04 0b 13 07 55 6e 6b\n" +
"0000260 6e 6f 77 6e 31 10 30 0e 06 03 55 04 03 13 07 55\n" +
"0000300 6e 6b 6e 6f 77 6e 30 1e 17 0d 31 31 30 38 30 34\n" +
"0000320 31 34 32 36 32 36 5a 17 0d 31 31 31 31 30 32 31\n" +
"0000340 34 32 36 32 36 5a 30 6c 31 10 30 0e 06 03 55 04\n" +
"0000360 06 13 07 55 6e 6b 6e 6f 77 6e 31 10 30 0e 06 03\n" +
"0000400 55 04 08 13 07 55 6e 6b 6e 6f 77 6e 31 10 30 0e\n" +
"0000420 06 03 55 04 07 13 07 55 6e 6b 6e 6f 77 6e 31 10\n" +
"0000440 30 0e 06 03 55 04 0a 13 07 55 6e 6b 6e 6f 77 6e\n" +
"0000460 31 10 30 0e 06 03 55 04 0b 13 07 55 6e 6b 6e 6f\n" +
"0000500 77 6e 31 10 30 0e 06 03 55 04 03 13 07 55 6e 6b\n" +
"0000520 6e 6f 77 6e 30 82 01 b7 30 82 01 2c 06 07 2a 86\n" +
"0000540 48 ce 38 04 01 30 82 01 1f 02 81 81 00 fd 7f 53\n" +
"0000560 81 1d 75 12 29 52 df 4a 9c 2e ec e4 e7 f6 11 b7\n" +
"0000600 52 3c ef 44 00 c3 1e 3f 80 b6 51 26 69 45 5d 40\n" +
"0000620 22 51 fb 59 3d 8d 58 fa bf c5 f5 ba 30 f6 cb 9b\n" +
"0000640 55 6c d7 81 3b 80 1d 34 6f f2 66 60 b7 6b 99 50\n" +
"0000660 a5 a4 9f 9f e8 04 7b 10 22 c2 4f bb a9 d7 fe b7\n" +
"0000700 c6 1b f8 3b 57 e7 c6 a8 a6 15 0f 04 fb 83 f6 d3\n" +
"0000720 c5 1e c3 02 35 54 13 5a 16 91 32 f6 75 f3 ae 2b\n" +
"0000740 61 d7 2a ef f2 22 03 19 9d d1 48 01 c7 02 15 00\n" +
"0000760 97 60 50 8f 15 23 0b cc b2 92 b9 82 a2 eb 84 0b\n" +
"0001000 f0 58 1c f5 02 81 81 00 f7 e1 a0 85 d6 9b 3d de\n" +
"0001020 cb bc ab 5c 36 b8 57 b9 79 94 af bb fa 3a ea 82\n" +
"0001040 f9 57 4c 0b 3d 07 82 67 51 59 57 8e ba d4 59 4f\n" +
"0001060 e6 71 07 10 81 80 b4 49 16 71 23 e8 4c 28 16 13\n" +
"0001100 b7 cf 09 32 8c c8 a6 e1 3c 16 7a 8b 54 7c 8d 28\n" +
"0001120 e0 a3 ae 1e 2b b3 a6 75 91 6e a3 7f 0b fa 21 35\n" +
"0001140 62 f1 fb 62 7a 01 24 3b cc a4 f1 be a8 51 90 89\n" +
"0001160 a8 83 df e1 5a e5 9f 06 92 8b 66 5e 80 7b 55 25\n" +
"0001200 64 01 4c 3b fe cf 49 2a 03 81 84 00 02 81 80 0a\n" +
"0001220 b8 57 e6 74 22 89 31 e9 fa c9 d4 66 4e 37 d7 68\n" +
"0001240 59 a1 d1 fb 6f 92 e5 18 f1 0a 41 4c 8a c9 39 a0\n" +
"0001260 e3 53 73 65 82 6b b7 a1 ee 65 a8 34 3e 85 8a 28\n" +
"0001300 71 43 0d af 71 07 97 d5 d2 e8 5b 20 46 74 36 83\n" +
"0001320 f5 75 31 9f 3f 7c b1 80 a8 30 40 cd b5 77 42 8c\n" +
"0001340 be 05 f6 e2 b7 f9 33 2f c9 59 93 8b 3e 61 db cc\n" +
"0001360 0e 61 ee 9d 86 8c 26 45 77 ac b9 b5 d1 8c d3 db\n" +
"0001400 51 a4 f7 4f 65 32 74 dc 02 51 89 15 80 d0 15 30\n" +
"0001420 0b 06 07 2a 86 48 ce 38 04 03 05 00 03 2f 00 30\n" +
"0001440 2c 02 14 10 de c6 be 97 2e 85 c3 ac 8c 08 0f 2c\n" +
"0001460 a9 43 54 42 0a d5 24 02 14 2d 18 5b 30 88 fc fb\n" +
"0001500 06 2b 0e c4 1a a9 b0 f6 0d 1d 74 1d 05 31 81 c5\n" +
"0001520 30 81 c2 02 01 01 30 74 30 6c 31 10 30 0e 06 03\n" +
"0001540 55 04 06 13 07 55 6e 6b 6e 6f 77 6e 31 10 30 0e\n" +
"0001560 06 03 55 04 08 13 07 55 6e 6b 6e 6f 77 6e 31 10\n" +
"0001600 30 0e 06 03 55 04 07 13 07 55 6e 6b 6e 6f 77 6e\n" +
"0001620 31 10 30 0e 06 03 55 04 0a 13 07 55 6e 6b 6e 6f\n" +
"0001640 77 6e 31 10 30 0e 06 03 55 04 0b 13 07 55 6e 6b\n" +
"0001660 6e 6f 77 6e 31 10 30 0e 06 03 55 04 03 13 07 55\n" +
"0001700 6e 6b 6e 6f 77 6e 02 04 4e 3a ac 12 30 09 06 05\n" +
"0001720 2b 0e 03 02 1a 05 00 30 0b 06 07 2a 86 48 ce 38\n" +
"0001740 04 01 05 00 04 2f 30 2d 02 15 00 8f db 45 5e 43\n" +
"0001760 9e 37 67 59 65 04 e6 80 8d 84 2f 2a 62 f2 59 02\n" +
"0002000 14 76 4f 7f c1 a8 10 83 fd 73 99 5c 89 1d 89 5a\n" +
"0002020 82 49 89 a4 e7\n" +
"";
private void write( OutputStream output, String string ) throws IOException {
byte[] data = string.getBytes( "ISO-8859-1" );
output.write( data );
}
private void copy( InputStream input, OutputStream output ) throws IOException {
byte[] buffer = new byte[1024];
int len;
while( ( len = input.read( buffer ) ) > 0 ) {
output.write( buffer, 0, len );
}
input.close();
}
public static void main( String[] args ) {
try {
new JarSigningBug().testJarSigningBug();
} catch( Exception e ) {
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Set a breakpoint in the constructor to SecurityException at line 35. Then you can walk up the stack until the JarFile instance to get the name of the JAR.