//==============================================================
//  版权所有：深圳杰文科技
//  文件名：Security.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者： Jay
//  修改时间：2020-1-13
//  修改说明： 增加AES
//==============================================================

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Infrastructure.Utilities
{
	//加密算法
	public static class Encrypt
	{
		public const string CommonPassword = "Abcdef-123456_!@#$%^";

		#region - AES -

		public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
		{
			byte[] encryptedBytes = null;

			// Set your salt here, change it to meet your flavor:
			// The salt bytes must be at least 8 bytes.
			byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

			using (MemoryStream ms = new MemoryStream())
			{
				using (RijndaelManaged AES = new RijndaelManaged())
				{
					AES.KeySize = 256;
					AES.BlockSize = 128;

					var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
					AES.Key = key.GetBytes(AES.KeySize / 8);
					AES.IV = key.GetBytes(AES.BlockSize / 8);

					AES.Mode = CipherMode.CBC;

					using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
					{
						cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
						cs.Close();
					}
					encryptedBytes = ms.ToArray();
				}
			}

			return encryptedBytes;
		}

		public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
		{
			byte[] decryptedBytes = null;

			// Set your salt here, change it to meet your flavor:
			// The salt bytes must be at least 8 bytes.
			byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

			using (MemoryStream ms = new MemoryStream())
			{
				using (RijndaelManaged AES = new RijndaelManaged())
				{
					AES.KeySize = 256;
					AES.BlockSize = 128;

					var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
					AES.Key = key.GetBytes(AES.KeySize / 8);
					AES.IV = key.GetBytes(AES.BlockSize / 8);

					AES.Mode = CipherMode.CBC;

					using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
					{
						cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
						cs.Close();
					}
					decryptedBytes = ms.ToArray();
				}
			}

			return decryptedBytes;
		}


		public static string EncryptText(string input, string password)
		{
			// Get the bytes of the string
			byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
			byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

			// Hash the password with SHA256
			passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

			byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

			string result = Convert.ToBase64String(bytesEncrypted);

			return result;
		}

		public static string DecryptText(string input, string password)
		{
			// Get the bytes of the string
			byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
			byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
			passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

			byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);

			string result = Encoding.UTF8.GetString(bytesDecrypted);

			return result;
		}

		#endregion

		#region - DES -

		/// <summary>
		/// DES算法加密字符串
		/// </summary>
		/// <param name="key">密钥</param>
		/// <param name="iv">初始化向量</param>
		/// <param name="source">源字符串</param>
		/// <returns>加密后的字符串</returns>
		public static string DesEncrype(string key, string iv, string source)
		{
			byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(key);
			byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(iv);
			DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write))
                {

                    using (StreamWriter sw = new StreamWriter(cst))
                    {
                        sw.Write(source);
                        sw.Flush();
                        cst.FlushFinalBlock();
                        sw.Flush();
                        return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
                    }
                }
            }
		}

		/// <summary>
		/// DES算法解密字符串
		/// </summary>
		/// <param name="key">密钥</param>
		/// <param name="iv">初始化向量</param>
		/// <param name="source">源字符串</param>
		/// <returns>解密后的字符串</returns>
		public static string DesDecrype(string key, string iv, string source)
		{
			byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(key);
			byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(iv);
			byte[] byEnc = Convert.FromBase64String(source);

			DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream(byEnc))
            {
                using (CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read))
                {
                    using (StreamReader sr = new StreamReader(cst))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
		}

		#endregion

		#region - MD5 -

		/// <summary>
		/// MD5加密
		/// 注意，MD5算法是不可逆的，所以MD5只能比较加密后的值。
		/// </summary>
		/// <param name="toCryString"></param>
		/// <returns></returns>
		public static string MD5(string toCryString)
		{
            if (!string.IsNullOrEmpty(toCryString))
            {
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                byte[] b = Encoding.Default.GetBytes(toCryString);
                return BitConverter.ToString(md5.ComputeHash(b)).Replace("-", "");
            }

            return "";
		}

		#endregion

		#region - 加、解密byte数组 -

		public static byte[] EncryptBytes(byte[] bytes, string key, string iv)
		{
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			des.Key = Encoding.ASCII.GetBytes(key);
            des.IV = Encoding.ASCII.GetBytes(iv);
			ICryptoTransform desencrypt = des.CreateEncryptor();
			return desencrypt.TransformFinalBlock(bytes, 0, bytes.Length);
		}

        public static byte[] DecryptBytes(byte[] bytes, string key, string iv)
		{
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			des.Key = Encoding.ASCII.GetBytes(key);
            des.IV = Encoding.ASCII.GetBytes(iv);
			ICryptoTransform desencrypt = des.CreateDecryptor();
			return desencrypt.TransformFinalBlock(bytes, 0, bytes.Length);
		}

		#endregion
	}
}
