aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorRoman / Linnea Gräf <roman.graef@gmail.com>2022-10-11 21:43:00 +0200
committerGitHub <noreply@github.com>2022-10-11 15:43:00 -0400
commit54eea328ad47ff55f3c8498fdc13e61a30200087 (patch)
tree26a44e51b55f69891ee49518c96f42e8b7d334d2 /src/main/java
parent90b3225afdd5e43c54e82d73478f2c2f1e046f80 (diff)
downloadNotEnoughUpdates-54eea328ad47ff55f3c8498fdc13e61a30200087.tar.gz
NotEnoughUpdates-54eea328ad47ff55f3c8498fdc13e61a30200087.tar.bz2
NotEnoughUpdates-54eea328ad47ff55f3c8498fdc13e61a30200087.zip
Add ability to sign update.json, needed for autoupdates (#354)
* Add ability to sign update.json, needed for autoupdates * Remove update from URL
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java18
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java9
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java80
3 files changed, 89 insertions, 18 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java
index 36443b27..cac93369 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java
@@ -49,10 +49,6 @@ public class UpdateCommand extends ClientCommandBase {
"" +
"§e[NEU] §b/neuupdate help - View help.\n" +
"§e[NEU] §b/neuupdate check - Check for updates.\n" +
- "§e[NEU] §b/neuupdate url <url> - Load an update from an direct download URL.\n" +
- " §cONLY DO THIS WITH TRUSTED URLS OR IT MIGHT RESULT IN A RAT!\n" +
- "§e[NEU] §b/neuupdate fromartifact <url> - Load an update from an artifact.\n" +
- " §cIf you don't know what this is, don't use it.\n" +
""
));
@@ -68,20 +64,6 @@ public class UpdateCommand extends ClientCommandBase {
case "check":
neu.autoUpdater.displayUpdateMessageIfOutOfDate();
break;
- case "url":
- if (args.length != 2) {
- sender.addChatMessage(new ChatComponentText("§e[NEU] §cPlease provide an URL"));
- }
- URL url;
- try {
- url = new URL(args[1]);
- } catch (MalformedURLException e) {
- e.printStackTrace();
- sender.addChatMessage(new ChatComponentText("§e[NEU] §cInvalid URL"));
- return;
- }
- neu.autoUpdater.updateFromURL(url);
- break;
case "scheduledownload":
neu.autoUpdater.scheduleDownload();
break;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java
index 389cfc75..54fcc204 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java
@@ -26,6 +26,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.MoulSigner;
import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
@@ -171,6 +172,14 @@ public class AutoUpdater {
File repo = neu.manager.repoLocation;
File updateJson = new File(repo, "update.json");
if (updateJson.exists()) {
+ if (!MoulSigner.verifySignature(updateJson)) {
+ NotEnoughUpdates.LOGGER.error("update.json found without signature");
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "§e[NEU] §cThere has been an error checking for updates. Check the log or join the discord for more information.").setChatStyle(
+ Utils.createClickStyle(
+ ClickEvent.Action.OPEN_URL, "https://discord.gg/moulberry")));
+ return;
+ }
try {
JsonObject o = neu.manager.getJsonFromFile(updateJson);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java b/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java
new file mode 100644
index 00000000..6510bc20
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+public class MoulSigner {
+ private MoulSigner() {}
+
+ static PublicKey publicKey;
+
+ static {
+ try (InputStream is = MoulSigner.class.getResourceAsStream("/moulberry.key")) {
+ byte[] publicKeyBytes = IOUtils.toByteArray(is);
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
+ publicKey = KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec);
+ } catch (IOException | NullPointerException | NoSuchAlgorithmException | InvalidKeySpecException e) {
+ NotEnoughUpdates.LOGGER.error("Cannot initialize MoulSigner", e);
+ }
+ }
+
+ public static boolean verifySignature(byte[] data, byte[] signatureBytes) {
+ if (Boolean.getBoolean("neu.noverifysignature")) return true;
+ if (publicKey == null) {
+ NotEnoughUpdates.LOGGER.warn("MoulSigner could not be initialized, will fail this request");
+ return false;
+ }
+ try {
+ Signature signature = Signature.getInstance("SHA256withRSA");
+ signature.initVerify(publicKey);
+ signature.update(data);
+ return signature.verify(signatureBytes);
+ } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
+ NotEnoughUpdates.LOGGER.error("Error while verifying signature. Considering this as invalid signature", e);
+ return false;
+ }
+ }
+
+ public static boolean verifySignature(File file) {
+ try {
+ return verifySignature(
+ IOUtils.toByteArray(file.toURI()),
+ IOUtils.toByteArray(new File(file.getParentFile(), file.getName() + ".asc").toURI())
+ );
+ } catch (IOException e) {
+ NotEnoughUpdates.LOGGER.error("Ran into an IOException while verifying a signature", e);
+ return false;
+ }
+ }
+}