系列目錄
前言:
這一節提供一個簡單的功能,這個功能看似簡單,找了一下沒找到EF鏈接數據庫串的加密幫助文檔,只能自己寫了,這樣也更加符合自己的加密要求
- 有時候我們發布程序為了避免程序外的SQL鏈接串明文暴露,需要進行一些加密手段!
- 加密主要分幾類:對稱加密,非對稱加密,散列算法(自己百度腦補,這里不再多說)
- 我這里選擇AES 256位的加密,主要加密速度算法快,安全性高,資源消耗低。
- 公司一直在使用AES加密來加密一些小數據量的數據,比較方法和安全
這是我選擇加密AES的理由,當然你可以選擇其他有名的加密算法,比如MD5,SHA,3DES.(注:大公司應該都是禁止自行寫算法的來加解密的)
知識點:
數據的使用跟我們登錄流程基本都是一樣的,獲取加密鏈接串,然后解密使用
所以我們需要:
- 加密類
- 加密工具
- 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。實現加密,運行正常
大家趕快把他繼承到系統里面!
謝謝大家!