Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8047353

Improve error message when a JAR with invalid signatures is loaded

    XMLWordPrintable

    Details

    • Type: Enhancement
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 6u26, 9
    • Fix Version/s: None
    • Component/s: security-libs
    • Labels:
    • Subcomponent:
    • Understanding:
      Fix Understood
    • CPU:
      x86
    • OS:
      generic

      Description

      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.

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            coffeys Sean Coffey
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Dates

              Created:
              Updated:
              Imported: