通常網站都會與資料庫溝通,也因此在 csharp 的專案設定檔,我們大都會將連線字串寫在這裡,便於程式調用,但資料庫連線字串包含了帳號密碼,直接寫在設定組態檔是一個資安漏洞 為了不要讓明碼直接暴露出去,我們這裡最好做一些防護措施,利用演算法將明文加密,等到要用的時候再解密出來。
當然這樣的做法還是有風險的,因為加解密的 Key、IV 也還是一樣都放在組態檔內,所以這只能說是一個初步的防護方式
連線字串加密
先透過一組金鑰 (public key, private key)來作加密、解密,有興趣的可以透過Online RSA Encryption, Decryption And Key Generator Tool來測試一下
需要先將需要保護的連線字串加密,然後將這個加密過後的字串,放到web.config
裡面,等到程式需要資料庫連線的時候,取得加密字串後再針對他進行解密即可,搭配上 web.config 的連線字串lockItem
設定使用。思路已經有了,所以具體的步驟大概就是要做
- Key、IV
- 加解密函式
- 判斷是否需要執行解密
Key、IV
這邊直接使用網路上的範例,相關知識可以參考一下這兩篇文章
config 設定
<?xml version="1.0" encoding="utf-8"?>
<appSettings>
<add key="hashKey" value="金鑰喔金鑰喔金鑰喔金鑰喔"/>
<add key="iv" value="加密向量初始資料"/>
</appSettings>
加解密函式
public string Decryption(string CipherText,string hashKey,string iv)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Encoding.Unicode.GetBytes(hashKey);
aesAlg.IV = Encoding.Unicode.GetBytes(iv);
ICryptoTransform decrypt = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
byte[] decrypted = decrypt.TransformFinalBlock(Convert.FromBase64String(CipherText), 0, Convert.FromBase64String(CipherText).Length);
return Encoding.Unicode.GetString(decrypted);
}
}
public string Encryption(string PlainText,string hashKey, string iv)
{
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Encoding.Unicode.GetBytes(hashKey);
aesAlg.IV = Encoding.Unicode.GetBytes(iv);
ICryptoTransform encrypt = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
byte[] encrypted = encrypt.TransformFinalBlock(Encoding.Unicode.GetBytes(PlainText), 0,
Encoding.Unicode.GetBytes(PlainText).Length);
return Convert.ToBase64String(encrypted);
}
}
判斷是否需要執行解密
直接取得連線字串的 function 當中判斷處理
private string GetVersion()
{
var connectionString = GetConnectionString("db");
var commandText = "select @@version";
using (var cnn = new MySqlConnection(connectionString))
{
return cnn.Query<string>(commandText).FirstOrDefault();
}
}
public string GetConnectionString(string name)
{
var connectionString = ConfigurationManager.ConnectionStrings[name];
var source = connectionString.ConnectionString;
if (connectionString.LockItem)
{
var hashKey = ConfigurationManager.AppSettings["hashKey"];
var iv = ConfigurationManager.AppSettings["iv"];
source = Decryption(source, hashKey, iv);
}
return source;
}
Sample Code
組態檔案加密
透過 aspnet_regiis.exe 來處理,需要透過管理員權限來執行喔
# 透過 aspnet_regiis將 指定目錄下的 web.config 當中的 appSettings 區段加密
aspnet_regiis -pef appSettings D:\code\Github\Repos\CryptoConnStrDemo\CryptoConnStrDemo
# 同上,參數改為 pdf 則為解密
aspnet_regiis -pdf appSettings D:\code\Github\Repos\CryptoConnStrDemo\CryptoConnStrDemo
如果要在本機測試的話,需要先將 Visual Studio 在建置的時候使用 local 的 IIS,而非 IISExpress
如果需要將本機的 RSA 金鑰容器給別台主機使用,則需要先將金鑰容器匯出,再由別的主機匯入使用
# 匯出
aspnet_regiis -px "NetFrameworkConfigurationKey" D:/RSAkeys.xml -pri
# 匯入
aspnet_regiis -pi "NetFrameworkConfigurationKey" D:/RSAkeys.xml