using AnotherReplayReader.PluginSystem; using AnotherReplayReader.Utils; using Microsoft.Win32; using System; using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text.Json; using System.Threading.Tasks; namespace AnotherReplayReader { internal static class Plugin { public static Task<bool> LoadPlayerIdentityPlugin(PlayerIdentity playerIdentity) { return Task.Run(async () => { var name = $"{nameof(AnotherReplayReader)}.{nameof(PlayerIdentity)}"; var fileName = Path.Combine(App.LibsFolder, $"{name}.dll"); if (File.Exists(fileName)) { var assembly = await Load(fileName); var pluginType = assembly.GetType($"{name}.Plugin", true); var plugin = (IPlugin)Activator.CreateInstance(pluginType); Auth.LoadPlugin(plugin); playerIdentity.LoadPlugin(plugin); return true; } return false; }); } public static async Task<Assembly> Load(string path) { using var file = File.OpenRead(path); using var metaFile = File.OpenRead($"{path}.meta"); var metaTask = JsonSerializer.DeserializeAsync<VerifierPayload>(metaFile, Network.CommonJsonOptions); using var memory = new MemoryStream(); await file.CopyToAsync(memory); var array = memory.ToArray(); using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(array); var meta = await metaTask ?? throw new InvalidDataException("Failed to load meta file"); if (!Enumerable.SequenceEqual(hash, meta.ByteData.Value)) { throw new InvalidDataException($"Hash does not match, might be corrupt {Convert.ToBase64String(hash)} vs {meta.Data}"); } if (!Verifier.Verify(meta)) { throw new InvalidDataException("Invalid metadata, might be corrupt"); } return Assembly.Load(array); } public static void Sign() { var openFileDialog = new OpenFileDialog { Filter = "dll (*.dll)|*.dll|所有文件 (*.*)|*.*", InitialDirectory = AppContext.BaseDirectory, }; var result = openFileDialog.ShowDialog(); if (result is true) { using var file = openFileDialog.OpenFile(); using var memory = new MemoryStream(); file.CopyTo(memory); using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(memory.ToArray()); Verifier.Sign(hash); } } } }