X509Certificate2 implements the IDisposable interface starting with the .NET Framework 4.6; in previous versions of the .NET Framework, the X509Certificate2 class does not implement this interface, and therefore the Dispose method does not exist.
Prevent file creation when X509Certificate2 is created?
-
20-06-2023 - |
Question
We create a X509Certificate2 object in our ASP.NET app to make periodic outgoing connections. Every time one of these certificates is created a new file is created in:
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
That folder now has 4 million files that never get cleaned up. I've tried removing the Persist flag
new X509Certificate2(certBytes, p12Pwd, X509KeyStorageFlags.MachineKeySet);
//no X509KeyStorageFlags.PersistKeySet
but that doesn't help -- still get the 2Kb file on every call.
I got my hopes up when I saw this answer, but this is a 2008 R2 server, and the temp files are not 0 bytes, so it seems to be a different case.
How can we use a X509Certificate2 without filling up the disk?
Solution
OTHER TIPS
I have the same issue on our server. The best way I found for now is to delete files from my code.
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));
}
}
}
To reproduce your problem I have created this sample code. My testing environment was Windows 8.1 64bit and the application was written in .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();
}
}
}
}
I was shocked that file size of C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
went up to 2MB. Then application exited and the filesize dropped down to 20K (that was probably its starting size).
Then I have added cert.Reset();
(I have commented it in the code above). This should be called when you no longer need the X509Certificate2
instance. After that, the filesize of C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
was flapping between 20K and 22K.
So my suggestion is to call cert.Reset();
when you no longer need the X509Certificate2
instance.
I have the same issue on our server. The best way I found for now is to delete files (except useful ones) via a script.
Exception list :
- Microsoft Internet Information Server -> c2319c42033a5ca7f44e731bfd3fa2b5 ...
- NetFrameworkConfigurationKey -> d6d986f09a1ee04e24c949879fdb506c ...
- iisWasKey -> 76944fb33636aeddb9590521c2e8815a ...
- WMSvc Certificate Key Container -> bedbf0b4da5f8061b6444baedf4c00b1 ...
- iisConfigurationKey -> 6de9cb26d2b98c01ec4e9e8b34824aa2 ...
- MS IIS DCOM Server -> 7a436fe806e483969f48a894af2fe9a1 ...
- TSSecKeySet1 -> f686aace6942fb7f7ceb231212eef4a4 ...
- https://forums.whirlpool.net.au/archive/1683713
This solution remains a patch. It would be better to no generate files in MachineKeys folder.