-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Cannot export RSAParameters from X509Certificate2 in .NET 9 RC2 #109059
Comments
|
@vcsjones Thanks for quick response. Attached the file. Had to change the extension to .log because GH did not allow me to attach the PFX directly. |
In general I am surprised this worked with .NET 8 - it is known that exporting plaintext from Windows does not work reliably. See #26031 and #77590 for some previous discussion on this. You can work around this in .NET 9 like so, using the work arounds discussed in the linked issues: using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Runtime.InteropServices;
Console.WriteLine(RuntimeInformation.FrameworkDescription);
var certBytes = File.ReadAllBytes("customer.pfx");
var cert = new X509Certificate2(certBytes, (string)null, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet);
RSAParameters p;
using (RSA tmp = RSA.Create())
using (RSA key = cert.GetRSAPrivateKey())
{
const string pwd = "TempPassword";
PbeParameters pbeParameters = new PbeParameters(PbeEncryptionAlgorithm.Aes128Cbc, HashAlgorithmName.SHA256, 1);
tmp.ImportEncryptedPkcs8PrivateKey(pwd, key.ExportEncryptedPkcs8PrivateKey(pwd, pbeParameters), out _);
p = tmp.ExportParameters(true);
}
// p now contains the RSA parameters. However, we should try look at why this worked in .NET 8. |
So this was introduced by #107005 |
The commit message pointed out the problem here:
(Where I think I meant "no CSP attribute" instead of "no name"). This PFX does not specify a CSP for the private key, which is why the ctor and X509CertificateLoader both load it into CNG now. On .NET 8 and older (including .NET Framework) it was being loaded into the CAPI "Base Cryptographic Provider", which would mean that it gets really bad usability as But, really, this is just yet another instance of ".NET had ExportParameters long before there was a crypto subsystem that made a distinction between export-encrypted and export-plaintext... and we should consider hiding the difference in our layer instead of making someone write the workaround themselves." The workaround being // I didn't verify this compiles, it's the gist of the answer...
private static readonly PbeParameters s_pbeParams = new PbeParameters(PbeAlgorithm.TripleDesPkcs12, HashAlgorithmName.SHA1, 1);
...
using (RSA priv = cert.GetRSAPrivateKey())
using (RSA temp = RSA.Create())
{
temp.ImportEncryptedPkcs8PrivateKey(priv.ExportEncryptedPkcs8PrivateKey("", s_pbeParams), "", out _);
return temp.ExportParameters(true);
} Since the workaround exists, and is trivial, and we already know the caller intent, and we're going to hit it a lot more often as people move to X509CertificateLoader... we should just tackle it in the platform. |
Re-opening for backport. |
This will be fixed in .NET 9 GA by #109134. Thank you very much for the report! |
Description
I've noticed a discrepancy in behavior between .NET 8 and 9 (RC2) when it comes to the ability to export the RSAParameters (with private) between .NET 8 and .NET 9.
From a quick investigation it looks like ExportPolicy is different between those two frameworks despite passing same X509KeyStorageFlags parameters to the X509Certificate2 ctor (tried X509CertificateLoader as well).
I'm running this on Windows.
Reproduction Steps
I can paste the PFX if needed. Got it from the staging Let's Encrypt.
Expected behavior
On .NET 8 I'm getting following output from the console writeline
Actual behavior
On .NET 9 RC2 I'm getting following output:
I'm suspecting that the exception is caused because of the missing 'AllowPlaintextExport' flag.
Regression?
Yes?
Known Workarounds
No response
Configuration
Other information
No response
The text was updated successfully, but these errors were encountered: