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

Improve error message when a JAR with invalid signatures is loaded

    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
              Reporter:
              coffeys Sean Coffey
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Imported: