问题
I have a problem with X509AsymmetricSecurityKey.GetAsymmetricAlgorithm running in a standard unit test. The test has been passing for years running on .Net Framework version 4.5.2 (C#), however since upgrading the project to version 4.7.2 it has ben failing as GetAsymmetricAlgorithm returns null. The exact same code runs perfect outside the test.
X509Certificate2 cert = null;
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
// I'm actually using FindByThumbprint, just changing this here to protect keys
cert = store.Certificates[0];
// cert is valid X509, securityKey is valid
X509AsymmetricSecurityKey securityKey = new X509AsymmetricSecurityKey(cert);
// rsa is null
RSACryptoServiceProvider rsa = securityKey.GetAsymmetricAlgorithm(SecurityAlgorithms.RsaSha256Signature, true) as RSACryptoServiceProvider;
Same code, same certificate, running though test GetAsymmetricAlgorithm returns null, running on "live" code (class library called from WebAPI) it works perfect.
Any ideas why? I can't see anything in the docs for previous .Net version changes, nothing in the Microsoft docs.
https://docs.microsoft.com/en-us/dotnet/api/system.identitymodel.tokens.x509asymmetricsecuritykey.getasymmetricalgorithm?view=netframework-4.7.2
Thanks for any help on this.
回答1:
As Crypt32 suggested in a comment, the problem is that after you upgraded from targeting <= 4.6.2 to targeting 4.7(+) you got a "retargeting change" which says that GetAsymmetricAlgorithm is allowed to return instances of RSACng, which is the better RSA class in .NET Framework.
The best action in your code is to change the line to
RSA rsa = securityKey.GetAsymmetricAlgorithm(SecurityAlgorithms.RsaSha256Signature, true) as RSA;
Then find the places that the code no longer compiles, and change from the RSACryptoServiceProvider variant method to the new RSA (base class) methods. (e.g. SignData(byte[], object)
=> SignData(byte[], RSASignaturePadding)
).
You really want to avoid saying RSACng
or RSACryptoServiceProvider
if you can help it, since there are theoretical cases where RSACng
won't work, and RSACryptoServiceProvider
will be returned instead (older smartcards / HSMs which have a CAPI driver, but not a CNG driver).
This particular retargeting change is the System.IdentityModel version of https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/retargeting/4.5-4.7.2#wcf-transport-security-supports-certificates-stored-using-cng, which seems to have not been written down. If you need to turn this off, the setting name is Switch.System.IdentityModel.DisableCngCertificates
.
来源:https://stackoverflow.com/questions/53535972/x509asymmetricsecuritykey-getasymmetricalgorithm-returns-null-after-net-4-7-2-u