Windows 2012 R2 – Safely Delete Files from C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

sslwindowswindows-server-2012-r2

On a Windows 2012 R2 Server with IIS, we have a web application which was generating certificates in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys and persisting the keys. We have fixed the issue but now the folder has over 6,000,000 files in it.

I tried renaming the folder and creating an empty MachineKeys folder, but it broke the OS's ability to handle SSL connections.

I'm able to find which LocalMachine repository certificates correspond to which filenames using this script:

Foreach ($MachineCert In Get-ChildItem Cert:\LocalMachine -Recurse | Where HasPrivateKey)
{
    $array += $MachineCert | 
       Select @{n='Subject';   e={ $MachineCert.Subject }},
              @{n='Container'; e={ $MachineCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName }},
              @{n='Store';     e={ $MachineCert.PSParentPath }}
}

However, I don't know what to do with this information. There are millions and millions of files so should I be able all of them safely other than those reported by the script above?

Best Answer

I was able to figure this out. First I used this script to compile a list of certificates that needed to be kept:

$array = @()

Foreach ($MachineCert In Get-ChildItem Cert:\LocalMachine -Recurse | Where HasPrivateKey)
{
    $array += $MachineCert | 
       Select @{n='Subject';   e={ $MachineCert.Subject }},
              @{n='Container'; e={ $MachineCert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName }},
              @{n='Store';     e={ $MachineCert.PSParentPath }}
}

$array | Export-CSV c:\temp\out.csv

Then I took all the container names from the output file and fed them into another script which copied the files from the MachineKeys folder with matching filename to a separate folder:

$arr = @(
    "f686aace6942fb7f7ceb231212eef4a4_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "d1acbca52745e8cdc7796dc9283bb8fc_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "83ceb9ab426f3fa7efdf06154db8cd13_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "98d0bf53be581119e8ac290607289a64_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "e955cd99d4ab953714119f933c483fd5_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "1b1f4753df9704baf9d16743d0c9b3d1_4cd8c04c-5245-4f49-962b-9e4388716e1f",
    "a31b3a063eb59a2fe7801565c6aa3846_4cd8c04c-5245-4f49-962b-9e4388716e1f"
)


gci -File -Recurse -Include $arr | % { copy-item $_.FullName "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys_new" }

That script ran for almost an entire day since it had to go through millions of files. Once it completed, I renamed the existing folder to "MachineKeys_old" and renamed the new folder from the script above to "MachineKeys". I rebooted the server to be sure everything still worked, and it did. SQL, IIS, everything works.

One more thing to watch for - make sure you assign the proper permissions to the new MachineKeys folder. For me, I had to give "Everyone" read/write/modify" access.