如何在 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, &#xD;&#xA;                    System, Version=2.0.0.0, Culture=neutral, &#xD;&#xA;                    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,&#xD;&#xA;                    Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,&#xD;&#xA;                    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.


如果讨论中有任何遗漏,请告诉我,我会更新这个答案。