Статус: Новичок
Группы: Участники
Зарегистрирован: 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;
}
}
}
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.06.2017(UTC) Сообщений: 8
|
Товарищи, разработчики! Может у Вас есть какие-то идеи по этому вопросу? Очень критично!
|
|
|
|
Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,375 Откуда: КРИПТО-ПРО Сказал «Спасибо»: 32 раз Поблагодарили: 704 раз в 613 постах
|
Я не смог понять из поста, где и когда конкретно возникает проблема. |
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.06.2017(UTC) Сообщений: 8
|
Добрый день, В методе Encrypt строка 35 Код:
// Восстановим существующий
gost28147 = CryptoUtils.GetSymmetricAlgorithm(inputCryptoDataInfo, storeLocation, thumbprint);
Сам метод GetSymmetricAlgorithm приведен выше. Отредактировано пользователем 22 ноября 2017 г. 10:00:25(UTC)
| Причина: Не указана
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 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.
|
|
|
|
Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,375 Откуда: КРИПТО-ПРО Сказал «Спасибо»: 32 раз Поблагодарили: 704 раз в 613 постах
|
А в eventlog есть интересные записи? Попробуйте сделать законеченный пример - я постараюсь запустить и отследить утечку хэндлов.
|
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 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 раз(а).
|
|
|
|
Статус: Сотрудник
Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC) Сообщений: 6,375 Откуда: КРИПТО-ПРО Сказал «Спасибо»: 32 раз Поблагодарили: 704 раз в 613 постах
|
|
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.06.2017(UTC) Сообщений: 8
|
Спасибо огромное! Стало намного лучше. Но где-то еще осталась утечка (хэндлы освобождаются, но не все), ищем где. Как только что-то будет известно отпишусь.
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.06.2017(UTC) Сообщений: 8
|
Прошу прощения за задержку. Мы протестировали, подтверждаю, проблема решена. Спасибо за оперативность.
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close