.Net框架更新后的EncryptedXml DecryptDocument方法错误

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

cyn*_*nic 2

我自己无法重现该问题 - 我没有我怀疑是问题所在的“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 一起使用的驱动程序。或者您可以接受上面的黑客,为了更安全而重写。