using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace ASHermed.SinoInterface.Tools
{

    /// <summary>
    /// cigna提供的加解密方法
    /// </summary>
    public class CignaHelper
    {

        public static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd)
        {
            //var pc = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.MachineKeySet);
            //return (RSACryptoServiceProvider)pc.PrivateKey;
            var cer = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.Exportable);//X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable
            var rsaParam = cer.GetRSAPrivateKey().ExportParameters(true);
            var rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(rsaParam);
            return rsa;
        }

        public static RSACryptoServiceProvider GetPublicKey(string pubKeyFile)
        {
            //var pc = new X509Certificate2(pubKeyFile);
            //return (RSACryptoServiceProvider)pc.PublicKey.Key;
            var cer = new X509Certificate2(pubKeyFile);
            var rsaParam = cer.GetRSAPublicKey().ExportParameters(false);
            var rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(rsaParam);
            return rsa;

        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static string Encrypt(string plaintext, RSACryptoServiceProvider provider)
        {
            using (RSACryptoServiceProvider RSACryptography = provider)
            {
                byte[] PlaintextData = Encoding.UTF8.GetBytes(plaintext);
                int MaxBlockSize = RSACryptography.KeySize / 8 - 11;    //加密块最大长度限制


                if (PlaintextData.Length <= MaxBlockSize)
                    return Convert.ToBase64String(RSACryptography.Encrypt(PlaintextData, false));


                using (MemoryStream PlaiStream = new MemoryStream(PlaintextData))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);


                    while (BlockSize > 0)
                    {
                        byte[] ToEncrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);


                        byte[] Cryptograph = RSACryptography.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);


                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }


                    return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
                }
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static string Decrypt(string ciphertext, RSACryptoServiceProvider provider)
        {
            using (RSACryptoServiceProvider RSACryptography = provider)
            {
                byte[] CiphertextData = Convert.FromBase64String(ciphertext);
                int MaxBlockSize = RSACryptography.KeySize / 8;    //解密块最大长度限制


                if (CiphertextData.Length <= MaxBlockSize)
                    return Encoding.UTF8.GetString(RSACryptography.Decrypt(CiphertextData, false));


                using (MemoryStream CrypStream = new MemoryStream(CiphertextData))
                using (MemoryStream PlaiStream = new MemoryStream())
                {
                    byte[] Buffer = new byte[MaxBlockSize];
                    int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);


                    while (BlockSize > 0)
                    {
                        byte[] ToDecrypt = new byte[BlockSize];
                        Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);


                        byte[] Plaintext = RSACryptography.Decrypt(ToDecrypt, false);
                        PlaiStream.Write(Plaintext, 0, Plaintext.Length);


                        BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                    }


                    return Encoding.UTF8.GetString(PlaiStream.ToArray());
                }
            }
        }

        public static string Sign(string xml, RSACryptoServiceProvider pubProvider)
        {
            //Console.WriteLine("加载数字证书私钥：" + pfxpath + "证书密码：" + pfxpassword);
            //签名 
            //Console.WriteLine("--------开始使用私钥创建例子");
            //Console.WriteLine("--------需要签名的：" + xml);
            // X509Certificate2 objx5092 = new X509Certificate2(pfxpath, pfxpassword);   //当前用户存储，本地测试
            //X509Certificate2 objx5092 = new X509Certificate2(priKeyFile, keyPwd, X509KeyStorageFlags.Exportable);   //本地存储，服务器测试(windows server2008)要使用这个

            //RSACryptoServiceProvider rsa = objx5092.PrivateKey as RSACryptoServiceProvider;
            byte[] data = Encoding.GetEncoding("utf-8").GetBytes(xml);
            byte[] hashValue = pubProvider.SignData(data, "MD5");
            string msg = Convert.ToBase64String(hashValue);
            //Console.WriteLine("--------得到：" + msg);

            return msg;
        }


        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

    }
}

