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); + } + } }