I would like to protect one key/value pair in my appSettings but not the others using something like I've previously done with the ProtectSection method as seen below.
var configurationSection = config.GetSection("appSettings");
configurationSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
Ideally I would like to do something like the following:
var开发者_运维知识库 configurationElement = config.GetSection("appSettings").GetElement("Protected");
configurationElement.ElementInformation.ProtectElement("DataProtectionConfigurationProvider");
Here is the example appSettings I would be operating on:
<configuration>
<appSettings>
<add key="Unprotected" value="ChangeMeFreely" />
<add key="Protected" value="########"/>
</appSettings>
</configuration>
I've been searching but haven't found a way to do this. Is this possible?
Not out of the box - .NET offers you the ability to encrypt sections - but not individual elements. However, since those are only strings, it's absolutely possible for you yourself to create some scheme to encrypt the string before saving it to file, and decrypt it after it's been read from the config file.
But this won't be transparent - you'll have to do it yourself and you have to do it explicitly.
I had the same issue when I needed to encrypt a single value from the app settings section. I used the EncryptText
and DecryptText
private methods of the DpapiProtectedConfigurationProvider
class which allowed me to encrypt any text values, and not necessarily config elements.
Here is the helper class:
public class WebConfigEncryption
{
private readonly DpapiProtectedConfigurationProvider _provider;
private readonly MethodInfo _encryptTextMethod;
private readonly MethodInfo _decryptTextMethod;
public WebConfigEncryption()
{
_provider = new DpapiProtectedConfigurationProvider();
_encryptTextMethod = _provider.GetType().GetMethod("EncryptText", BindingFlags.Instance | BindingFlags.NonPublic);
_decryptTextMethod = _provider.GetType().GetMethod("DecryptText", BindingFlags.Instance | BindingFlags.NonPublic);
}
public string Encrypt(string value)
{
var encryptedValue = value != null ? (string)_encryptTextMethod.Invoke(_provider, new object[] { value }) : null;
return encryptedValue;
}
public string Decrypt(string value)
{
var decryptedValue = value != null ? (string)_decryptTextMethod.Invoke(_provider, new object[] { value }) : null;
return decryptedValue;
}
}
Example of usage:
[Test]
public void EncryptDecryptTest()
{
var instance = new WebConfigEncryption();
var encrypted = instance.Encrypt("123");
var decrypted = instance.Decrypt(encrypted);
Assert.That(decrypted, Is.EqualTo("123"));
}
Also if you have access to XmlNode
or XmlElement
instances, you can use public methods of the provider class: DpapiProtectedConfigurationProvider.Encrypt(XmlNode)
and DpapiProtectedConfigurationProvider.Decrypt(XmlNode)
instead of reflection.
精彩评论