背景
在程序或服務(wù)開(kāi)發(fā)過(guò)程中,我們通常會(huì)把一些程序需要用到的常量數(shù)據(jù)配置在web.config或app.config文件中募疮,通常配置到這些文件中的Key與Value都是明文的涣易,但有時(shí)候我們并不希望這些配置讓他人知道蚯嫌。
在這種情況下贬蛙,我們可以使用ASP.NET Encrypt和Decrypt來(lái)對(duì)配置文件進(jìn)行加密长搀,不影響程序使用蹂季,但又不被他人知道配置的具體內(nèi)容冕广。
環(huán)境
- Windonw 7 / Windows Server 2008
- .Net Framework 4.0
- IIS
以上環(huán)境準(zhǔn)備好后,在搭建好的IIS上創(chuàng)建三個(gè)站點(diǎn) WebSite1, WebSite2, WebSite3
工具
- asp.net_regiis.exe
- vs 2010 tool
- sn.exe
- gacutil.exe
asp.net_regiis.exe位于路徑C:\Windows\Microsoft.NET\Framework64\v4.0.30319
使用管理員身份運(yùn)行cmd.exe
Start --> All Programs --> Microsoft Visual Studio 2010 --> Visual Studio Tools --> Visual Studio x64 Win64 Command Prompt (2010)(run as administrator)
sn, gacutil 在VS 2010 tool中可直接使用
Providers in .NET Framework
DpapiProtectedConfigurationProvider
uses the Windows Data Protected API(DPAPI) to encrypt and Decrypt data.RsaProtectedConfigurationProvider
useed the RSA encryption algorithm to encrypt and Decrypt data.
Providers means Protected configuration Providers
Machine-Level and User-Level
Machine-Level
available to all users
Machine-level 的Key對(duì)所有管理員用戶(hù)有效果偿洁,但也受ACLs的約束
User-Level
available only to the user that created the key container.
stored with the Windonw user profile for a particular user
userd to encrypt and decrypt information for applications that run under that specific user identity.
user-level 的Key是與用戶(hù)賬號(hào)綁定的撒汉,用戶(hù)被刪除時(shí),key也被刪除
這里所講的avalliable是指能夠加密和解密
Tool and Parameters
Tool
asp.net_regiis.exe
encrypt parameters
-pe the name of the configuraiton element to be encrypt
-app identity the application for which the web.config file will be encrypted
-site identity which web site the application is a part of
-prov identity the name of the ProtectedConfigurationProvider that will preform the encryption and decryption.
pe, app 是必須要指定的值
site默認(rèn)值為1, prov默認(rèn)使用defaultProvider
decrypt parameters
-pd the name of the configuration element to be decrypted.
-app identify the application for which the web.config file will be encrypted
-site identify which Web site the application is a part of
-prov not need to specify
在解密時(shí)不需要使用prov來(lái)指定ProtectedConfigurationProvider涕滋,because that information is read from the configProtectionProvider attribute of the protected configuration section.
Encrypting Website’s Web.config
在VS Tool中輸入以下命令
aspnet_regiis -pef "connectionStrings" E:\webSite1
或
aspnet_regiis -pe "connectionStrings" -app "/WebSite1" -site "WebSite1"
需要為WebSite1添加虛擬目錄
或
aspnet_regiss -pe "connectionStrings" -app "/WebSite1" -site "WebSite1" -prov DataProtectionConfigurationProvider
需要為WebSite1添加虛擬目錄睬辐,指定Provider
解密
aspnet_regiis -pd "connectionStrings" -app "/WebSite1" -site "WebSite1"
Create a RSA Key Container
Tool
aspnet_regiis
Parameters
-pc : the name of the key container used by the RsaProtectedConfigurationProvider specified in the configProtectedData section of web.config file
-exp : ensure that RSA key container can be exported
Web.config的配置
<configProtectedData>
<providers>
<add name="CustomerProvider" keyContainerName="SampleKeys" useMachineContainer="true" description="Users RsaCryptoSErviceProvider to encrypt and decrypt" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=4.0.0.0, Cultuer=neutral, PublicKeyToken=b03f5f7f11d50a3a">
</providers>
</configProtectedData>
以上配置中的KeyContainerName="true",表示使用Machine-level, false表示使用user-level
加密時(shí)使用以下命令
aspnet_regiis -pe "connectionStrings" -app "/WebSite2" -site "WebSite2" -prov "CustomeProvider"
Exporting a RSA Key Container
使用命令
aspnet_regiis -px "SampleKeys" E:\MachineSmapleKey.xml -pri
Importing a RSA Key Container
aspnet_regiis -pi "MyKeys" keys.xml -pku
Deleting a RSA Key Container
aspnet_regiis -pz "MyKeys"
Custome Provider Type
Implementing a Protected Configuration Provider
- Algorithm
an algorithm other than those available with the RSA or DPAPI providers - Required Classes
ProtectedConfigurationProvider class from the System.Configuration namespace
ProviderBase class from the System.Configuration.Provider namespace - Required Members
Initialize method (from ProviderBase)
Encrypt method (from ProtectedConfigurationProvider)
Decrypt method (from ProtectedConfigurationProvider)
Build Protected Configuration Provider
- Generate a strong-name key pair
sn -k keys.snk
- Create a program file named TripleDESProtectedConfigurationProvider
using System.Xml;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Configuration;
namespace AA.BB.ProtectedConfiguration
{
public class TripleDESProtectedConfigurationProvider : ProtectedConfigurationProvider
{
private TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
private string pKeyFilePath;
private string pName;
public string KeyFilePath
{
get { return pKeyFilePath; }
}
//
// ProviderBase.Name
//
public override string Name
{
get { return pName; }
}
//
// ProviderBase.Initialize
//
public override void Initialize(string name, NameValueCollection config)
{
pName = name;
pKeyFilePath = config["keyFilePath"];
ReadKey(KeyFilePath);
}
//
// ProtectedConfigurationProvider.Encrypt
//
public override XmlNode Encrypt(XmlNode node)
{
string encryptedData = EncryptString(node.OuterXml);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml("<EncryptedData>" + encryptedData + "</EncryptedData>");
return xmlDoc.DocumentElement;
}
//
// ProtectedConfigurationProvider.Decrypt
//
public override XmlNode Decrypt(XmlNode encryptedNode)
{
string decryptedData = DecryptString(encryptedNode.InnerText);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.LoadXml(decryptedData);
return xmlDoc.DocumentElement;
}
//
// EncryptString
// Encrypts a configuration section and returns the encrypted
// XML as a string.
//
private string EncryptString(string encryptValue)
{
byte[] valBytes = Encoding.Unicode.GetBytes(encryptValue);
ICryptoTransform transform = des.CreateEncryptor();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(valBytes, 0, valBytes.Length);
cs.FlushFinalBlock();
byte[] returnBytes = ms.ToArray();
cs.Close();
return Convert.ToBase64String(returnBytes);
}
//
// DecryptString
// Decrypts an encrypted configuration section and returns the
// unencrypted XML as a string.
//
private string DecryptString(string encryptedValue)
{
byte[] valBytes = Convert.FromBase64String(encryptedValue);
ICryptoTransform transform = des.CreateDecryptor();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(valBytes, 0, valBytes.Length);
cs.FlushFinalBlock();
byte[] returnBytes = ms.ToArray();
cs.Close();
return Encoding.Unicode.GetString(returnBytes);
}
//
// CreateKey
// Generates a new TripleDES key and vector and writes them
// to the supplied file path.
//
public void CreateKey(string filePath)
{
des.GenerateKey();
des.GenerateIV();
StreamWriter sw = new StreamWriter(filePath, false);
sw.WriteLine(ByteToHex(des.Key));
sw.WriteLine(ByteToHex(des.IV));
sw.Close();
}
//
// ReadKey
// Reads in the TripleDES key and vector from the supplied
// file path and sets the Key and IV properties of the
// TripleDESCryptoServiceProvider.
//
private void ReadKey(string filePath)
{
StreamReader sr = new StreamReader(filePath);
string keyValue = sr.ReadLine();
string ivValue = sr.ReadLine();
des.Key = HexToByte(keyValue);
des.IV = HexToByte(ivValue);
}
//
// ByteToHex
// Converts a byte array to a hexadecimal string.
//
private string ByteToHex(byte[] byteArray)
{
string outString = "";
foreach (Byte b in byteArray)
outString += b.ToString("X2");
return outString;
}
//
// HexToByte
// Converts a hexadecimal string to a byte array.
//
private byte[] HexToByte(string hexString)
{
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i*2, 2), 16);
return returnBytes;
}
}
}
- Compile the code and assign the resulting assembly with the strong-name key
csc /out:TripleDESProtectedConfigurationProvider.dll /t:library TripleDESProtectedConfigurationProvider.cs /r:System.Configuration.dll /keyfile:keys.snk
- Install the assembly in the GAC(global assembly cach)
gacutil -i TripleDESProtectedConfigurationProvider.dll
Use a Custom Provider type
-
Generate Key File
CreateKey.exe E:\ASP\Keys.txt
Modify the configProtectedData Section of the Web.config
<configProtectedData>
<providers>
<add name="SampleProvider" useMachineContainer="true" type="AA.BB.TripleDESProtectedConfigurationProvider TripleDESProtectedConfigurationProvider Version=0.0.0.0, Cultuer=neutral PublicKeyToken=b06675f7f11d50a3a",description="Users RsaCryptoSErviceProvider to encrypt and decrypt" keyFilePath="E:\ASP\Key" >
</providers>
</configProtectedData>