Browse Source

Merge pull request #135 from ionite34/update-signatures

pull/14/head
Ionite 1 year ago committed by GitHub
parent
commit
08f4a437c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      StabilityMatrix/StabilityMatrix.csproj
  2. 51
      StabilityMatrix/Updater/SignatureChecker.cs
  3. 29
      StabilityMatrix/Updater/UpdateHelper.cs

1
StabilityMatrix/StabilityMatrix.csproj

@ -33,6 +33,7 @@
<PackageReference Include="NCode.ReparsePoints" Version="1.0.2" /> <PackageReference Include="NCode.ReparsePoints" Version="1.0.2" />
<PackageReference Include="NLog" Version="5.2.0" /> <PackageReference Include="NLog" Version="5.2.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.0" /> <PackageReference Include="NLog.Extensions.Logging" Version="5.3.0" />
<PackageReference Include="NSec.Cryptography" Version="22.4.0" />
<PackageReference Include="Octokit" Version="6.2.1" /> <PackageReference Include="Octokit" Version="6.2.1" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="Polly" Version="7.2.4" /> <PackageReference Include="Polly" Version="7.2.4" />

51
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;
/// <summary>
/// Initializes a new instance of SignatureChecker.
/// </summary>
/// <param name="publicKeyPkix">Pkix format public key. Defaults to update verification key.</param>
public SignatureChecker(string? publicKeyPkix = null)
{
publicKey = PublicKey.Import(
Algorithm,
Encoding.ASCII.GetBytes(publicKeyPkix ?? UpdatePublicKey),
KeyBlobFormat.PkixPublicKeyText);
}
/// <summary>
/// Verifies the signature of provided data.
/// </summary>
/// <param name="data">Data to verify</param>
/// <param name="signature">Signature in base64 encoding</param>
/// <returns>True if verified</returns>
public bool Verify(string data, string signature)
{
var signatureBytes = Convert.FromBase64String(signature);
return Algorithm.Verify(publicKey, Encoding.UTF8.GetBytes(data), signatureBytes);
}
/// <summary>
/// Verifies the signature of provided data.
/// </summary>
/// <param name="data">Data to verify</param>
/// <param name="signature">Signature in base64 encoding</param>
/// <returns>True if verified</returns>
public bool Verify(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature)
{
return Algorithm.Verify(publicKey, data, signature);
}
}

29
StabilityMatrix/Updater/UpdateHelper.cs

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using System.Windows.Threading; using System.Windows.Threading;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using StabilityMatrix.Extensions;
using StabilityMatrix.Helper; using StabilityMatrix.Helper;
using StabilityMatrix.Models; using StabilityMatrix.Models;
using StabilityMatrix.Models.Configs; using StabilityMatrix.Models.Configs;
@ -62,6 +63,21 @@ public class UpdateHelper : IUpdateHelper
httpClientName: "UpdateClient"); httpClientName: "UpdateClient");
} }
/// <summary>
/// Data for use in signature verification.
/// Semicolon separated string of fields:
/// "version, releaseDate, channel, type, url, changelog, hashBlake3"
/// </summary>
private string GetUpdateInfoSignedData(UpdateInfo updateInfo)
{
var channel = updateInfo.Channel.GetStringValue().ToLowerInvariant();
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}";
}
private async Task CheckForUpdate() private async Task CheckForUpdate()
{ {
try try
@ -83,6 +99,19 @@ public class UpdateHelper : IUpdateHelper
logger.LogError("UpdateInfo is null"); logger.LogError("UpdateInfo is null");
return; 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; var currentVersion = Assembly.GetExecutingAssembly().GetName().Version;

Loading…
Cancel
Save