src/share/classes/org/openjdk/jigsaw/cli/Signer.java

Print this page

        

@@ -30,10 +30,11 @@
 import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.security.*;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import javax.security.auth.DestroyFailedException;
 
 import static java.lang.System.err;

@@ -41,11 +42,13 @@
 import static java.lang.System.out;
 import static java.security.KeyStore.PasswordProtection;
 import static java.security.KeyStore.PrivateKeyEntry;
 
 import org.openjdk.jigsaw.*;
-import org.openjdk.jigsaw.ModuleFile.Reader;
+import org.openjdk.jigsaw.ModuleFileParser;
+import org.openjdk.jigsaw.ModuleFileParserException;
+import org.openjdk.jigsaw.ModuleFileParser.Event;
 import org.openjdk.internal.joptsimple.OptionException;
 import org.openjdk.internal.joptsimple.OptionParser;
 import org.openjdk.internal.joptsimple.OptionSet;
 import org.openjdk.internal.joptsimple.OptionSpec;
 

@@ -213,21 +216,31 @@
                 throw new Command.Exception("unable to extract private key " +
                                             "entry from keystore", x);
             }
 
             // First, read in module file and calculate hashes
-            List<byte[]> hashes = null;
-            byte[] moduleInfoBytes = null;
-            try (FileInputStream mfis = new FileInputStream(moduleFile);
-                 Reader reader = new Reader(new DataInputStream(mfis)))
-            {
-                moduleInfoBytes = reader.readStart();
-                if (reader.hasSignature())
+            List<byte[]> hashes = new ArrayList<>();
+            int moduleInfoLength = 0;
+            try (FileInputStream mfis = new FileInputStream(moduleFile)) {
+                ModuleFileParser parser = ModuleFile.newParser(mfis);
+                hashes.add(parser.getHash());
+                while (parser.hasNext()) {
+                    Event event = parser.next();
+                    if (event == Event.END_SECTION) {
+                        SectionHeader header = parser.getSectionHeader();
+                        if (header.getType() == SectionType.SIGNATURE)
                     throw new Command.Exception("module file is already signed");
-                reader.readRest();
-                hashes = reader.getCalculatedHashes();
-            } catch (IOException x) {
+                        if (header.getType() == SectionType.MODULE_INFO)
+                            moduleInfoLength = header.getCSize();
+                        checkHashMatch(header.getHash(), parser.getHash());
+                        hashes.add(parser.getHash());
+                    } else if (event == Event.END_FILE) {
+                        checkHashMatch(parser.fileHeader().getHash(), parser.getHash());
+                        hashes.add(parser.getHash());
+                    }
+                }
+            } catch (IOException | ModuleFileParserException x) {
                 throw new Command.Exception("unable to read module file", x);
             }
 
             // Next, generate signature and insert into signed module file
             File tmpFile = (signedModuleFile == null)

@@ -239,11 +252,11 @@
 
                 // Transfer header and module-info from module file
                 // to signed module file.
                 long remainderStart = ModuleFileHeader.LENGTH
                                       + SectionHeader.LENGTH
-                                      + moduleInfoBytes.length;
+                                      + moduleInfoLength;
                 FileChannel source = mraf.getChannel();
                 FileChannel dest = raf.getChannel();
                 for (long pos = 0; pos < remainderStart;) {
                     pos += source.transferTo(pos, remainderStart - pos, dest);
                 }

@@ -273,10 +286,29 @@
                     throw new Command.Exception("unable to sign module", ioe);
                 }
             }
         }
 
+        private void checkHashMatch(byte[] expected, byte[] computed) {
+            if (!MessageDigest.isEqual(expected, computed))
+                throw new ModuleFileParserException("Expected hash "
+                                      + hashHexString(expected)
+                                      + " instead of "
+                                      + hashHexString(computed));
+        }
+
+        private String hashHexString(byte[] hash) {
+            StringBuilder hex = new StringBuilder("0x");
+            for (int i = 0; i < hash.length; i++) {
+                int val = (hash[i] & 0xFF);
+                if (val <= 16)
+                    hex.append("0");
+                hex.append(Integer.toHexString(val));
+            }
+            return hex.toString();
+        }
+
         private PrivateKeyEntry getPrivateKeyEntry(String signer)
             throws GeneralSecurityException, IOException
         {
             PasswordProtection storePassword = null;
             PasswordProtection keyPassword = null;