-
Notifications
You must be signed in to change notification settings - Fork 5k
X509CertificateLoader can't load public key from pfx file without password #115137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones |
The presence of a SID string (.S-1-5-21-2569210111-3594215139-1303219835-11740) is interesting. When you exported the certificate from certmgr, did you use the "Group or user names" option to protect the private key instead of a password? @bartonjs probably remembers better than I do, but DPAPI protected PFX files have some oddities about them that require specific flags to open them. |
@vcsjones : I checked and then unchecked the box, and then keyboard smashed a password. So maybe there's a bug in Windows where it exported it with a user-encrypted private key anyway; or maybe it just remembers the user who exported it. I would be surprised if it matters because I only want the public key anyway. |
@vcsjones @bartonjs https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.pkcs12loaderlimits?view=net-9.0 - perhaps one of the |
The PFX produced by that still uses a password in two places... 1) the integrity MAC (which for the most part serves as "make sure the password is valid when we use it later") 2) the private keys are still encrypted (but the certs aren't) Since the PFX has a MAC, and you've specified a password (as null), and we can't verify the MAC, we fail to load the file. We'd have to add an "IgnoreIntegrityCheck" parameter to the loader limits to support this from normal API. But, since this sounds like advanced usage, you might instead just want to use the Pkcs12Info class. Pkcs12Info info = Pkcs12Info.Decode(File.ReadAllBytes(path), out _);
foreach (Pkcs12SafeContents safeContents in info.AuthenticatedSafe)
{
if (safeContents.ConfidentialityMode == Pkcs12ConfidentialityMode.None)
{
foreach (Pkcs12SafeBag safeBag in safeContents.GetBags())
{
if (safeBag is Pkcs12CertBag certBag)
{
if (certBag.IsX509Certificate)
{
yield return certBag.GetCertificate();
}
}
}
}
} That skips right over the authentication check, ignores all private keys, ignores all attributes, and skips any encrypted SafeContents belonging to the authsafe. |
OK that works. It's kind of embarrassing that I wasn't able to construct a test example of the actual use case. The production use case appears to allow a PFX here but it shouldn't have a private key at all. However I couldn't get any of my tools to generate one without a private key that really shouldn't be there. I guess that's what we get for bad spec writing by whoever wrote this auth spec. It's a base64 encoded certificate, but it's not directly a PEM file. Too bad. Usually it's a base64 encoded CER file, but a base64 encoded PEM file or even a PFX file is also valid(!). |
Description
This should work but doesn't.
I haven't been able to actually remove the private key from the pfx file so I won't be uploading it; however this pfx file is unusual; on examining it on strings it's obvious the public key side is not encrypted.
You can generate one of these yourself: export a key from Windows certificate manager; uncheck enable certificate privacy.
(Yes the certificate really is for localhost)
Reproduction Steps
Expected behavior
Get X509Certificate2 class back without a private key
Actual behavior
throws
Regression?
Kind of
Known Workarounds
No response
Configuration
No response
Other information
No response
The text was updated successfully, but these errors were encountered: