using Furion;
using Furion.FriendlyException;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Ewide.Core.Util
{
    public static class RSAHandler
    {
        /// <summary>
        /// XML 文件转成PEM 公钥格式
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="saveFile"></param>
        /// <returns></returns>
        public static string Xml2PemPublic(string xml, string saveFile)  
        {
            var rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(xml); var p = rsa.ExportParameters(false);
            RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent)); using (var sw = new StreamWriter(saveFile))
            {
                var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
                pemWriter.WriteObject(key);
            }
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key); byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            string publicKey = Convert.ToBase64String(serializedPublicBytes);
            return Format(publicKey, 1);
        }
        /// <summary>
        /// 格式化
        /// </summary>
        /// <param name="key"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static string Format(string key, int type)
        {
            string result = string.Empty;
            int length = key.Length / 64; 
            for (int i = 0; i < length; i++)
            {
                int start = i * 64;
                result = result + key.Substring(start, 64) + "\r\n";
            }
            result = result + key.Substring(length * 64); 
            if (type == 1)
            {
                result = result.Insert(0, "-----BEGIN PUBLIC KEY-----\r\n");
                result += "\r\n-----END PUBLIC KEY-----";
            }
            if (type == 2)
            {
                result = result.Insert(0, "-----BEGIN PRIVATE KEY-----\r\n");
                result += "\r\n-----END PRIVATE KEY-----";
            }
            return result;
        }
        /// <summary>
        /// RSA加密  公钥
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string RSAEncrypt(string content)
        {
            string publickey = App.Configuration["RSA:publickey"];
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            rsa.FromXmlString(publickey);
            cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
            return Convert.ToBase64String(cipherbytes);
        }

        /// <summary>
        /// RSA解密 私钥
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string RSADecrypt(string content)
        {
            string privatekey = App.Configuration["RSA:privatekey"];
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] cipherbytes;
            try
            {   //很有可能是报文被修改 情况很小
                rsa.FromXmlString(privatekey);
                cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), false);
                return Encoding.UTF8.GetString(cipherbytes);
            }
            catch
            {
                throw Oops.Oh(ErrorCode.D1000);
            }
        }
    }
}
