src/share/classes/org/openjdk/jigsaw/cli/Signer.java
Print this page
*** 30,39 ****
--- 30,40 ----
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,51 ****
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.internal.joptsimple.OptionException;
import org.openjdk.internal.joptsimple.OptionParser;
import org.openjdk.internal.joptsimple.OptionSet;
import org.openjdk.internal.joptsimple.OptionSpec;
--- 42,54 ----
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.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,233 ****
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())
throw new Command.Exception("module file is already signed");
! reader.readRest();
! hashes = reader.getCalculatedHashes();
! } catch (IOException x) {
throw new Command.Exception("unable to read module file", x);
}
// Next, generate signature and insert into signed module file
File tmpFile = (signedModuleFile == null)
--- 216,246 ----
throw new Command.Exception("unable to extract private key " +
"entry from keystore", x);
}
// First, read in module file and calculate hashes
! 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");
! 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,249 ****
// Transfer header and module-info from module file
// to signed module file.
long remainderStart = ModuleFileHeader.LENGTH
+ SectionHeader.LENGTH
! + moduleInfoBytes.length;
FileChannel source = mraf.getChannel();
FileChannel dest = raf.getChannel();
for (long pos = 0; pos < remainderStart;) {
pos += source.transferTo(pos, remainderStart - pos, dest);
}
--- 252,262 ----
// Transfer header and module-info from module file
// to signed module file.
long remainderStart = ModuleFileHeader.LENGTH
+ SectionHeader.LENGTH
! + moduleInfoLength;
FileChannel source = mraf.getChannel();
FileChannel dest = raf.getChannel();
for (long pos = 0; pos < remainderStart;) {
pos += source.transferTo(pos, remainderStart - pos, dest);
}
*** 273,282 ****
--- 286,314 ----
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;