using System;
using System.Security.Cryptography;
using System.Text;
namespace LJLib.Tools.DEncrypt
{
    /// <summary> 
    /// RSA加密解密及RSA签名和验证
    /// </summary> 
    public static class RSACryption
    {

        #region RSA 加密解密

        #region RSA 的密钥产生

        /// <summary>
        /// RSA 的密钥产生 产生私钥 和公钥 
        /// </summary>
        public static void RSAKey(out string privateKey, out string publicKey)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {
                privateKey = rsa.ToXmlString(true);
                publicKey = rsa.ToXmlString(false);
            }
        }
        #endregion

        #region RSA的加密函数
        //############################################################################## 
        //RSA 方式加密 
        //说明KEY必须是XML的行式,返回的是字符串 
        //在有一点需要说明！！该加密方式有 长度 限制的！！ 
        //############################################################################## 

        //RSA的加密函数  string
        public static string RSAEncrypt(string publicKey, string source)
        {
            return Convert.ToBase64String(RSAEncrypt(publicKey, Encoding.UTF8.GetBytes(source)));
        }
        //RSA的加密函数 byte[]
        public static byte[] RSAEncrypt(string publicKey, byte[] source)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(publicKey);
                return rsa.Encrypt(source, false);
            }
        }
        #endregion

        #region RSA的解密函数
        //RSA的解密函数  string
        public static string RSADecrypt(string privateKey, string base64Str)
        {
            return Encoding.UTF8.GetString(RSADecrypt(privateKey, Convert.FromBase64String(base64Str)));
        }

        //RSA的解密函数  byte
        public static byte[] RSADecrypt(string privateKey, byte[] destData)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(privateKey);
                return rsa.Decrypt(destData, false);
            }
        }
        #endregion

        #endregion

        #region RSA数字签名

        #region RSA签名
        //RSA签名 
        public static string SignData(string privateKey, string source)
        {
            return SignData(privateKey, Encoding.UTF8.GetBytes(source));
        }

        //RSA签名 
        public static string SignData(string privateKey, byte[] source)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(privateKey);
                var RSAFormatter = new RSAPKCS1SignatureFormatter(rsa);
                //RSAFormatter.SetHashAlgorithm("MD5");

                //var md5 = new LJLib.Tools.Encry.MD5();
                ////执行签名 
                //return Convert.ToBase64String(RSAFormatter.CreateSignature(md5.ComputeHash(source)));

                RSAFormatter.SetHashAlgorithm("SHA256");

                var sha = new LJLib.Tools.Encry.sha256();
                //执行签名 
                return Convert.ToBase64String(RSAFormatter.CreateSignature(sha.Getsha256(source)));

            }
        }

        #endregion

        #region RSA 签名验证

        public static bool Verify(string publicKey, string source, string signData)
        {
            return Verify(publicKey, Encoding.UTF8.GetBytes(source), signData);
        }

        public static bool Verify(string publicKey, byte[] source, string signData)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(publicKey);
                var RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
                //RSADeformatter.SetHashAlgorithm("MD5");

                //var md5 = new LJLib.Tools.Encry.MD5();

                //return RSADeformatter.VerifySignature(md5.ComputeHash(source), Convert.FromBase64String(signData));

                RSADeformatter.SetHashAlgorithm("SHA256");

                var sha = new LJLib.Tools.Encry.sha256();

                return RSADeformatter.VerifySignature(sha.Getsha256(source), Convert.FromBase64String(signData));
            }
        }

        #endregion


        #endregion

    }
}
