-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
This happens when calling GetRSAPrivateKey on a certificate with a persisted private key… after having called Export(PFX) on the cert.
-
Cert is found from the store, it has the named private key info property (2), but not the “I have a loaded NCrypt key handle” property (78)
-
Call export(PFX). Inside PFXExportCertStore it needs to load the private key (to export it), and apparently it caches it back on the cert object (property 78).
-
Then you call GetRSAPrivateKey(). We see that prop 78 was set, which hitherto has only happened from loading certs in an ephemeral context. So we tell the CngKey object that IsEphemeral is true.
-
For… some… reason… the IsEphemeral property writes the property persisted. Since this is actually a persisted key object, the property is actually written to the key store vs just in the ephemeral key’s ephemeral property bag.
-
This object is now already loaded on the cert (prop 78) and knows it’s ephemeral (from the property), so it’s happy for all further uses on this instance.
-
Read the cert from the store again (same process, different process, doesn’t matter). Prop 2 is set, Prop 78 is not.
-
Call GetRSAPrivateKey. We’re doing a cold-load (no prop 78). We load the key, and check “it better not claim to have a ‘CLR IsEphemeral’ property, because I don’t know what it means for a persisted key to claim it’s ephemeral”. Explode.
I don’t know that this would have been something that changed in Windows (since I reproed it on 2012R2). We can forward fix the problem by checking for prop 2 before we assert that a prop-78 load means an ephemeral key.
After calling cert2.Export(PFX):
Attached repro can be found here https://github.com/javiercn/certificaterepro