如何在 C# 中使用带有 ProtectSection 方法的 RsaProtectedConfigurationProvider 创建可导出的 RSA 密钥
How can I create an exportable RSA key with RsaProtectedConfigurationProvider with ProtectSection method in C#
在下面的示例中,我保护了 "Sleutels.config" 文件的 "DemoWinApp.Properties.Settings" 部分。
private static void toggleProtectionSleutelsConfig()
{
var fileMap = new ConfigurationFileMap(@"D:\Experimenten\ReadProtectedConfigFile\Sleutels.config");
var configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
var sectionGroup = configuration.GetSectionGroup("applicationSettings"); // This is the section group name, change to your needs
var section = (ClientSettingsSection)sectionGroup.Sections.Get("DemoWinApp.Properties.Settings"); // This is the section name, change to your needs
var setting = section.Settings.Get("SecretMessage"); // This is the setting name, change to your needs
Console.WriteLine(setting.Value.ValueXml.InnerText);
// Toggle beveiliging
if (!section.SectionInformation.IsProtected)
{
//Protecting the specified section with the specified provider
section.SectionInformation.ProtectSection("RSA");
}
else
{
section.SectionInformation.UnprotectSection();
}
section.SectionInformation.ForceSave = true;
configuration.Save(ConfigurationSaveMode.Modified);
Console.ReadKey();
}
"Sleutels.config" 文件的内容是:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, 
 System, Version=2.0.0.0, Culture=neutral, 
 PublicKeyToken=b77a5c561934e089">
<section name="DemoWinApp.Properties.Settings" type="System.Configuration.ClientSettingsSection,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<DemoWinApp.Properties.Settings>
<setting name="SecretMessage" serializeAs="String">
<value>This is the secret message.</value>
</setting>
</DemoWinApp.Properties.Settings>
</applicationSettings>
<configProtectedData>
<providers>
<add name="RSA"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
 Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
 processorArchitecture=MSIL"
keyContainerName="RobinsKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
</configuration>
在 运行 代码之后 "Sleutels.config" 文件被加密并在 C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
中创建了一个 RSA 密钥容器
如果我尝试使用命令行导出 RSA 密钥容器:
c:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pc "RobinsKeys" –exp
然后我收到错误信息:
Exporting RSA Keys to file...
Key not valid for use in specified state.
这意味着 RSA 密钥容器未标记为 "exportable"。如果您要使用命令行创建密钥容器,则有一个可选参数“-exp”来将密钥标记为可导出。
例如:
aspnet_regiis -pc "RobinsKeys" -exp
此 -exp
选项在代码中使用 section.SectionInformation.ProtectSection("RSA");
方法时是否也可用,或者作为 "Sleutels.config" 配置文件中 RSA 提供程序部分的配置选项?
感谢任何帮助!
为了总结讨论,您需要先创建一个 RSA 加密容器 以编程方式,然后才能使用它来存储 RSA 密钥。
原因是 RSAProtectedConfigurationProvider
没有选项 使自动创建的 RSA 密钥容器 可导出。
正如您在聊天中所写,此解决方法可以通过以下示例代码实现(我已将一些输出添加到控制台,对打印的 RSA 参数进行了解释 here):
void Main()
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
var cp = new System.Security.Cryptography.CspParameters();
cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = "RobinsKeys";
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
// If it is not already there, it will create a new one, which is exportable.
var myRSA = new System.Security.Cryptography.RSACryptoServiceProvider(cp);
// print it on console
Console.WriteLine($"=== Container: {cp.KeyContainerName} ===");
Console.WriteLine(myRSA.ToXmlString(true).Replace("><", ">\n<"));
}
可以更详细地阅读here。提供的 link 还展示了如何
- 生成并保存密钥对
- 从容器中获取密钥
- 从容器中删除密钥
获取容器列表可能会有用,这是 discussed in a separate question。
您可以找到有关密钥容器的更多信息 in this Microsoft article,以及可用的 aspnet_regiis
参数。
创建RSA 容器后,IIS 就可以使用它。了解用户级别和机器级别密钥容器之间的区别很重要,is described in this documentation.
如果讨论中有任何遗漏,请告诉我,我会更新这个答案。
在下面的示例中,我保护了 "Sleutels.config" 文件的 "DemoWinApp.Properties.Settings" 部分。
private static void toggleProtectionSleutelsConfig()
{
var fileMap = new ConfigurationFileMap(@"D:\Experimenten\ReadProtectedConfigFile\Sleutels.config");
var configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
var sectionGroup = configuration.GetSectionGroup("applicationSettings"); // This is the section group name, change to your needs
var section = (ClientSettingsSection)sectionGroup.Sections.Get("DemoWinApp.Properties.Settings"); // This is the section name, change to your needs
var setting = section.Settings.Get("SecretMessage"); // This is the setting name, change to your needs
Console.WriteLine(setting.Value.ValueXml.InnerText);
// Toggle beveiliging
if (!section.SectionInformation.IsProtected)
{
//Protecting the specified section with the specified provider
section.SectionInformation.ProtectSection("RSA");
}
else
{
section.SectionInformation.UnprotectSection();
}
section.SectionInformation.ForceSave = true;
configuration.Save(ConfigurationSaveMode.Modified);
Console.ReadKey();
}
"Sleutels.config" 文件的内容是:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, 
 System, Version=2.0.0.0, Culture=neutral, 
 PublicKeyToken=b77a5c561934e089">
<section name="DemoWinApp.Properties.Settings" type="System.Configuration.ClientSettingsSection,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<DemoWinApp.Properties.Settings>
<setting name="SecretMessage" serializeAs="String">
<value>This is the secret message.</value>
</setting>
</DemoWinApp.Properties.Settings>
</applicationSettings>
<configProtectedData>
<providers>
<add name="RSA"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
 Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
 processorArchitecture=MSIL"
keyContainerName="RobinsKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
</configuration>
在 运行 代码之后 "Sleutels.config" 文件被加密并在 C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
如果我尝试使用命令行导出 RSA 密钥容器:
c:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pc "RobinsKeys" –exp
然后我收到错误信息:
Exporting RSA Keys to file...
Key not valid for use in specified state.
这意味着 RSA 密钥容器未标记为 "exportable"。如果您要使用命令行创建密钥容器,则有一个可选参数“-exp”来将密钥标记为可导出。
例如: aspnet_regiis -pc "RobinsKeys" -exp
此 -exp
选项在代码中使用 section.SectionInformation.ProtectSection("RSA");
方法时是否也可用,或者作为 "Sleutels.config" 配置文件中 RSA 提供程序部分的配置选项?
感谢任何帮助!
为了总结讨论,您需要先创建一个 RSA 加密容器 以编程方式,然后才能使用它来存储 RSA 密钥。
原因是 RSAProtectedConfigurationProvider
没有选项 使自动创建的 RSA 密钥容器 可导出。
正如您在聊天中所写,此解决方法可以通过以下示例代码实现(我已将一些输出添加到控制台,对打印的 RSA 参数进行了解释 here):
void Main()
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
var cp = new System.Security.Cryptography.CspParameters();
cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = "RobinsKeys";
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
// If it is not already there, it will create a new one, which is exportable.
var myRSA = new System.Security.Cryptography.RSACryptoServiceProvider(cp);
// print it on console
Console.WriteLine($"=== Container: {cp.KeyContainerName} ===");
Console.WriteLine(myRSA.ToXmlString(true).Replace("><", ">\n<"));
}
可以更详细地阅读here。提供的 link 还展示了如何
- 生成并保存密钥对
- 从容器中获取密钥
- 从容器中删除密钥
获取容器列表可能会有用,这是 discussed in a separate question。
您可以找到有关密钥容器的更多信息 in this Microsoft article,以及可用的 aspnet_regiis
参数。
创建RSA 容器后,IIS 就可以使用它。了解用户级别和机器级别密钥容器之间的区别很重要,is described in this documentation.
如果讨论中有任何遗漏,请告诉我,我会更新这个答案。