Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline strogen  
#1 Оставлено : 20 ноября 2017 г. 10:32:24(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Добрый день.

Crypto PRO
Версия C1rypto PRO CSP 4.0.9842
.NET SDK 1.0.6262.0

Web app:
ASP.NET MVC 5
Framework.NET 4.6.1

Столкнулись с такой проблемой.
После интенсивного использования методов симметричного шифрования приложение (w3wp.exe) не освобождает handle.
В итоге шифрование перестает работать и приложение падает.

Происходит это при восстановлении криптопровайдера из сессионного ключа

Код:

        /// <summary>
        /// Восстанавливает симметричный ключ шифрования
        /// </summary>
        /// <param name="cryptoDataInfo"></param>
        /// <param name="storeLocation"></param>
        /// <param name="thumbprint"></param>
        /// <returns></returns>
        public static Gost28147 GetSymmetricAlgorithm(CryptoDataInfo cryptoDataInfo, StoreLocation storeLocation, string thumbprint)
        {
            Gost3410CryptoServiceProvider gost3410Crypto = null;
            try
            {
                gost3410Crypto = PrivateKeyFromSertificate(storeLocation, thumbprint);

                GostKeyExchangeDeformatter keyDeformatter = new GostKeyExchangeDeformatter(gost3410Crypto);
                // Восстановление по данным обмена симметричного ключа на основе ГОСТ Р 34.10 транспорта.
                SymmetricAlgorithm symmetric = keyDeformatter.DecryptKeyExchangeData(cryptoDataInfo.SessionKey);
                symmetric.IV = cryptoDataInfo.IV;

                Gost28147 gost28147 = symmetric as Gost28147;
                if (gost28147 == null)
                    throw new CryptographicException("Алгоритм не является алгоритмом ГОСТ 28147.");

                return gost28147;
            }
            finally
            {
                gost3410Crypto?.Clear();

                gost3410Crypto?.Dispose();
            }
        }


Дальше в коде мы используем этот метод и очищаем криптопровайдер.

Код:

    /// <summary>
    /// Класс реализует алгоритм шифрования данных по ГОСТ 28147
    /// </summary>
    public static class Encryptor
    {
        /// <summary>
        /// Шифрование данных
        /// </summary>
        /// <param name="inputCryptoDataInfo">Информация о данных для шифрования</param>
        /// <param name="publicKeyParameters"></param>
        /// <param name="storeLocation">Задает расположение хранилища сертификатов X.509</param>
        /// <param name="thumbprint">Отпечаток сертификата</param>
        /// <returns>Возвращает результат шифрования данных или CryptographicException</returns>
        public static CryptoDataInfo Encrypt(CryptoDataInfo inputCryptoDataInfo, string publicKeyParameters, StoreLocation storeLocation, string thumbprint)
        {
            // Открытый ключ получателя.
            Gost3410CryptoServiceProvider gost3410 = null;
            // Симметричный ключ, реализующий алгоритм ГОСТ 28147
            Gost28147 gost28147 = null;
            try
            {
                // Создаем Открытый ключ получателя.
                gost3410 = new Gost3410CryptoServiceProvider(); 

                    //Добавляем ключевую информацию получателя
                    gost3410.ImportParameters(JsonConvert.DeserializeObject<Gost3410Parameters>(publicKeyParameters));

                // Создаем форматер, шифрующий на асимметричном ключе получателя.
                GostKeyExchangeFormatter formatter = new GostKeyExchangeFormatter(gost3410);

                if (inputCryptoDataInfo.SessionKey == null || inputCryptoDataInfo.IV == null)
                {
                    // Создаем симметричный ключ.
                    gost28147 = Gost28147.Create();
                }
                else
                {
                    // Восстановим существующий
                    gost28147 = CryptoUtils.GetSymmetricAlgorithm(inputCryptoDataInfo, storeLocation, thumbprint);
                }

                var result = new CryptoDataInfo
                {
                    SessionKey = formatter.CreateKeyExchangeData(gost28147),
                    IV = gost28147.IV,
                    Data = GostEncrypt(gost28147, inputCryptoDataInfo.Data)
                };

                // Шифруем

                return result;
            }
            catch (Exception ex)
            {
                Logger.Log.Error($"Шифрование данных - Ошибка. {ex.Message}", ex);
                throw new CryptographicException("Ошибка шифрования данных.", ex);
            }
            finally
            {
                // Освобождаем ресурсы
                gost28147?.Clear();
                gost3410?.Clear();

                gost28147?.Dispose();
                gost3410?.Dispose();
            }
        }

        // Шифруем байтовый массив
        private static byte[] GostEncrypt(Gost28147 key, byte[] sourceBytes)
        {
            using (var encryptedStream = new MemoryStream())
            {
                // Создаем шифратор для ГОСТ.
                using (var encryptor = (CPCryptoAPITransform)key.CreateEncryptor())
                {
                    using (var cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
                    {
                        using (var originalByteStream = new MemoryStream(sourceBytes))
                        {
                            int data;
                            while ((data = originalByteStream.ReadByte()) != -1)
                                cryptoStream.WriteByte((byte)data);
                        }
                    }
                }

                var encryptedBytes = encryptedStream.ToArray();
                return encryptedBytes;
            }
        }
    }
Offline strogen  
#2 Оставлено : 21 ноября 2017 г. 13:00:34(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Товарищи, разработчики! Может у Вас есть какие-то идеи по этому вопросу? Очень критично!
Offline Максим Коллегин  
#3 Оставлено : 21 ноября 2017 г. 20:21:12(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,377
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 706 раз в 614 постах
Я не смог понять из поста, где и когда конкретно возникает проблема.
Знания в базе знаний, поддержка в техподдержке
Offline strogen  
#4 Оставлено : 22 ноября 2017 г. 9:59:30(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Добрый день,

В методе Encrypt
строка 35
Код:

// Восстановим существующий
gost28147 = CryptoUtils.GetSymmetricAlgorithm(inputCryptoDataInfo, storeLocation, thumbprint);


Сам метод GetSymmetricAlgorithm приведен выше.

Отредактировано пользователем 22 ноября 2017 г. 10:00:25(UTC)  | Причина: Не указана

Offline strogen  
#5 Оставлено : 23 ноября 2017 г. 14:41:52(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Добавляю stack trace
Код:

Шифрование данных - Ошибка. The keyset is not defined.

System.Security.Cryptography.CryptographicException: The keyset is not defined.

   at CryptoPro.Sharpei.COMCryptography.ImportCspBlob(Byte[] keyBlob, SafeProvHandleCP hProv, CspProviderFlags flags, SafeKeyHandleCP hImportKey, SafeKeyHandleCP& hKey)
   at CryptoPro.Sharpei.GostSharedSecretCryptoServiceProvider.CryptoProUnwrap(Byte[] wrapped)
   at CryptoPro.Sharpei.GostKeyExchangeDeformatter.DecryptKeyExchangeData(Byte[] data)
   at Platform.BusinessLogic.Crypto.CryptoUtils.GetSymmetricAlgorithm(CryptoDataInfo cryptoDataInfo, StoreLocation storeLocation, String thumbprint) 

System.Security.Cryptography.CryptographicException: Insufficient memory available for the operation.

Offline Максим Коллегин  
#6 Оставлено : 23 ноября 2017 г. 18:03:01(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,377
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 706 раз в 614 постах
А в eventlog есть интересные записи?
Попробуйте сделать законеченный пример - я постараюсь запустить и отследить утечку хэндлов.

Знания в базе знаний, поддержка в техподдержке
Offline strogen  
#7 Оставлено : 24 ноября 2017 г. 10:30:27(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Добрый день, во вложении консольное приложение, повторяющее описанную проблему.
Перед запуском поставьте приложенный сертификат или в коде укажите другой.
И для того, чтобы долго не ждать ошибки, мы на dev машине ограничиваем через реестр кол-во хэндлов.

В Events log есть вот такое:

КриптоПро CSP. Ошибка при создании нового дескриптора. Текущая заполненность таблицы дескрипторов: 2049/2048 (no entries left). Размер таблицы можно задать в реестре: HKLM\SOFTWARE\[WOW6432Node\]Crypto Pro\Cryptography\CurrentVersion\Parameters\MaxHandles=dword:степень_двойки. Минимальное значение: 4096, максимальное значение: 67108864, по умолчанию: 1048576. Размером будет половина указанного значения.

Заранее спасибо!

CryptoTest.zip (524kb) загружен 5 раз(а).
Offline Максим Коллегин  
#8 Оставлено : 24 ноября 2017 г. 18:41:59(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,377
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 706 раз в 614 постах
Спасибо за обратную связь и сэмпл. Ошибку нашёл, попробую исправить в ближайшее время. Собрал тестовую сборку - проверьте пожалуйста, что проблема ушла, а новые не появились)
https://www.cryptopro.ru.../1.0.6537.3/NETSetup.exe

Отредактировано пользователем 24 ноября 2017 г. 22:59:31(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
Offline strogen  
#9 Оставлено : 27 ноября 2017 г. 15:28:04(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Спасибо огромное!
Стало намного лучше.
Но где-то еще осталась утечка (хэндлы освобождаются, но не все), ищем где.
Как только что-то будет известно отпишусь.
Offline strogen  
#10 Оставлено : 1 декабря 2017 г. 13:02:37(UTC)
strogen

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.06.2017(UTC)
Сообщений: 8
Российская Федерация

Прошу прощения за задержку.
Мы протестировали, подтверждаю, проблема решена.
Спасибо за оперативность.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.