Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ 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,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Я не смог понять из поста, где и когда конкретно возникает проблема.
Знания в базе знаний, поддержка в техподдержке
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,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
А в 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,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Спасибо за обратную связь и сэмпл. Ошибку нашёл, попробую исправить в ближайшее время. Собрал тестовую сборку - проверьте пожалуйста, что проблема ушла, а новые не появились)
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 Лента
Пользователи, просматривающие эту тему
Перейти  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.