using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace APT.Utility
{
    public static class RSAHelper
    {
        public static (byte[] PublicKey, byte[] PrivateKey) GenerateRsaKeysByte()
        {
            using var rsa = RSA.Create(2048); // 推荐2048位密钥
            var privateKey = rsa.ExportRSAPrivateKey();// rsa.ExportRSAPrivateKeyPem(); // 私钥(PEM格式)
            var publicKey = rsa.ExportRSAPublicKey();//.ExportRSAPublicKeyPem();   // 公钥(PEM格式)
            return (publicKey, privateKey);
        }
        public static (string PublicKey, string PrivateKey) GenerateRsaKeys()
        {
            // 推荐2048位密钥
            using var rsa = RSA.Create(2048);
            //var privateKey = Encoding.UTF8.GetString(rsa.ExportRSAPrivateKey());// 私钥(PEM格式)
            //var publicKey = Encoding.UTF8.GetString(rsa.ExportRSAPublicKey());  // 公钥(PEM格式)
            var privateKey = rsa.ExportRSAPrivateKeyPem();
            var publicKey = rsa.ExportRSAPublicKeyPem();
            //签名
            byte[] dataBytes = Encoding.UTF8.GetBytes("13245");
            byte[] signatureBytes = rsa.SignData(
                dataBytes,
                HashAlgorithmName.SHA256, // 推荐SHA256
                RSASignaturePadding.Pkcs1  //.Pkcs1 // 或RSASignaturePadding.Pss
            );
            string strSignData = Convert.ToBase64String(signatureBytes);
            // //验证 true
            // byte[] dataBytes2 = Encoding.UTF8.GetBytes(strSignData);
            // byte[] signatureBytes2 = Encoding.UTF8.GetBytes("13245");
            // var rrr = rsa.VerifyData(
            //    dataBytes2,
            //    signatureBytes2,
            //    HashAlgorithmName.SHA256,
            //    RSASignaturePadding.Pkcs1  //.Pkcs1 // 必须与签名时一致
            //);
            // //验证 false
            // byte[] signatureBytes3 = Encoding.UTF8.GetBytes("1324235");
            // var rrr3 = rsa.VerifyData(
            //    dataBytes2,
            //    signatureBytes3,
            //    HashAlgorithmName.SHA256,
            //    RSASignaturePadding.Pkcs1  // 必须与签名时一致
            //);
            return (publicKey, privateKey);
        }
        /// 
        /// 使用RSA私钥对数据进行签名
        /// 
        public static byte[] SignData(byte[] data, string privateKey)
        {
            using (var rsa = RSA.Create())
            {
                rsa.FromXmlString(privateKey);
                // 使用SHA256作为哈希算法,PKCS#1 v1.5填充模式
                return rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            }
        }
        /// 
        /// 使用RSA公钥验证签名
        /// 
        public static bool VerifyData(byte[] data, byte[] signature, string publicKey)
        {
            using (var rsa = RSA.Create())
            {
                rsa.FromXmlString(publicKey);
                return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            }
        }
        public static string ExportPublicKeyPem(this RSA rsa)
        {
            var exported = rsa.ExportSubjectPublicKeyInfo();
            return $"-----BEGIN PUBLIC KEY-----\n{Convert.ToBase64String(exported, Base64FormattingOptions.InsertLineBreaks)}\n-----END PUBLIC KEY-----";
        }
        public static string ExportPrivateKeyPem(this RSA rsa)
        {
            var exported = rsa.ExportPkcs8PrivateKey();
            return $"-----BEGIN PRIVATE KEY-----\n{Convert.ToBase64String(exported, Base64FormattingOptions.InsertLineBreaks)}\n-----END PRIVATE KEY-----";
        }
        public static void ImportPublicKeyPem(this RSA rsa, string pem)
        {
            var base64 = pem.Replace("-----BEGIN PUBLIC KEY-----", "")
                           .Replace("-----END PUBLIC KEY-----", "")
                           .Replace("\n", "");
            var bytes = Convert.FromBase64String(base64);
            rsa.ImportSubjectPublicKeyInfo(bytes, out _);
        }
        public static void ImportPrivateKeyPem(this RSA rsa, string pem)
        {
            var base64 = pem.Replace("-----BEGIN PRIVATE KEY-----", "")
                           .Replace("-----END PRIVATE KEY-----", "")
                           .Replace("\n", "");
            var bytes = Convert.FromBase64String(base64);
            rsa.ImportPkcs8PrivateKey(bytes, out _);
        }
        /// 
        /// 扩展方法:导出PEM格式的私钥
        /// 
        /// 
        /// 
        public static string ExportRSAPrivateKeyPem(this RSA rsa)
        {
            var privateKey = rsa.ExportRSAPrivateKey();
            //return Convert.ToBase64String(privateKey, Base64FormattingOptions.InsertLineBreaks);
            return Encoding.UTF8.GetString(privateKey);
            //return "-----BEGIN PRIVATE KEY-----\n" +
            //    Encoding.UTF8.GetString(privateKey)
            //       //Convert.ToBase64String(privateKey, Base64FormattingOptions.InsertLineBreaks) 
            //       + "\n-----END PRIVATE KEY-----";
            //return "-----BEGIN PRIVATE KEY-----" +
            //    Encoding.UTF8.GetString(privateKey)
            //       //Convert.ToBase64String(privateKey, Base64FormattingOptions.InsertLineBreaks) 
            //       + "-----END PRIVATE KEY-----";
        }
        /// 
        /// 扩展方法:导出PEM格式的公钥
        /// 
        /// 
        /// 
        public static string ExportRSAPublicKeyPem(this RSA rsa)
        {
            var publicKey = rsa.ExportRSAPublicKey();
            //return Convert.ToBase64String(publicKey, Base64FormattingOptions.InsertLineBreaks);
            return Encoding.UTF8.GetString(publicKey);
            //return "-----BEGIN PUBLIC KEY-----\n" +
            //    Encoding.UTF8.GetString(publicKey)
            //       //Convert.ToBase64String(publicKey, Base64FormattingOptions.InsertLineBreaks) 
            //       + "\n-----END PUBLIC KEY-----";
            //return "-----BEGIN PUBLIC KEY-----" +
            //    Encoding.UTF8.GetString(publicKey)
            //       //Convert.ToBase64String(publicKey, Base64FormattingOptions.InsertLineBreaks) 
            //       + "-----END PUBLIC KEY-----";
        }
    }
}