I have an old function written in 2013 that decrypt xml that was encrypted by another program.
The code is realy simple
public static void Decrypt(XmlDocument Doc)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml(Doc);
// Decrypt the XML document.
exml.DecryptDocument();
}
It worked like a charm until recently that some of our clients started to upgrade their framework to 4.6.2, so the method DecryptDocument() stopped working. Now it throws an exception "The algorithm group '' is invalid". If I remove .net framework 4.6.2 it works again.
The sample code in this link will reproduce the error, it will encrypt successfully then fail to decrypt.
I'm using A3 certificates, pendrive token. Anyone have faced this problem? there is any work around in .net 4.6.2?
Edit 1:
Stacktrace:
at System.Security.Cryptography.CngAlgorithmGroup..ctor(String algorithmGroup)
at System.Security.Cryptography.CngKey.get_AlgorithmGroup()
at System.Security.Cryptography.RSACng..ctor(CngKey key)
at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2 certificate)
at System.Security.Cryptography.CngLightup.GetRSAPrivateKey(X509Certificate2 cert)
at System.Security.Cryptography.Xml.EncryptedXml.DecryptEncryptedKey(EncryptedKey encryptedKey)
at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData encryptedData, String symmetricAlgorithmUri)
at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument()
at Criptografar.Program.Decrypt(XmlDocument Doc) in C:\Users\leoka\Documents\Visual Studio 2017\Projects\ConsoleApp4\Criptografar\Program.cs:line 152
at Criptografar.Program.Main(String[] args) in C:\Users\leoka\Documents\Visual Studio 2017\Projects\ConsoleApp4\Criptografar\Program.cs:line 83
I cannot reproduce the problem myself - I don't have the "pendrive token" which I suspect is the problem - so this is guesswork.
There are two generations of cryptographic APIs in Windows - the "old" one and the "new generation" one, known as CNG.
Now, if you look at the source code for the CngLightup
type that appears midway through your stack trace, specifically the DetectRsaCngSupport
method, you'll see that .NET framework tries to use the new generation API if possible. My guess is that the "pendrive token" device does not support the new API. You can verify this by forcing the use of the old API. Unfortunately, there does not seem to be a public configuration flag that controls this, so you must resort to reflection-based hacks. For example, you can put something like this at the beginning of your program, so that it runs once, before you try the decrypting operation:
var cngLightupType = typeof(EncryptedXml).Assembly.GetType("System.Security.Cryptography.CngLightup");
var preferRsaCngField = cngLightupType.GetField("s_preferRsaCng", BindingFlags.Static | BindingFlags.NonPublic);
var getRsaPublicKeyField = cngLightupType.GetField("s_getRsaPublicKey", BindingFlags.Static | BindingFlags.NonPublic);
var getRsaPrivateKeyField = cngLightupType.GetField("s_getRsaPrivateKey", BindingFlags.Static | BindingFlags.NonPublic);
preferRsaCngField.SetValue(null, new Lazy<bool>(() => false));
getRsaPublicKeyField.SetValue(null, null);
getRsaPrivateKeyField.SetValue(null, null);
Do note that it is extremely hacky, not thread-safe, error handling is omitted etc. If you verify that the CNG usage is the problem, you can then ask the "pendrive token" supplier to provide drivers that work with CNG. Or you can live with the hack above, rewritten for more safety.
There are some runtime changes in .Net 4.6.2 that affect EncrtyptedXml
- see https://msdn.microsoft.com/en-us/library/mt670901(v=vs.110).aspx#Anchor_5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With