Leo*_*ier 11 c# xml encryption encryption-asymmetric x509certificate2
我有一个2013年写的旧函数解密由另一个程序加密的xml.
代码非常简单
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();
}
Run Code Online (Sandbox Code Playgroud)
直到最近,我们的一些客户才开始将其框架升级到4.6.2,因此方法DecryptDocument()停止工作.现在它抛出异常"算法组''无效".如果我删除.net框架4.6.2它再次工作.
此链接中的示例代码将重现错误,它将成功加密然后无法解密.
我正在使用A3证书,pendrive令牌.有人遇到过这个问题吗?在.net 4.6.2中有什么工作吗?
编辑1:
堆栈跟踪:
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
我自己无法重现该问题 - 我没有我怀疑是问题所在的“pendrive 令牌” - 所以这是猜测。Windows 中有两代加密 API - “旧”一代和“新一代”(称为 CNG)。现在,如果您查看堆栈跟踪中间出现的类型的源代码CngLightupDetectRsaCngSupport,特别是方法,您将看到 .NET 框架在可能的情况下尝试使用新一代 API。我的猜测是“pendrive token”设备不支持新的 API。您可以通过强制使用旧 API 来验证这一点。不幸的是,似乎没有公共配置标志来控制这一点,因此您必须诉诸基于反射的黑客。例如,您可以在程序开头放置类似的内容,以便在尝试解密操作之前运行一次:
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);
Run Code Online (Sandbox Code Playgroud)
请注意,它非常 hacky,不是线程安全的,省略了错误处理等。如果您验证 CNG 的使用是问题所在,那么您可以要求“pendrive 令牌”供应商提供与 CNG 一起使用的驱动程序。或者您可以接受上面的黑客,为了更安全而重写。