mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-08-04 04:26:15 -04:00
updater: move signature back to just the binary
Yes, makes it cryptographically weaker, but somebody who can modify responses of my webserver has probably enough power to access gitlab secrets already. The signature is pretty "optional" then.
This commit is contained in:
parent
2548b5c027
commit
c6978abe10
@ -29,7 +29,7 @@ Otherwise it responds with `200 OK` and returns a json object (with the signatur
|
|||||||
"url": "https:// where to download it",
|
"url": "https:// where to download it",
|
||||||
"size": <Update size in Bytes>,
|
"size": <Update size in Bytes>,
|
||||||
"sha512": "SHA512 hash of the binary",
|
"sha512": "SHA512 hash of the binary",
|
||||||
"signature": "Release signature"
|
"signature": "SHA512withRSA signature of the binary"
|
||||||
},
|
},
|
||||||
"release_notes": "<Optional text for release notes to show in the client>"
|
"release_notes": "<Optional text for release notes to show in the client>"
|
||||||
}
|
}
|
||||||
@ -45,10 +45,6 @@ Once it is downloaded, minosoft asks the user to restart. It will then quit and
|
|||||||
|
|
||||||
The client will refuse to update, if the release date of the next version is lower than the version currently running (i.e. no downgrades)
|
The client will refuse to update, if the release date of the next version is lower than the version currently running (i.e. no downgrades)
|
||||||
|
|
||||||
## Signature
|
|
||||||
|
|
||||||
The first line of the file is the base64 encoded signature of the whole json object.
|
|
||||||
|
|
||||||
## Future
|
## Future
|
||||||
|
|
||||||
- Maybe split the fat jar and download all dependencies individual (reduces size of the binary; lowers traffic)
|
- Maybe split the fat jar and download all dependencies individual (reduces size of the binary; lowers traffic)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -13,26 +13,27 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.updater
|
package de.bixilon.minosoft.updater
|
||||||
|
|
||||||
import org.testng.Assert.assertThrows
|
|
||||||
import org.testng.annotations.Test
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
|
|
||||||
@Test(groups = ["updater"])
|
@Test(groups = ["updater"])
|
||||||
class MinosoftUpdaterTest {
|
class MinosoftUpdaterTest {
|
||||||
|
|
||||||
private fun verify(signature: String, data: String) {
|
/*
|
||||||
MinosoftUpdater.parse(signature + "\n" + data)
|
private fun verify(data: String) {
|
||||||
|
MinosoftUpdater.parse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun `verify broken signature`() {
|
fun `verify broken signature`() {
|
||||||
assertThrows { verify("NOT_VALID", """{"id":"dummy","name":"Dummy version","date":-1,"stable":true,"page":null,"download":{"url":"https://bixilon.de/secret-update.jar","size":123,"sha512":"b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee"},"release_notes":":)"}""") }
|
assertThrows { verify("""{"id":"dummy","name":"Dummy version","date":-1,"stable":true,"page":null,"download":{"url":"https://bixilon.de/secret-update.jar","size":123,"sha512":"b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee"},"release_notes":":)"}""", "NOT_VALID") }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun `verify correct signature`() {
|
fun `verify correct signature`() {
|
||||||
assertThrows {
|
assertThrows {
|
||||||
verify(
|
verify(
|
||||||
"Mv7979ky1AlMCcOLmX+Zdmo2Y7YOGiMthTBeNP2jKUPRkMtX1GCBYMrsKV+si9rR9Kg+1Ns82Hw1iYAI+ZOkTzVmoIeaWkqL4PN4sCCVllm2ZmZhTap7wdNAVEjW197Cf+V2YJW0TsG+j2s6OK86gdtVmyJ96X/ENhXTJRp8pW50lcCyy95ipQ1Qe8v4mAFykpU9XC/yU2Mhil/KznxvxKgd7N4+/VNpubOHetWfdiz9jqAB6uaYVi0H9E+EoZodkG3Iy5uagr1OrWNiwjk3LQUEk+J+5cYRPqBHrqLM9VNQFa5BqysSJoW7cIo/QUQA47EBxO8Rmg/juFA1l9bXtSUA+1j12n9ImhE/L3cYseYiIN8GFRpbhSaROgfZW9u3lVHM4g45q67zvvdf+Eo7lqfipYio89rQ984U58o5AvLhV+WqhDVRBTTtO+oI/FjdiHIruoiY/adEz7gJEAlrMlgoAAQkVnKma9uufObIemL+QGpDjLvdluIgts/cT34r4I5Xaij1vGAjzZ+Fe+Tn5tuW48pjtjWCzAwVTEu/zf/VKSJPoCVGx5YCvFE3CKXkVWuJ86gj+rO/SXWkjv672EetaVwv2Uc/RkCfru84m6bQWAHzb3P46Hfkw3kIyaIudxgizy1xlxLEEU3LwUU/vFxTd2Q6lAhGGMn6Imy9Z6I=",
|
"""{"id":"dummy","name":"Dummy version","date":-1,"stable":true,"page":null,"download":{"url":"https://bixilon.de/secret-update.jar","size":123,"sha512":"b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee"},"release_notes":":)"}""",
|
||||||
"""{"id":"dummy","name":"Dummy version","date":-1,"stable":true,"page":null,"download":{"url":"https://bixilon.de/secret-update.jar","size":123,"sha512":"b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee"},"release_notes":":)"}""")
|
"Mv7979ky1AlMCcOLmX+Zdmo2Y7YOGiMthTBeNP2jKUPRkMtX1GCBYMrsKV+si9rR9Kg+1Ns82Hw1iYAI+ZOkTzVmoIeaWkqL4PN4sCCVllm2ZmZhTap7wdNAVEjW197Cf+V2YJW0TsG+j2s6OK86gdtVmyJ96X/ENhXTJRp8pW50lcCyy95ipQ1Qe8v4mAFykpU9XC/yU2Mhil/KznxvxKgd7N4+/VNpubOHetWfdiz9jqAB6uaYVi0H9E+EoZodkG3Iy5uagr1OrWNiwjk3LQUEk+J+5cYRPqBHrqLM9VNQFa5BqysSJoW7cIo/QUQA47EBxO8Rmg/juFA1l9bXtSUA+1j12n9ImhE/L3cYseYiIN8GFRpbhSaROgfZW9u3lVHM4g45q67zvvdf+Eo7lqfipYio89rQ984U58o5AvLhV+WqhDVRBTTtO+oI/FjdiHIruoiY/adEz7gJEAlrMlgoAAQkVnKma9uufObIemL+QGpDjLvdluIgts/cT34r4I5Xaij1vGAjzZ+Fe+Tn5tuW48pjtjWCzAwVTEu/zf/VKSJPoCVGx5YCvFE3CKXkVWuJ86gj+rO/SXWkjv672EetaVwv2Uc/RkCfru84m6bQWAHzb3P46Hfkw3kIyaIudxgizy1xlxLEEU3LwUU/vFxTd2Q6lAhGGMn6Imy9Z6I=")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -45,7 +45,7 @@ class UpdaterC(profile: OtherProfile) {
|
|||||||
* - OS: Operating system (windows, linux, mac, ...)
|
* - OS: Operating system (windows, linux, mac, ...)
|
||||||
* - ARCH: architecture of the current build (x86, x64, arm64)
|
* - ARCH: architecture of the current build (x86, x64, arm64)
|
||||||
*/
|
*/
|
||||||
var url by StringDelegate(profile, "https://minosoft.bixilon.de/v1/updates?version=\${VERSION}&channel=\${CHANNEL}&commit=\${COMMIT}&os=\${OS}&arch=\${ARCH}")
|
var url by StringDelegate(profile, "https://minosoft.bixilon.de/api/v1/updates?version=\${VERSION}&channel=\${CHANNEL}&commit=\${COMMIT}&os=\${OS}&arch=\${ARCH}")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the newest version matches this field, it won't be shown
|
* If the newest version matches this field, it won't be shown
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -19,4 +19,5 @@ data class DownloadLink(
|
|||||||
val url: URL,
|
val url: URL,
|
||||||
val size: Int,
|
val size: Int,
|
||||||
val sha512: String,
|
val sha512: String,
|
||||||
|
val signature: String,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -101,9 +101,7 @@ object MinosoftUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun parse(data: String): MinosoftUpdate {
|
fun parse(data: String): MinosoftUpdate {
|
||||||
val (signature, json) = data.split('\n', limit = 2)
|
return Jackson.MAPPER.readValue(data, MinosoftUpdate::class.java)
|
||||||
UpdateKey.require(signature, json)
|
|
||||||
return Jackson.MAPPER.readValue(json, MinosoftUpdate::class.java)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun download(update: MinosoftUpdate, progress: UpdateProgress) {
|
fun download(update: MinosoftUpdate, progress: UpdateProgress) {
|
||||||
@ -116,5 +114,6 @@ object MinosoftUpdater {
|
|||||||
|
|
||||||
progress.log?.print("TODO :)")
|
progress.log?.print("TODO :)")
|
||||||
progress.stage = UpdateProgress.UpdateStage.FAILED
|
progress.stage = UpdateProgress.UpdateStage.FAILED
|
||||||
|
// UpdateKey.require(data, signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2021 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -15,5 +15,6 @@ package de.bixilon.minosoft.util.http
|
|||||||
|
|
||||||
class HTTPResponse<T>(
|
class HTTPResponse<T>(
|
||||||
val statusCode: Int,
|
val statusCode: Int,
|
||||||
|
val headers: Map<String, String>,
|
||||||
val body: T,
|
val body: T,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020-2023 Moritz Zwerger
|
* Copyright (C) 2020-2024 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
@ -42,22 +42,23 @@ abstract class SignatureSigner(
|
|||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun verify(data: ByteArray, signature: ByteArray): Boolean {
|
open fun verify(data: ByteArray, signature: ByteArray?): Boolean {
|
||||||
|
if (signature == null) return false
|
||||||
val instance = createInstance()
|
val instance = createInstance()
|
||||||
instance.update(data)
|
instance.update(data)
|
||||||
return instance.verify(signature)
|
return instance.verify(signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun require(data: ByteArray, signature: ByteArray) {
|
fun require(data: ByteArray, signature: ByteArray?) {
|
||||||
if (verify(data, signature)) return
|
if (verify(data, signature)) return
|
||||||
throw SignatureException()
|
throw SignatureException()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verify(data: String, signature: String): Boolean {
|
fun verify(data: String, signature: String?): Boolean {
|
||||||
return verify(data.toByteArray(), Base64.getDecoder().decode(signature))
|
return verify(data.toByteArray(), Base64.getDecoder().decode(signature))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun require(data: String, signature: String) {
|
fun require(data: String, signature: String?) {
|
||||||
if (verify(data, signature)) return
|
if (verify(data, signature)) return
|
||||||
throw SignatureException()
|
throw SignatureException()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user