From 8f41af1d41ef5af2757ca7ac9dfc0b89f218902d Mon Sep 17 00:00:00 2001 From: Emmanuel Bourg Date: Fri, 2 Jun 2023 23:22:46 +0200 Subject: [PATCH] Hash the class identifier of the sub storages in MSI files (#149) --- .../src/main/java/net/jsign/msi/MSIFile.java | 57 ++++++++----------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/jsign-core/src/main/java/net/jsign/msi/MSIFile.java b/jsign-core/src/main/java/net/jsign/msi/MSIFile.java index 3a671000..9b5a1cd8 100644 --- a/jsign-core/src/main/java/net/jsign/msi/MSIFile.java +++ b/jsign-core/src/main/java/net/jsign/msi/MSIFile.java @@ -169,29 +169,6 @@ public boolean hasExtendedSignature() { } } - private List getSortedProperties() { - List entries = new ArrayList<>(); - - append(fsRead.getPropertyTable().getRoot(), entries); - - return entries; - } - - private void append(DirectoryProperty node, List entries) { - Map sortedEntries = new TreeMap<>(); - for (Property entry : node) { - sortedEntries.put(new MSIStreamName(entry.getName()), entry); - } - - for (Property property : sortedEntries.values()) { - if (!property.isDirectory()) { - entries.add(property); - } else { - append((DirectoryProperty) property, entries); - } - } - } - @Override public byte[] computeDigest(MessageDigest digest) throws IOException { try { @@ -202,8 +179,22 @@ public byte[] computeDigest(MessageDigest digest) throws IOException { updateDigest(digest, msiDigitalSignatureExDocument); } - // hash the entries - for (Property property : getSortedProperties()) { + computeDigest(digest, fsRead.getPropertyTable().getRoot()); + + return digest.digest(); + } catch (IndexOutOfBoundsException | IllegalArgumentException | IllegalStateException | NoSuchElementException e) { + throw new IOException("MSI file format error", e); + } + } + + private void computeDigest(MessageDigest digest, DirectoryProperty node) { + Map sortedEntries = new TreeMap<>(); + for (Property child : node) { + sortedEntries.put(new MSIStreamName(child.getName()), child); + } + + for (Property property : sortedEntries.values()) { + if (!property.isDirectory()) { String name = new MSIStreamName(property.getName()).decode(); if (name.equals(DIGITAL_SIGNATURE_ENTRY_NAME) || name.equals(MSI_DIGITAL_SIGNATURE_EX_ENTRY_NAME)) { continue; @@ -211,17 +202,15 @@ public byte[] computeDigest(MessageDigest digest) throws IOException { POIFSDocument document = new POIFSDocument((DocumentProperty) property, fsRead); updateDigest(digest, document); + } else { + computeDigest(digest, (DirectoryProperty) property); } - - // hash the package ClassID, in serialized form - byte[] classId = new byte[16]; - fsRead.getRoot().getStorageClsid().write(classId, 0); - digest.update(classId); - - return digest.digest(); - } catch (IndexOutOfBoundsException | IllegalArgumentException | IllegalStateException | NoSuchElementException e) { - throw new IOException("MSI file format error", e); } + + // hash the package ClassID, in serialized form + byte[] classId = new byte[16]; + node.getStorageClsid().write(classId, 0); + digest.update(classId); } private void updateDigest(MessageDigest digest, POIFSDocument document) {