116 lines
4.9 KiB
C#

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<byte[]> ByteData { get; }
[JsonIgnore]
public Lazy<byte[]> 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 = @"<RSAKeyValue><Modulus>3vw5CoFRDFt2ri4jLDTu75cw1U/tCRjya7q8X/IdULaOJOYG8C+uqrF2Atb4ou+4SrmF+bvJM9cFsf3yO7XpeIDpkxD3KGbIEw+0JixTIIm+y5xlLKDDwbZHnYjJOBTt6JBn0yqwx7vY2UEZIcRU6wlOmUapnkpiaC2anNhSPqk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
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<byte>(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<VerifierPayload>(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);
}
}
}
}