1. 程式人生 > >ASP.NET MVC5+EF6+EasyUI 後臺管理系統(62)-EF鏈接串加密

ASP.NET MVC5+EF6+EasyUI 後臺管理系統(62)-EF鏈接串加密

image title orm mst .... 比較 string類 sin isn

前言:

  這一節提供一個簡單的功能,這個功能看似簡單,找了一下沒找到EF鏈接數據庫串的加密幫助文檔,只能自己寫了,這樣也更加符合自己的加密要求

  • 有時候我們發布程序為了避免程序外的SQL鏈接串明文暴露,需要進行一些加密手段!
  • 加密主要分幾類:對稱加密,非對稱加密,散列算法(自己百度腦補,這裏不再多說)
  • 我這裏選擇AES 256位的加密,主要加密速度算法快,安全性高,資源消耗低。
  • 公司一直在使用AES加密來加密一些小數據量的數據,比較方法和安全

  這是我選擇加密AES的理由,當然你可以選擇其他有名的加密算法,比如MD5,SHA,3DES.(註:大公司應該都是禁止自行寫算法的來加解密的)

知識點:

 數據的使用跟我們登錄流程基本都是一樣的,獲取加密鏈接串,然後解密使用

 所以我們需要:

  1. 加密類
  2. 加密工具
  3. EF在何處使用鏈接字符串

1.加密類

技術分享圖片 技術分享圖片
    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;
namespace Apps.Common
{
    public class AESEncryptHelper
    {

        /// <summary>
        /// 獲取密鑰
        /// </summary>
        private static string Key
        {
            get { return @")O[NB]6,YF}+efcaj{+oESb9d8>Z‘e9M"; }
        }

        /// <summary>
        /// 獲取向量
        /// </summary>
        private static string IV
        {
            get { return @"L+\~f4,Ir)b$=pkf"; }
        }

        #region 參數是byte[]類型
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="Data">被加密的明文</param>
        /// <param name="Key">密鑰</param>
        /// <param name="Vector">向量</param>
        /// <returns>密文</returns>
        public static Byte[] AESEncrypt(Byte[] Data, String Key, String Vector)
        {
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);
            Byte[] Cryptograph = null; // 加密後的密文
            Rijndael Aes = Rijndael.Create();
            try
            {
                // 開辟一塊內存流
                using (MemoryStream Memory = new MemoryStream())
                {
                    // 把內存流對象包裝成加密流對象
                    using (CryptoStream Encryptor = new CryptoStream(Memory,
                     Aes.CreateEncryptor(bKey, bVector),
                     CryptoStreamMode.Write))
                    {
                        // 明文數據寫入加密流
                        Encryptor.Write(Data, 0, Data.Length);
                        Encryptor.FlushFinalBlock();

                        Cryptograph = Memory.ToArray();
                    }
                }
            }
            catch
            {
                Cryptograph = null;
            }
            return Cryptograph;
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="Data">被解密的密文</param>
        /// <param name="Key">密鑰</param>
        /// <param name="Vector">向量</param>
        /// <returns>明文</returns>
        public static Byte[] AESDecrypt(Byte[] Data, String Key, String Vector)
        {
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);

            Byte[] original = null; // 解密後的明文

            Rijndael Aes = Rijndael.Create();
            try
            {
                // 開辟一塊內存流,存儲密文
                using (MemoryStream Memory = new MemoryStream(Data))
                {
                    // 把內存流對象包裝成加密流對象
                    using (CryptoStream Decryptor = new CryptoStream(Memory,
                    Aes.CreateDecryptor(bKey, bVector),
                    CryptoStreamMode.Read))
                    {
                        // 明文存儲區
                        using (MemoryStream originalMemory = new MemoryStream())
                        {
                            Byte[] Buffer = new Byte[1024];
                            Int32 readBytes = 0;
                            while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
                            {
                                originalMemory.Write(Buffer, 0, readBytes);
                            }

                            original = originalMemory.ToArray();
                        }
                    }
                }
            }
            catch
            {
                original = null;
            }
            return original;
        }

        #endregion

        #region 參數是string類型

      

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="plainStr">明文字符串</param>
        /// <returns>密文</returns>
        public static string AESEncrypt(string plainStr)
        {
            byte[] bKey = Encoding.UTF8.GetBytes(Key);
            byte[] bIV = Encoding.UTF8.GetBytes(IV);
            byte[] byteArray = Encoding.UTF8.GetBytes(plainStr);

            string encrypt = null;
            Rijndael aes = Rijndael.Create();
            using (MemoryStream mStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateEncryptor(bKey, bIV), CryptoStreamMode.Write))
                {
                    cStream.Write(byteArray, 0, byteArray.Length);
                    cStream.FlushFinalBlock();
                    encrypt = Convert.ToBase64String(mStream.ToArray());
                }
            }
            aes.Clear();
            return encrypt;
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="plainStr">明文字符串</param>
        /// <param name="returnNull">加密失敗時是否返回 null,false 返回 String.Empty</param>
        /// <returns>密文</returns>
        public static string AESEncrypt(string plainStr, bool returnNull)
        {
            string encrypt = AESEncrypt(plainStr);
            return returnNull ? encrypt : (encrypt == null ? String.Empty : encrypt);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="encryptStr">密文字符串</param>
        /// <returns>明文</returns>
        public static string AESDecrypt(string encryptStr)
        {
            byte[] bKey = Encoding.UTF8.GetBytes(Key);
            byte[] bIV = Encoding.UTF8.GetBytes(IV);
            byte[] byteArray = Convert.FromBase64String(encryptStr);

            string decrypt = null;
            Rijndael aes = Rijndael.Create();
            using (MemoryStream mStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateDecryptor(bKey, bIV), CryptoStreamMode.Write))
                {
                    cStream.Write(byteArray, 0, byteArray.Length);
                    cStream.FlushFinalBlock();
                    decrypt = Encoding.UTF8.GetString(mStream.ToArray());
                }
            }
            aes.Clear();
            return decrypt;
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="encryptStr">密文字符串</param>
        /// <param name="returnNull">解密失敗時是否返回 null,false 返回 String.Empty</param>
        /// <returns>明文</returns>
        public static string AESDecrypt(string encryptStr, bool returnNull)
        {
            string decrypt = AESDecrypt(encryptStr);
            return returnNull ? decrypt : (decrypt == null ? String.Empty : decrypt);
        }


        #endregion

        #region 256位AES加密算法

        /// <summary>
        /// 256位AES加密
        /// </summary>
        /// <param name="toEncrypt"></param>
        /// <returns></returns>
        public static string Encrypt(string toEncrypt)
        {
            // 256-AES key    
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(Key);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        /// <summary>
        /// 256位AES解密
        /// </summary>
        /// <param name="toDecrypt"></param>
        /// <returns></returns>
        public static string Decrypt(string toDecrypt)
        {
            // 256-AES key    
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(Key);
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return UTF8Encoding.UTF8.GetString(resultArray);
        }

        #endregion
    }
}
技術分享圖片

網上一抓一大把,自己搜索想要的加密類啦!

2.加密工具

加密工具這個網上抓不到,需要自己結合加密類來開發,這個不用我帶領大夥來開發吧,好吧

新建一個WinFrom程序,命名Apps.EncryptHelper,引用你加密類的所在的類庫,或者直接放到Apps.EncryptHelper下就可以

技術分享圖片

從工具欄拉取2個TextBox和2個Button排版好,基本頁面就做完了,最後分別雙擊兩個按鈕進入事件實現代碼

技術分享圖片
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Apps.Common;
namespace Apps.EncryptHelper
{
    public partial class Encrypt : Form
    {
        public Encrypt()
        {
            InitializeComponent();
        }
        //加密
        private void btnEncrypt_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtSourceText.Text))
            {
                MessageBox.Show("沒數據加毛密-_-!");
                return;
            }
            else
            {
               txtResultText.Text = AESEncryptHelper.Encrypt(txtSourceText.Text);
            }
        }
        //解密
        private void btnDecrypt_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtSourceText.Text))
            {
                MessageBox.Show("沒數據解毛密-_-!");
                return;
            }
            else if (!IsBase64Formatted(txtSourceText.Text))
            {
                MessageBox.Show("別逗了,我只認識被我加過密的?");
                return;
            }
            else
            {
                txtResultText.Text = AESEncryptHelper.Decrypt(txtSourceText.Text);
            }
        }

        public static bool IsBase64Formatted(string input)
        {
            try
            {
                Convert.FromBase64String(input);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
技術分享圖片

幾十行代碼,解決車房老婆問題!運行....

技術分享圖片技術分享圖片.

3.結合進EF

這塊還是比較容易搞定的

第一:找到web.config的connectionStrings的EF鏈接串

第二:把修改對應Key串的Value

技術分享圖片
  <connectionStrings>
    <add name="DBContainer" connectionString="ka7ocMA8nEYPjbQYUlVwbsmTeIdxKGE+ZfXAu3/0eMhVRP+iN+9ECpY/lItoY9vfZVDA9EVgmMzH/8Z0rxRIhGPRhVMFWliBuJ9RDGtHbqRY02voyLbrZ7IiXRnXyhlLFsvgj23KXnHl8J6jxB1QNsmuUxPlqnD6HP9y5RQq2EJ//OT+uKqhVC1qUqVzdY+XR6HX/O5jGk6kJGk3Nk83qo09eBOundO7OdxQG9SXPUYNyZjhyx9YV2/1UbghuxHrxHrAuxiE4mJLqH/rusjAy8d3LS/ROiiBszSY+I400Ce4NigDwZaG679yvBKBQ5pg" providerName="System.Data.EntityClient" />
  </connectionStrings>
技術分享圖片

第三:找到EF讀取串的地方

技術分享圖片

這裏必須讀取解密後發的字符串,所以我們再寫一個方法來獲取解密後的字符串ConfigPara

技術分享圖片
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Apps.Common
{
    public class ConfigPara
    {
        public static string EFDBConnection {
            get {
                string connection = System.Configuration.ConfigurationManager.ConnectionStrings["DBContainer"].ConnectionString;
                return AESEncryptHelper.Decrypt(connection);
            }
        }
    }
}
技術分享圖片

技術分享圖片

註意修改後也是沒有用的,會回檔,因為這個類是根據T4生成的,所以我們必須修改T4

技術分享圖片

修改對應紅框的位置!

搞破壞的,難道你現在還能看懂我的連接串?:-)

技術分享圖片

ok。實現加密,運行正常

技術分享圖片

大家趕快把他繼承到系統裏面!

謝謝大家!

ASP.NET MVC5+EF6+EasyUI 後臺管理系統(62)-EF鏈接串加密