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;