When trying to get a X509Certificate2
object from the X509Store
using the following code:
private X509Certificate2 GetKey()
{
try
{
X509Store store = new X509Store("WebHosting", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var collection = store.Certificates.Find(X509FindType.FindBySubjectName, "xxxxxxx", true);
if (collection.Count == 0)
{
throw new Exception("No keys matched");
}
if (collection.Count > 1)
{
StringBuilder sb = new StringBuilder();
sb.Append("More than 1 key matched:\r\n");
foreach (var cert in collection)
{
sb.Append($"{cert.SubjectName} - {cert.Thumbprint}\r\n");
}
throw new Exception(sb.ToString());
}
return collection[0];
}
catch (Exception ex)
{
// something really bad happened, log it
Logger.LogException(ex);
throw;
}
}
I successfully get the key; however, when trying to get the private key within the object using key.PrivateKey
, I get the following error: OpenCSP failed with error code 2148073494.
Looking up the Windows error 2148073494, I get nte_bad_keyset
. It looks like there have been errors around other situations that throw this same error here, but they closed that bug as fixed. When I run this bit of code in a console app, it works fine and it also works fine in my test environment running under IISExpress. When run in a production environment under IIS, I get this error every time. I've tried running under the context of an admin user just to make sure it wasn't an odd permission error, same thing. From what I understand about this Windows error, is that Windows gave me where the key lives, then told me there is nothing at that address. I'm using "System.Security.Cryptography.Algorithms": "4.3.0"
for this.
EDIT: I should note that as part of my testing, I actually grabbed the exact certificate I'm looking for from the production environment onto my test environment and it loaded fine. I also ran the console app on the production environment pulling the same key and it worked fine.
Ultimately, the answer is "something deleted the private key after importing it to the certificate store" (or, maybe it's possible to confuse Windows into remembering where a key lives despite it not actually living there).
If you know that it, for example, works for a little while then stops:
Seeing that it's in "Microsoft RSA SChannel Cryptographic Provider", turn to https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778(v=vs.85).aspx and see that the keyfile will be located at
%ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeys
. TheUnique container name
happens to be the name of the file it'll have.So, open that directory, right click on the file.
Later, after you start getting keyset errors, search the security log for an audit on the file delete (event 4663 from Security-Auditing):
That will tell you what process/user did the delete operation... and maybe that'll be enough to identify what went wrong.
You could presumably do the private key file identification and audit registration more programmatically; but this was the quickest way I knew to explain it.