
[英]Encryption / Decryption of app.config sections using RsaProtectedConfigurationProvider
[英]Using RsaProtectedConfigurationProvider to perform encryption on strings not in a config file
我的组织要求使用生产服务器上的特定System.Configuration.RsaProtectedConfigurationProvider加密敏感的连接字符串。 但是,我有一个将连接字符串存储在数据库中的应用程序,我想用相同的密钥对它们进行加密。
我最初的想法是创建一个虚拟配置文件,其中包含对加密提供程序的引用,将其加载一些文本并执行加密,而不必将其写回到磁盘。 然后,我可以将密文/明文从xml中拉出:
DummyConfig.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="DummySection" type="virutalConfig.DummySect, virutalConfig, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<DummySection />
<configProtectedData>
<providers>
<add name="MyProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
 Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
 processorArchitecture=MSIL"
keyContainerName="MyKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
</configuration>
Program.cs中:
class Program
{
static void Main(string[] args)
{
var fileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = @"c:\virtconfigtest\DummyConfig.config"
};
var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var sect = config.GetSection("DummySection") as DummySect;
sect.Inf = "this is some plaintext!";
sect.SectionInformation.ProtectSection("MyProvider");
//sect.SectionInformation.ForceSave = true;
//config.Save();
if (sect.SectionInformation.IsProtected)
{
Console.WriteLine("Section is protected. Raw XML:");
Console.WriteLine(sect.SectionInformation.GetRawXml());
}
else
{
Console.WriteLine("Section is not protected. Raw XML:");
Console.WriteLine(sect.SectionInformation.GetRawXml());
}
Console.ReadLine();
}
}
public class DummySect : ConfigurationSection
{
public DummySect() { }
[ConfigurationProperty("inf")]
public string Inf
{
get { return (string)this["inf"]; }
set { this["inf"] = value; }
}
}
不幸的是,GetRawXml()仅返回纯文本,甚至要获取此文本,似乎必须将配置文件写回到磁盘。
我可以通过将磁盘上的文件作为xml文档读取来获得所需的内容,但我不想这样做。 无论如何,即使没有增加磁盘写入量,整个计划还是相当粗略的。 我需要从提供商那里获取RSA密钥吗? 如果是这样,怎么办?
经过一些研究和反复试验,我最终找到了解决方法。
这是配置文件的加密部分的样子:
<DummySection configProtectionProvider="MyProvider">
<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>RsMpDD/wJmmpN+Mme+qFuRVm2Ddk759hWM7HaeAnW7xpfkCoC4ko7vDBmqylzQ0QAFL2wuR8u8Bsf+4xwn++Ru/GsEaYrGrcDMYJTuWElyHuxnw+5umqexQJye2R5uL/91alFVNV41HnSPlwuA+pgk14yHSWIflIyKFmUTx58vU=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>lQI7gyQZ2HIIQUdKsp73HrYcebbOiO4dCriwCt5avfVTcxPZEHzaCfV52k+triRwq64uGVCNRpGUe5PCVEfbWwrPHaNaFzRp</CipherValue>
</CipherData>
</EncryptedData>
</DummySection>
密文的第一块是使用RSA加密的三重DES密钥。 可以从以下目录中的文件获得密钥对:C:\\ ProgramData \\ Microsoft \\ Crypto \\ RSA \\ MachineKeys
第二部分使用此DES密钥加密,并带有64位初始化向量。 令人沮丧的是,它用以下方法填充:ISO10126
这是执行解密的代码:
var cspParameters = new CspParameters()
{
KeyContainerName = "MyKeys",
Flags = CspProviderFlags.UseMachineKeyStore
}; //refers to a file in the machine keys directory
var rsaKey = new RSACryptoServiceProvider(cspParameters);
var t1 =
Convert.FromBase64String(
"RsMpDD/wJmmpN+Mme+qFuRVm2Ddk759hWM7HaeAnW7xpfkCoC4ko7vDBmqylzQ0QAFL2wuR8u8Bsf+4xwn++Ru/GsEaYrGrcDMYJTuWElyHuxnw+5umqexQJye2R5uL/91alFVNV41HnSPlwuA+pgk14yHSWIflIyKFmUTx58vU=");
var t2 =
Convert.FromBase64String(
"lQI7gyQZ2HIIQUdKsp73HrYcebbOiO4dCriwCt5avfVTcxPZEHzaCfV52k+triRwq64uGVCNRpGUe5PCVEfbWwrPHaNaFzRp");
var desKey = rsaKey.Decrypt(t1, false); //get the des key
var iv = t2.Take(8).ToArray(); //get the initialization vector
var ct = t2.Skip(8).ToArray(); //get the actual ciphertext
var desEnc = new TripleDESCryptoServiceProvider()
{
Padding = PaddingMode.ISO10126
};
var plaintext = Encoding.Default.GetString(desEnc.CreateDecryptor(desKey, iv).TransformFinalBlock(ct, 0, ct.Length));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.