问题
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.
回答1:
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:
> certutil -store my
...
================ Certificate 6 ================
Serial Number: 3451b93c10f9279348a949f729d1ff10
Issuer: CN=localhost
NotBefore: 1/26/2015 2:19 PM
NotAfter: 1/25/2020 4:00 PM
Subject: CN=localhost
Signature matches Public Key
Root Certificate: Subject matches Issuer
Template:
Cert Hash(sha1): 15 e3 4c d3 2d a7 54 99 a9 17 8f 17 26 25 63 25 8f 3a 94 28
Key Container = IIS Express Development Certificate Container
Unique container name: fad662b360941f26a1193357aab3c12d_1fcb2e07-cec4-4ba1-9c78-58a431e1aefd
Provider = Microsoft RSA SChannel Cryptographic Provider
Encryption test passed
CertUtil: -store command completed successfully.
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
. The Unique container name
happens to be the name of the file it'll have.
So, open that directory, right click on the file.
- Properties
- Security Tab
- Advanced button
- Auditing tab
- Edit button
- Add button
- Type "Everyone", push "Check Names", pick "Everyone", hit OK, hit OK.
- Check Delete: Success.
- Hit OK to dismiss all the dialogs.
Later, after you start getting keyset errors, search the security log for an audit on the file delete (event 4663 from Security-Auditing):
An attempt was made to access an object.
Subject:
Security ID: SOMEDOMAIN\theaccount
Account Name: theaccount
Account Domain: SOMEDOMAIN
Logon ID: 0xabcdef
Object:
Object Server: Security
Object Type: File
Object Name: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\fad662b360941f26a1193357aab3c12d_1fcb2e07-cec4-4ba1-9c78-58a431e1aefd
Handle ID: 0xef8
Process Information:
Process ID: 0xf54
Process Name: C:\Windows\explorer.exe
Access Request Information:
Accesses: DELETE
Access Mask: 0x10000
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.
来源:https://stackoverflow.com/questions/41479755/net-core-x509certificate2-privatekey-throws-nte-bad-keyset-error