using System.Globalization; using System.Text.Json.Serialization; using Semver; using StabilityMatrix.Core.Converters.Json; using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Core.Models.Update; public record UpdateInfo { [JsonConverter(typeof(SemVersionJsonConverter))] public required SemVersion Version { get; init; } public required DateTimeOffset ReleaseDate { get; init; } public UpdateChannel Channel { get; init; } public UpdateType Type { get; init; } public required Uri Url { get; init; } public required Uri Changelog { get; init; } /// /// Blake3 hash of the file /// public required string HashBlake3 { get; init; } /// /// ED25519 signature of the semicolon seperated string: /// "version + releaseDate + channel + type + url + changelog + hash_blake3" /// verifiable using our stored public key /// public required string Signature { get; init; } /// /// Data for use in signature verification. /// Semicolon separated string of fields: /// "version, releaseDate, channel, type, url, changelog, hashBlake3" /// public string GetSignedData() { var channel = Channel.GetStringValue().ToLowerInvariant(); var date = FormatDateTimeOffsetInvariant(ReleaseDate); return $"{Version};{date};{channel};" + $"{(int)Type};{Url};{Changelog};" + $"{HashBlake3}"; } /// /// Format a DatetimeOffset to a culture invariant string for use in signature verification. /// private static string FormatDateTimeOffsetInvariant(DateTimeOffset dateTimeOffset) { return dateTimeOffset.ToString( @"yyyy-MM-ddTHH\:mm\:ss.ffffffzzz", CultureInfo.InvariantCulture ); } }