簡介

開發人員經常會在 web.config 中存放網站應用程式會用到的組態設定資料,例如:資料庫連線字串。其中有些可能是屬於比較機密的資料,需要使用加密的方式將這些資料加以保護,以免隨便就 被別人看見。以往開發人員必須自己處理加密和解密的動作,現在 ASP.NET 2.0 提供了方便的加密和解密機制,讓我們可以很容易的將組態檔的某個區段 (section) 的內容加密。本文以一個簡單的實作範例來示範如何將 web.config 的內容加密,以及如何在程式中讀取加密過的組態設定。

準備工作

先在 Visual Studio 2005 中建立一個 Web Site,假設建立在 D:\Work\Demo\EncryptWebConfig。接著在 web.config 中加入 appSetting 設定,參考以下範例:

<configuration>
    <appSettings>
<add key="mySecret" value="這是我的秘密資料"/>
</appSettings>
<connectionStrings/> <!-- 其餘省略.... --> </configuration>

加密組態檔

加密的方法是利用 .NET Framework 提供的命令列工具:aspnet_regiis.exe。首先,開啟程式集 > Microsoft .NET Framework SDK v2.0 > SDK Command Prompt,接著輸入以下命令:

aspnet_regiis -pef appSettings D:\Work\Demo\EncryptWebConfig

aspnet_regiis 的 -pef 參數是用來加密某個絕對路徑下的 web.config 的某個 section,因此除了指定要加密的區段(此例為 appSettings),還要指定網站的絕對路徑 (此例為 D:\Work\Demo\EncryptWebConfig)。

如果加密成功,會出現以下訊息:

Encrypting configuration section...
Succeeded!

接著回到 Visual Studio 2005,檢視 web.config,原本的 <appSettings> 元素的內容會變成類似下面這樣:

<appSettings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>Rsa Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>z90mHvF2ckJWcNn(略...)</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>IGp7RWwbBkY2M2Bz5izbs(略...)</CipherValue>
</CipherData>
</EncryptedData>
</appSettings>

這樣就完成加密的工作了。接下來看看如何在程式中讀取加密過的資料。

在程式中讀取加密過的組態

在程式中讀取加密過的組態設定資料,程式撰寫方式跟平常一樣。例如:

string s = ConfigurationManager.AppSettings["mySecret"];

我們完全不需要自行撰寫解密的程式碼,因為 .NET Framework 類別已經在背後幫我們自動處理掉解密的工作了。

解密組態檔

如果要將之前加密過的組態檔內容還原成加密之前的資料,可以使用 aspnet_regiis -pdf 命令,例如:

aspnet_regiis -pdf appSettings D:\Work\Demo\EncryptWebConfig

此外,你可以重複執行同一個加密或解密的命令。對一個加密過的區段再次加密,只會將原始資料重新加密,而不會將加密後的資料再重複加密一次;而對一個解密過的資料重複進行解密動作,也不會有任何影響。

aspnet_regiis 的其他加密參數

-pe 與 -pd 參數

在前面的簡單示範中,筆者使用的是 -pef 參數,此參數必須指定一個加密的區段名稱,以及要加密的網站的絕對路徑。你還可以使用 -pe 參數來加密組態檔,使用此參數時,通常會搭配 -app 參數來指定虛擬目錄的名稱,例如:

aspnet_regiis -pe appSettings -app /MyWeb

如果 -app 之後所指定的虛擬目錄是 '/',則會加密 IIS 網站的根目錄底下的 web.config。如果你沒有指定 -app 參數,那就會加密 .NET Framework 安裝目錄下的 CONFIG\web.config。

與 -pe 參數對應的解密參數就是 -pd,用法與 -pe 參數相同。

-prov 參數

在前面的範例當中,加密後的 appSettings 元素有一個 configProtectionProvider 屬性:

<appSettings configProtectionProvider="RsaProtectedConfigurationProvider">

這個屬性的用途是指定加密的提供者,從它的屬性值可以看出,這個提供者所使用的加密演算法是 RSA。你也可以使用 -prov 參數來指定使用其他的提供者,例如 DPAPI (Data Protection Application Programming Interface) ,參考以下範例:

aspnet_regiis -pef appSettings D:\Work\Demo\EncryptWebConfig -prov DataProtectionConfigurationProvider

使用 DPAPI 加密後的組態檔內容如下:

<configuration>
    <appSettings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BF(略...)</CipherValue>
</CipherData>
</EncryptedData>
</appSettings>
<!-- 其餘省略.... --> </configuration>

若沒有指定 -prov 參數,預設就會使用 RSA 進行加密。

結語

本文簡單介紹了 ASP.NET 2.0 加密 web.config 的方法,以往開發人員必須自行撰寫加密解密的程式碼,現在只要使用 aspnet_regiis 這個命令列工具,執行一行命令就完成加密動作了。更棒的是,在程式中讀取加密過的資料完全不需要撰寫額外的程式碼,這些解密的過程都由 .NET Framework 類別幫我們在背後處理掉了。

另外,本文也提到了 RSA 和 DPAPI 兩種加密方式。根據 MSDN 文件的說明,如果你的網站會部署到多台伺服器上面以同時服務不同的用戶端,也就所謂的 Web farm 架構,那麼你應該要採用 RSA 的加密方式,因為這種方式可以讓你很容易的在多台伺服器之間匯出和匯入 RSA 金鑰(所有 Web farm 機器都要用同一把鑰匙,否則解密會有問題),若用 DPAPI 則很難確保所有機器都用同一把鑰匙。如果想要進一步了解 RSA 加密的應用,以及其他跟組態檔加密有關的議題,可以參考以下文章:

  • MSDN 文章:Encrypting Configuration Information Using Protected Configuration
  • MSDN 文章:How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI by J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley. Microsoft Corporation. July 2005
  • MSDN 文章:How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA by J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley. Microsoft Corporation. July 2005
  • Create Export & Encrypt connection string on server and dev machine with ASP.Net 2.0