From 90b2c74c770773d9c32cf11d3fc206e41b32bd81 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 2 Jul 2023 02:59:23 -0400 Subject: [PATCH 1/4] Add NSec.Cryptography --- StabilityMatrix/StabilityMatrix.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/StabilityMatrix/StabilityMatrix.csproj b/StabilityMatrix/StabilityMatrix.csproj index f4947bb6..b5e04e29 100644 --- a/StabilityMatrix/StabilityMatrix.csproj +++ b/StabilityMatrix/StabilityMatrix.csproj @@ -33,6 +33,7 @@ + From dee03170f3e4fde296cb7ee3d7de7a9c1258516f Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 2 Jul 2023 02:59:38 -0400 Subject: [PATCH 2/4] Add SignatureChecker class, updates public key --- StabilityMatrix/Updater/SignatureChecker.cs | 51 +++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 StabilityMatrix/Updater/SignatureChecker.cs diff --git a/StabilityMatrix/Updater/SignatureChecker.cs b/StabilityMatrix/Updater/SignatureChecker.cs new file mode 100644 index 00000000..3a1159a5 --- /dev/null +++ b/StabilityMatrix/Updater/SignatureChecker.cs @@ -0,0 +1,51 @@ +using System; +using System.Text; +using NSec.Cryptography; + +namespace StabilityMatrix.Updater; + +public class SignatureChecker +{ + private static readonly SignatureAlgorithm Algorithm = SignatureAlgorithm.Ed25519; + private const string UpdatePublicKey = + "-----BEGIN PUBLIC KEY-----\n" + + "MCowBQYDK2VwAyEAqYXhKG1b0iOMnAZGBSBdFlFEWpFBIbIPQk0TtyE2SfI=\n" + + "-----END PUBLIC KEY-----\n"; + + private readonly PublicKey publicKey; + + /// + /// Initializes a new instance of SignatureChecker. + /// + /// Pkix format public key. Defaults to update verification key. + public SignatureChecker(string? publicKeyPkix = null) + { + publicKey = PublicKey.Import( + Algorithm, + Encoding.ASCII.GetBytes(publicKeyPkix ?? UpdatePublicKey), + KeyBlobFormat.PkixPublicKeyText); + } + + /// + /// Verifies the signature of provided data. + /// + /// Data to verify + /// Signature in base64 encoding + /// True if verified + public bool Verify(string data, string signature) + { + var signatureBytes = Convert.FromBase64String(signature); + return Algorithm.Verify(publicKey, Encoding.UTF8.GetBytes(data), signatureBytes); + } + + /// + /// Verifies the signature of provided data. + /// + /// Data to verify + /// Signature in base64 encoding + /// True if verified + public bool Verify(ReadOnlySpan data, ReadOnlySpan signature) + { + return Algorithm.Verify(publicKey, data, signature); + } +} From 2d6d015c2c17e7a8cf05cdd29409a560cdb3b120 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 2 Jul 2023 03:13:54 -0400 Subject: [PATCH 3/4] Add signature verification to UpdateHelper --- StabilityMatrix/Updater/UpdateHelper.cs | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/StabilityMatrix/Updater/UpdateHelper.cs b/StabilityMatrix/Updater/UpdateHelper.cs index 630c483b..17b8b7c4 100644 --- a/StabilityMatrix/Updater/UpdateHelper.cs +++ b/StabilityMatrix/Updater/UpdateHelper.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Windows.Threading; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using StabilityMatrix.Extensions; using StabilityMatrix.Helper; using StabilityMatrix.Models; using StabilityMatrix.Models.Configs; @@ -62,6 +63,20 @@ public class UpdateHelper : IUpdateHelper httpClientName: "UpdateClient"); } + + /// + /// Data for use in signature verification. + /// Semicolon separated string of fields: + /// "version, releaseDate, channel, type, url, changelog, hashBlake3" + /// + private string GetUpdateInfoSignedData(UpdateInfo updateInfo) + { + var channel = updateInfo.Channel.GetStringValue().ToLowerInvariant(); + return $"{updateInfo.Version};{updateInfo.ReleaseDate:O};{channel};" + + $"{(int) updateInfo.Type};{updateInfo.DownloadUrl};{updateInfo.ChangelogUrl};" + + $"{updateInfo.HashBlake3}"; + } + private async Task CheckForUpdate() { try @@ -83,6 +98,19 @@ public class UpdateHelper : IUpdateHelper logger.LogError("UpdateInfo is null"); return; } + logger.LogInformation("UpdateInfo signature: {Signature}", updateInfo.Signature); + + var updateInfoSignData = GetUpdateInfoSignedData(updateInfo); + logger.LogInformation("UpdateInfo signed data: {SignData}", updateInfoSignData); + + // Verify signature + var checker = new SignatureChecker(); + if (!checker.Verify(updateInfoSignData, updateInfo.Signature)) + { + logger.LogError("UpdateInfo signature is invalid: {Info}", updateInfo); + return; + } + logger.LogInformation("UpdateInfo signature verified"); var currentVersion = Assembly.GetExecutingAssembly().GetName().Version; From 1de010ca45aa31938ebde5fd4049cdd44d67c450 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 2 Jul 2023 03:28:30 -0400 Subject: [PATCH 4/4] Fix datetime format --- StabilityMatrix/Updater/UpdateHelper.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/StabilityMatrix/Updater/UpdateHelper.cs b/StabilityMatrix/Updater/UpdateHelper.cs index 17b8b7c4..3dc9d477 100644 --- a/StabilityMatrix/Updater/UpdateHelper.cs +++ b/StabilityMatrix/Updater/UpdateHelper.cs @@ -72,7 +72,8 @@ public class UpdateHelper : IUpdateHelper private string GetUpdateInfoSignedData(UpdateInfo updateInfo) { var channel = updateInfo.Channel.GetStringValue().ToLowerInvariant(); - return $"{updateInfo.Version};{updateInfo.ReleaseDate:O};{channel};" + + var date = updateInfo.ReleaseDate.ToString("yyyy-MM-ddTHH:mm:ss.ffffffzzz"); + return $"{updateInfo.Version};{date};{channel};" + $"{(int) updateInfo.Type};{updateInfo.DownloadUrl};{updateInfo.ChangelogUrl};" + $"{updateInfo.HashBlake3}"; }