using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Windows; namespace AnotherReplayReader.Utils { internal class VerifierPayload { public string Data { get; } public string Signature { get; } [JsonIgnore] public Lazy ByteData { get; } [JsonIgnore] public Lazy ByteSignature { get; } public VerifierPayload(string data, string signature) { Data = data; Signature = signature; ByteData = new(() => Convert.FromBase64String(Data), LazyThreadSafetyMode.PublicationOnly); ByteSignature = new(() => Convert.FromBase64String(Signature), LazyThreadSafetyMode.PublicationOnly); } public static VerifierPayload FromBytes(byte[] data, byte[] signature) { return new(Convert.ToBase64String(data), Convert.ToBase64String(signature)); } } internal class Verifier { private const string _publicKey = @"3vw5CoFRDFt2ri4jLDTu75cw1U/tCRjya7q8X/IdULaOJOYG8C+uqrF2Atb4ou+4SrmF+bvJM9cFsf3yO7XpeIDpkxD3KGbIEw+0JixTIIm+y5xlLKDDwbZHnYjJOBTt6JBn0yqwx7vY2UEZIcRU6wlOmUapnkpiaC2anNhSPqk=AQAB"; public static bool Verify(VerifierPayload payload) { using var rsa = new RSACng(); rsa.FromXmlString(_publicKey); return rsa.VerifyData(payload.ByteData.Value, payload.ByteSignature.Value, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); } public static void Sign(object sample) { var fileName = Path.GetTempFileName(); try { var ea = Enumerable.Repeat(0xEA, 1024).ToArray(); const string splitter = "|DuplexBarrier|"; var isByteArray = false; if (sample is string sampleText) { File.WriteAllText(fileName, $"输入私钥信息以及需要签名的数据,用 `{splitter}` 分开\r\n\r\n{sampleText}"); } else if (sample is byte[] readyArray) { isByteArray = true; File.WriteAllText(fileName, $"输入私钥信息以及需要签名的数据{splitter}{Convert.ToBase64String(readyArray)}{splitter}"); } using (var process = Process.Start("notepad.exe", fileName)) { process.WaitForExit(); } var splitted = File.ReadAllText(fileName).Split(new[] { splitter }, StringSplitOptions.RemoveEmptyEntries); File.WriteAllBytes(fileName, ea); byte[] bytes; byte[] signature; using (var rsa = new RSACng()) { rsa.FromXmlString(splitted[0]); var text = splitted[1]; splitted = null; GC.Collect(); MessageBox.Show(text, $"快来确认一下~"); bytes = isByteArray ? Convert.FromBase64String(text) : Encoding.UTF8.GetBytes(text); signature = rsa.SignData(bytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); } GC.Collect(); var payload = VerifierPayload.FromBytes(bytes, signature); var serialized = JsonSerializer.Serialize(payload, Network.CommonJsonOptions); var choice = MessageBox.Show(serialized, "嗯哼", MessageBoxButton.YesNo); while (choice == MessageBoxResult.Yes) { File.WriteAllText(fileName, serialized); using (var process = Process.Start("notepad.exe", fileName)) { process.WaitForExit(); } using var rsa = new RSACng(); rsa.FromXmlString(_publicKey); var checkContent = File.ReadAllText(fileName); var check = JsonSerializer.Deserialize(checkContent, Network.CommonJsonOptions) ?? new("", ""); var checkData = Convert.FromBase64String(check.Data); var checkSignature = Convert.FromBase64String(check.Signature); var verified = rsa.VerifyData(checkData, checkSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); choice = MessageBox.Show($"结果:{verified}", "嗯哼", MessageBoxButton.YesNo); } } finally { File.Delete(fileName); } } } }