CryptographicException: «Указан неверный алгоритм» при использовании SHA-512 - PullRequest
0 голосов
/ 03 января 2019

В моем приложении WPF (.NET 4.6) мне необходимо использовать файл сертификата P12 для подписания строки с использованием алгоритма SHA-512 (для включения в заголовок веб-запроса). Я делаю так:

using (var rsa = myX509Certificate2.GetRSAPrivateKey()) {
  myBytes = rsa.SignData(
    Encoding.UTF8.GetBytes(stringToSign), 
    HashAlgorithmName.SHA512, 
    RSASignaturePadding.Pkcs1
  );
}

Это работает в тестировании и почти для всех моих клиентов, но случайный клиент получает следующее исключение:

System.Security.Cryptography.CryptographicException: Invalid algorithm specified.
  at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
  at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
  at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
  at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
  at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
  at System.Security.Cryptography.RSA.SignData(Byte[] data, Int32 offset, Int32 count, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
  at System.Security.Cryptography.RSA.SignData(Byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)

Это произошло совсем недавно с клиентом в Windows 7 SP1.

Я изо всех сил пытаюсь найти ответ через существующие вопросы SO или от Google в целом. Из того, что я могу сказать, это может быть связано с тем, что неподдерживаемый поставщик служб криптографии Windows используется скрытно, но я не уверен, так как не могу сам повторить ошибку.

Есть идеи, как решить эту проблему, либо с помощью кода, либо с помощью затронутых клиентов установить какие-либо конкретные обновления Windows?

1 Ответ

0 голосов
/ 03 января 2019

Если вы используете cert.GetRSAPrivateKey() и он возвращает экземпляр RSACryptoServiceProvider, который предполагает, что он не из PFX, а со смарт-карты со старым драйвером. Поскольку вы говорите, что это из .p12 / .pfx, это может означать, что PFX содержит ссылку на обычное имя провайдера криптографических услуг, которое CNG не взял на себя (но я никогда не видел этого в программном ключе). (Бритва Оккама задает один вопрос: вы уверены, что они случайно не используют неправильный сертификат?)

Если вы знаете, что это из PFX, и вы импортировали его с помощью бита Exportable, вы можете вручную преобразовать его из RSACryptoServiceProvider в RSACng:

using (RSA rsa = cert.GetRSAPrivateKey())
{
    byte[] toSign = Encoding.UTF8.GetBytes(stringToSign);
    myBytes = null;

    try
    {
        myBytes = rsa.SignData(
            toSign, 
            HashAlgorithmName.SHA512, 
            RSASignaturePadding.Pkcs1);
    }
    catch (CryptographicException)
    {
        try
        {
            using (RSA rsaCng = new RSACng())
            {
                rsaCng.ImportParameters(rsa.ExportParameters(true));

                myBytes = rsaCng.SignData(
                    toSign,
                    HashAlgorithmName.SHA512, 
                    RSASignaturePadding.Pkcs1);
            }
        }
        catch
        {
        }

        if (myBytes == null)
        {
            // Let the original exception continue
            throw;
        }
    }
}

(В качестве альтернативы исходному выбрасыванию исключения вы могли бы разрешить вместо этого выдавать исключение «повторная попытка»)


Кроме того, в Windows 10 исправлено множество поведений RSACryptoServiceProvider «недопустимый алгоритм», поэтому они всегда могли попробовать обновить.

...