【问题标题】:Prevent file creation when X509Certificate2 is created?创建 X509Certificate2 时阻止文件创建?
【发布时间】:2018-04-14 04:59:49
【问题描述】:

我们在我们的 ASP.NET 应用程序中创建一个 X509Certificate2 对象来建立定期的传出连接。每次创建这些证书之一时,都会在以下位置创建一个新文件:

C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

该文件夹现在有 400 万个文件永远不会被清理。我试过删除 Persist 标志

新 X509Certificate2(certBytes, p12Pwd, X509KeyStorageFlags.MachineKeySet);

//没有X509KeyStorageFlags.PersistKeySet

但这无济于事——每次调用时仍会获取 2Kb 文件。

当我看到this answer 时,我抱起了希望,但这是一个 2008 R2 服务器,临时文件不是 0 字节,所以它似乎是不同的情况。

我们如何在不填满磁盘的情况下使用 X509Certificate2?

【问题讨论】:

    标签: c# ssl certificate x509certificate x509certificate2


    【解决方案1】:

    Use .NET 4.6:

    X509Certificate2 实现 IDisposable 接口,以 .NET 框架 4.6;在 .NET Framework 的早期版本中, X509Certificate2 类没有实现这个接口,并且 因此 Dispose 方法不存在。

    【讨论】:

    • 还应该注意的是,你也不能设置 X509KeyStorageFlags.PersistKeySet 否则它会一直存在。尽管如此,微软应该提供一种更好的方法来处理这个问题,因为在关闭期间处理通过 Web 环境中的某个提供程序加载的证书并不总是那么容易。
    • @MichaelBrown:仅供参考,在我发布此答案时,我正在关注this issue,其中有一个关于“临时”证书的有趣讨论——当我尝试它时,它破坏了我们的系统。该问题现已关闭,我没有关注它。
    • 感谢您的跟进。我正在研究该特定功能,但在 .Net Standard 中没有看到对它的任何支持。 X509KeyStorageFlags 不包含EphemeralKeySet 并且似乎他们只是出于某种原因将其添加到.Net Core。将继续深入研究。
    【解决方案2】:

    我在我们的服务器上遇到了同样的问题。我目前发现的最好方法是从我的代码中删除文件。

    using System;
    using System.Security.Cryptography;
    using System.Security.Permissions;
    using System.IO;
    using System.Security.Cryptography.X509Certificates;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Byte[] bytes = File.ReadAllBytes(@"D:\tmp\111111111111.p12");
                X509Certificate2 x509 = new X509Certificate2(bytes, "qwerty", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
                var privateKey = x509.PrivateKey as RSACryptoServiceProvider;
                string uniqueKeyContainerName = privateKey.CspKeyContainerInfo.UniqueKeyContainerName;
                x509.Reset();
    
                File.Delete(string.Format(@"C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\{0}", uniqueKeyContainerName));
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      为了重现您的问题,我创建了此示例代码。我的测试环境是 Windows 8.1 64bit,应用程序是用 .NET 4.5 编写的。

      using System.IO;
      using System.Security.Cryptography.X509Certificates;
      
      namespace ConsoleApplication2
      {
          class Program
          {
              static void Main(string[] args)
              {
                  var certBytes = File.ReadAllBytes(@"c:\cert.p12");
                  var p12Pwd = "somepassword";
      
                  for (var i = 0; i < 1000; i++)
                  {
                      var cert = new X509Certificate2(certBytes, p12Pwd, X509KeyStorageFlags.MachineKeySet);
      
                      // this line helped keep filesize from growing   
                      // cert.Reset(); 
                  }
              }
          }
      }
      

      C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 的文件大小高达 2MB,这让我感到震惊。然后应用程序退出,文件大小下降到 20K(这可能是它的起始大小)。

      然后我添加了cert.Reset();(我已经在上面的代码中注释了它)。当您不再需要 X509Certificate2 实例时,应该调用它。之后,C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 的文件大小在 20K 和 22K 之间波动。

      所以我的建议是当您不再需要 X509Certificate2 实例时调用 cert.Reset();

      【讨论】:

      • 当我读到你的建议时我很兴奋,但后来发现我已经调用了 Reset :( 一个区别可能是我将证书传递给 SslStream.AuthenticateAsClient,所以我想知道这是否会增加一个对文件的引用...?进一步观察。
      • 仅供参考,当证书垃圾收集时,它与调用 Reset() 具有相同的效果。如果您现在需要该磁盘空间,则调用 reset 只是一种加快清理速度的方法
      • 感谢您的信息。我没有尝试使用重置方法。
      • 我不认为垃圾收集器在这里的所有情况下都有效,如果它可以工作的话,问题不应该发生。奇怪的是 X509Certificate2 有一个 Reset 但没有 Dispose
      • @Bogdan,X509Certificate2 有一个在 .NET 4.6 中调用 Reset 的 Dispose。
      【解决方案4】:

      我在我们的服务器上遇到了同样的问题。我目前发现的最好方法是通过脚本删除文件(有用的文件除外)。

      例外列表:

      • Microsoft Internet 信息服务器 -> c2319c42033a5ca7f44e731bfd3fa2b5 ...
      • NetFrameworkConfigurationKey -> d6d986f09a1ee04e24c949879fdb506c ...
      • iisWasKey -> 76944fb33636aeddb9590521c2e8815a ...
      • WMSvc 证书密钥容器 -> bedbf0b4da5f8061b6444baedf4c00b1 ...
      • iisConfigurationKey -> 6de9cb26d2b98c01ec4e9e8b34824aa2 ...
      • MS IIS DCOM 服务器 -> 7a436fe806e483969f48a894af2fe9a1 ...
      • TSSecKeySet1 -> f686aace6942fb7f7ceb231212eef4a4 ...
      • https://forums.whirlpool.net.au/archive/1683713

      通过https://forums.iis.net/t/1224708.aspx?C+ProgramData+Microsoft+Crypto+RSA+MachineKeys+is+filling+my+disk+space

      这个解决方案仍然是一个补丁。最好不要在 MachineKeys 文件夹中生成文件。

      【讨论】:

      • 我遇到了同样的问题。您是如何识别这些密钥的。我找不到 IIS 密钥。我们的服务器上没有以 c2319c42033a5ca7f44e731bfd3fa2b5 开头的机器密钥文件。
      猜你喜欢
      • 1970-01-01
      • 2018-05-29
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-18
      • 2020-02-12
      相关资源
      最近更新 更多