Ошибка EncryptedXml DecryptDocument после обновления .Net framework

У меня есть старая функция, написанная в 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();

    }

До недавнего времени он работал как шарм, что некоторые из наших клиентов начали обновлять свою структуру до 4.6.2, поэтому метод DecryptDocument() перестает работать. Теперь он выдает исключение "Группа алгоритмов" недействительна ". Если я удалю .NET Framework 4.6.2, он снова работает.

Пример кода в этой ссылке будет воспроизводить ошибку, он будет успешно зашифрован, а затем не сможет расшифровать.

Я использую сертификаты A3, токен pendrive. Кто-нибудь столкнулся с этой проблемой? есть какая-нибудь работа в .net 4.6.2?

Изменить 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

Ответ 1

Я не могу воспроизвести проблему самостоятельно - у меня нет "маркера pendrive", который, как я подозреваю, является проблемой, - так что это догадки. В Windows два поколения криптографических API-интерфейсов - "старый" и "новое поколение" , известное как CNG. Теперь, если вы посмотрите на исходный код для CngLightup типа, который появляется на полпути через вашу трассировку стека, в частности метод DetectRsaCngSupport вы увидите, что .NET framework пытается использовать 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);

Заметьте, что он чрезвычайно хакерский, не потокобезопасный, обработка ошибок не указана и т.д. Если вы убедитесь, что проблема использования CNG является проблемой, вы можете попросить поставщика маркера "pendrive" предоставить драйверы, которые работают с CNG, Или вы можете жить с взломом выше, переписанным для большей безопасности.

Ответ 3

Сегодня я столкнулся с чем-то очень похожим, что оказалось ошибкой в ​​.NET 4.6.2: https://github.com/Microsoft/dotnet/issues/341

В соответствии с этим вопросом есть два способа:

1) Модернизация ОС до Windows Server 2012R2 или новее, 2) загрузка профиль пользователя.