// 依赖: .NET 6+ (System.Security.Cryptography + HttpClient)
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

class KamiClient
{
    const string Base   = "{{BASE}}";
    const string PubUrl = "{{PUBKEY}}";
    const string Verify = "{{VERIFY}}";
    const string Code   = "YOUR-CARD-KEY";

    // 每块 190 字节, 以 | 连接
    static string Encrypt(string plain, RSA pub)
    {
        byte[] data = Encoding.UTF8.GetBytes(plain);
        var parts = new List<string>();
        for (int i = 0; i < data.Length; i += 190)
        {
            int len = Math.Min(190, data.Length - i);
            byte[] chunk = data.Skip(i).Take(len).ToArray();
            parts.Add(Convert.ToBase64String(pub.Encrypt(chunk, RSAEncryptionPadding.OaepSHA1)));
        }
        return string.Join("|", parts);
    }

    static string Decrypt(string cipher, RSA priv) =>
        string.Join("", cipher.Split('|').Select(p =>
            Encoding.UTF8.GetString(priv.Decrypt(Convert.FromBase64String(p), RSAEncryptionPadding.OaepSHA1))));

    static async Task Main()
    {
        var http = new HttpClient();

        // 1. 获取服务器公钥
        string pubJson = await http.GetStringAsync(PubUrl);
        string serverPem = JsonDocument.Parse(pubJson).RootElement
            .GetProperty("data").GetProperty("public_key").GetString()!;
        var serverPub = RSA.Create();
        serverPub.ImportFromPem(serverPem);

        // 2. 生成客户端密钥对
        var client = RSA.Create(2048);
        string clientPub = client.ExportSubjectPublicKeyInfoPem();

        // 3. 组装并加密请求
        string payload = JsonSerializer.Serialize(new Dictionary<string, object>
        {
            ["code"] = Code,
            ["timestamp"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
            ["client_public_key"] = clientPub,
        });
        string body = JsonSerializer.Serialize(new Dictionary<string, string>
        {
            ["encrypted"] = Encrypt(payload, serverPub),
        });

        // 4. 发送请求
        var content = new StringContent(body, Encoding.UTF8, "application/json");
        string resp = await (await http.PostAsync(Verify, content)).Content.ReadAsStringAsync();

        // 5. 解密响应
        using var doc = JsonDocument.Parse(resp);
        if (doc.RootElement.TryGetProperty("encrypted", out var enc))
            Console.WriteLine(Decrypt(enc.GetString()!, client));
        else
            Console.WriteLine(resp);
    }
}
