From 0e8d8192fb5a84ad68a3ca3cc02b5c549940b753 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 26 Aug 2026 13:33:16 +0200 Subject: [PATCH] report an oversized download manifest instead of verifying the signature alone --- drongo | 2 +- .../control/DownloadVerifierDialog.java | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drongo b/drongo index 96c91f50..0d8aaac1 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 96c91f506ef96114cdd7414c5fb8cdd33224fb3d +Subproject commit 0d8aaac106b52e71510b5e0bfa97e7103c8aefbc diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DownloadVerifierDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/DownloadVerifierDialog.java index b058607f..3efed6a9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DownloadVerifierDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DownloadVerifierDialog.java @@ -50,6 +50,9 @@ public class DownloadVerifierDialog extends Dialog { private static final DateFormat signatureDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy z"); private static final long MAX_VALID_MANIFEST_SIZE = 100 * 1024; + private static final int MANIFEST_HEADER_LENGTH = 1024; + private static final Pattern MANIFEST_HASH_LINE = Pattern.compile("^[0-9a-fA-F]{64}\\s+\\S+.*"); + private static final String CLEARSIGNED_HEADER = "-----BEGIN PGP SIGNED MESSAGE-----"; private static final String SHA256SUMS_MANIFEST_PREFIX = "sha256sums"; private static final List SIGNATURE_EXTENSIONS = List.of("asc", "sig", "gpg"); @@ -216,8 +219,11 @@ public class DownloadVerifierDialog extends Dialog { log.debug("Error reading manifest file", e); verify = false; } catch(InvalidManifestException e) { - release.set(manifestFile); - verify = false; + //A file too large to be a manifest is assumed to be a release file the signature signs directly, unless it still looks like a manifest + if(!isManifestContent(manifestFile)) { + release.set(manifestFile); + verify = false; + } } if(verify) { @@ -466,7 +472,7 @@ public class DownloadVerifierDialog extends Dialog { public static Map getManifest(File manifest) throws IOException, InvalidManifestException { if(manifest.length() > MAX_VALID_MANIFEST_SIZE) { - throw new InvalidManifestException(); + throw new InvalidManifestException("Manifest file is larger than " + (MAX_VALID_MANIFEST_SIZE / 1024) + "KB"); } try(InputStream manifestStream = new FileInputStream(manifest)) { @@ -494,6 +500,16 @@ public class DownloadVerifierDialog extends Dialog { return manifest; } + private static boolean isManifestContent(File file) { + try(InputStream inputStream = new FileInputStream(file)) { + String header = new String(inputStream.readNBytes(MANIFEST_HEADER_LENGTH), StandardCharsets.UTF_8); + return header.lines().anyMatch(line -> line.startsWith(CLEARSIGNED_HEADER) || MANIFEST_HASH_LINE.matcher(line).matches()); + } catch(IOException e) { + log.debug("Error reading manifest file", e); + return false; + } + } + private String getManifestHash(String contentFileName, Map manifest) { for(Map.Entry entry : manifest.entrySet()) { if(contentFileName.equalsIgnoreCase(entry.getKey().getName())) { @@ -822,5 +838,9 @@ public class DownloadVerifierDialog extends Dialog { } } - private static class InvalidManifestException extends Exception { } + private static class InvalidManifestException extends Exception { + public InvalidManifestException(String message) { + super(message); + } + } }