手裡在做的一個自用的多用戶進銷存項目,碰到了以下使用場景: 1、為了每個店鋪/倉庫的用戶都能及時獲得更新,軟體採用了clickOnce部署方式,這就導致了只要知道發佈地址,任何人都可以進行下載了。 2、現在只購買了一個SQL資料庫空間,並沒有購買虛擬主機之類的web空間(部署用的空間是用3322解析 ...
手裡在做的一個自用的多用戶進銷存項目,碰到了以下使用場景:
1、為了每個店鋪/倉庫的用戶都能及時獲得更新,軟體採用了clickOnce部署方式,這就導致了只要知道發佈地址,任何人都可以進行下載了。
2、現在只購買了一個SQL資料庫空間,並沒有購買虛擬主機之類的web空間(部署用的空間是用3322解析到自己的電腦上的),所以也沒辦法採用websevices來進行中間層操作了,只能用客戶端直接連接。
客戶端連接資料庫最大的隱患就是如果被反編譯的話會直接暴露資料庫地址,非常不安全,通常情況下採用的加密和解密都需要寫到程式里,如果被反編譯的話也會一併暴露,達不到加密目的。
項目中我採用了一個取巧的方法:利用文件的數字簽名作為密鑰來進行加密,具體的做法就是:
1、在系統指定位置放一個KEY文件,軟體讀取該文件的MD5值作為密鑰,對連接字元串進行AES/DES加密,將加密後的字元串放到軟體的配置文件中。
2、把該KEY文件會直接發放給使用的用戶(內部系統,使用人員可控),放到指定的系統路徑中,軟體讀取該文件的MD5值作為密鑰然後進行DES/AES解密。
好處就是:即使程式被反編譯,看到的也是加密後的字元串,拿不到key文件就無法進行解密。
而key文件則是通過另外的方式進行分發,並不隨軟體一起發佈,即使下載了程式,也還是拿不到key文件。
思路有了 實現起來也是非常的簡單:
第一步:準備一個KEY文件,可以是任意文件,一張圖片,一個文檔,或者一首歌曲,註意:該文件一旦被作為KEY文件將不能在有任何修改,否則MD5值就改變了,也就無法再解密。
第二部:讀取改文件的MD5值,核心代碼:(因為加密密鑰需要是8位,所以任意截取結果中的8位即可)
FileStream file = new FileStream(“filePath“, System.IO.FileMode.Open); //filepath為你的key文件路徑,建議放到C盤中 MD5 md5 = new MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(file); file.Close(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString().Substring(10, 8);
第三部:加密:核心代碼(用了DES,AES方法等同)(加密方法無需寫到程式中,只需要把加密結果寫到程式配置文件中即可)
public static string DESEncrypt(string plainStr) { byte[] bKey = Encoding.UTF8.GetBytes(Key); //key為第二部的返回值 byte[] bIV = Encoding.UTF8.GetBytes(@"L%n67}G\Mk@k%:~Y"); //加密向量,可以自己設置 byte[] byteArray = Encoding.UTF8.GetBytes(plainStr); string encrypt = null; DESCryptoServiceProvider des = new DESCryptoServiceProvider(); using (MemoryStream mStream = new MemoryStream()) { using (CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(bKey, bIV), CryptoStreamMode.Write)) { cStream.Write(byteArray, 0, byteArray.Length); cStream.FlushFinalBlock(); encrypt = Convert.ToBase64String(mStream.ToArray()); } } des.Clear(); return encrypt; }
第四部:解密:核心代碼(利用解密後的字元串進行連接即可)
public static string DESDecrypt(string encryptStr) { byte[] bKey = Encoding.UTF8.GetBytes(Key); //key為第二部的返回值 byte[] bIV = Encoding.UTF8.GetBytes(@"L%n67}G\Mk@k%:~Y"); //向量應等同於第三部中的向量 byte[] byteArray = Convert.FromBase64String(encryptStr); string decrypt = null; DESCryptoServiceProvider des = new DESCryptoServiceProvider(); try { using (MemoryStream mStream = new MemoryStream()) { using (CryptoStream cStream = new CryptoStream(mStream, des.CreateDecryptor(bKey, bIV), CryptoStreamMode.Write)) { cStream.Write(byteArray, 0, byteArray.Length); cStream.FlushFinalBlock(); decrypt = Encoding.UTF8.GetString(mStream.ToArray()); } } } catch { } des.Clear(); return decrypt; }
好了,是不是很簡單,現在即使你的程式被別人下載反編譯了,他想到你的電腦中把key文件拿走也不是一件容易的事。只要key文件不丟,基本就很難解密。
運行實例:使用哪個key文件進行加密,則只能使用其進行解密,一旦替換或者丟失則無法在解密。原理類似與綁定機器MAC地址,只是用一個文件來代替更為靈活。