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

Уведомление

Icon
Error

3 Страницы123>
Опции
К последнему сообщению К первому непрочитанному
Offline esolomonov  
#1 Оставлено : 12 августа 2020 г. 12:47:56(UTC)
esolomonov

Статус: Участник

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

Добрый день!

До настоящего момента мы расшифровывали небольшие файлы, но теперь потребовалась обработка файлов размером около 200 МБ. Столкнулся с тем, что чтение контейнера CMS дает ошибку:

ASN1 value too large

Происходит это в этом месте кода:

Код:
public static byte[] Decrypt(byte[] encodedCms, X509Certificate2 certificate)
{
    EnvelopedCms envelopedCms = new EnvelopedCms();

    envelopedCms.Decode(encodedCms);
    ...
}


Кто может поделиться опытом чтения больших файлов в формате контейнера CMS?

Сам я смог найти только вот эту библиотеку, которую разработал один добрый человек для чтения больших CMS:

https://archive.codeplex.com/?p=largecms

Но увы, у меня чтение 200 МБ CMS в этой библиотеке происходит так медленно, что пользоваться ею возможности нет. Процесс надолго останавливается в цикле чтения файла через функцию Win32 CryptMsgUpdate, которая читает файл порциями. Пробовал менять размер порций, но это никак не ускоряет процесс.

Может быть у кого-то есть опыт чтения и дешифрации больших файлов на C#? Я просто еще даже не дошел до расшифровки, может быть там тоже все зависнет, я не знаю. В Крипто Про Арме же процесс шифрования/дешифрования этого файла (200 МБ) происходит минут за 6-7, что вполне приемлемо.

Заранее всем спасибо.
Offline Андрей *  
#2 Оставлено : 12 августа 2020 г. 12:55:21(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Автор: esolomonov Перейти к цитате
В Крипто Про Арме же процесс шифрования/дешифрования этого файла (200 МБ) происходит минут за 6-7, что вполне приемлемо.

Это опечатка...?

Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей *  
#3 Оставлено : 12 августа 2020 г. 13:03:54(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Может проблема с диском?

Использую CryptMsgUpdate (на c# не проверял):
шифрование 150 Мб - 5 сек
расшифровка - так же


на медленном диске:
Размер файла: 230 Мб - 9 сек.
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#4 Оставлено : 12 августа 2020 г. 13:05:20(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
Автор: esolomonov Перейти к цитате
В Крипто Про Арме же процесс шифрования/дешифрования этого файла (200 МБ) происходит минут за 6-7, что вполне приемлемо.

Это опечатка...?



Что-то я преувеличил, на расшифровку этого файла (200 МБ в base64) ушло 23 секунды.
Offline esolomonov  
#5 Оставлено : 12 августа 2020 г. 13:16:05(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
Может проблема с диском?

Использую CryptMsgUpdate (на c# не проверял):
шифрование 150 Мб - 5 сек
расшифровка - так же


на медленном диске:
Размер файла: 230 Мб - 9 сек.


Удивительно...

Вот часть кода библиотеки, на которую я ссылался, вот тут все зависает надолго. Причем в отладке видно, что все работает, просто очень медленно:

Код:
public unsafe static void ProcessMessage(SafeMsgHandle hMsg, FileStream file)
{
	// Variables
	BinaryReader stream = null;
	byte[] pbData = null;
	long dwRemaining = 0;
	bool bFinal = false;
	bool bResult = false;

	// Process message
	dwRemaining = file.Length;
	stream = new BinaryReader(file);
	do
	{
		// Read one chunk of data
		pbData = stream.ReadBytes(1024 * 1000 * 10);
		if (pbData.Length == 0)
		{
			break;
		}

		// Update message piece by piece    
		bFinal = (dwRemaining <= 1024 * 1000 * 10);
		fixed (byte* pAux = &pbData[0])
		{
			bResult = CryptMsgUpdate(
				hMsg.DangerousGetHandle(),
				new IntPtr(pAux),
				pbData.Length,
				bFinal
			);
			if (!bResult)
			{
				throw new Exception("CryptMsgUpdate error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
			}
		}
		dwRemaining = dwRemaining - pbData.Length;

	} while (!bFinal);
}


Я здесь в 10 раз уменьшил размер порции, потому что при изначальном размере я просто не мог дождаться даже одного вызова CryptMsgUpdate. Дело точно не в диске, потому что с диска я файл байтами читаю моментально, за секунду. К этому моменту он уже прочтен.

Вот же беда...
Offline Андрей *  
#6 Оставлено : 12 августа 2020 г. 13:27:38(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
А если исправить на 1024 * 1024?
у меня по 1 Мб в тесте.
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#7 Оставлено : 12 августа 2020 г. 14:10:11(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
А если исправить на 1024 * 1024?
у меня по 1 Мб в тесте.


Я почему-то как всегда забыл начать с примеров в SDK. Впрочем, там тоже самое. Но теперь просто я напишу более предметно. Итак, моя задача расшифровать большой файл, потом проверить подпись и снять ее. Есть пример в SDK: StreamVerify.cs. К сожалению, он не расшифровывает файл, а проверяет подпись. Но в начале в этом примере файл формата CMS читается, а мне это как раз и нужно. Как потом расшифровывать — это второй вопрос. Для начала хочется хотя бы прочесть файл. Файл у меня размером 200 МБ (бинарный). Я запускаю пример в оригинальном виде, там буфер чтения равен как раз 1 МБ (1024*1024). Так вот, 8% файла у меня читается 2 минуты. Это очень медленно!

Вопрос: почему?

Кусок кода — цикл чтения из SDK:

Код:
while (dwRemaining > 0)
{
	inFile.Read(pbData, 0, dwSize);

	// Вызываем обработку блока
	bResult = CMSWin32.CryptMsgUpdate( hMsg, pbPtr,
		dwSize, (dwRemaining <= dwSize) ? true : false );
	if (!bResult)
	{
		throw new CryptographicException(
			"CryptMsgUpdate error #" + 
			Marshal.GetLastWin32Error().ToString(), 
			new Win32Exception(Marshal.GetLastWin32Error()));
	}

	// Переходим к следующему блоку
	dwRemaining -= dwSize;
	if (dwRemaining < dwSize)
	{
		dwSize = (int)dwRemaining;
	}
	if (progress != null)
		progress(dwFileSize, dwRemaining);
}

Offline Андрей *  
#8 Оставлено : 12 августа 2020 г. 14:20:11(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
а этот файл, 200МБ - он из другой ИС?

Предлагаю зашифровать для теста файл (через КриптоАРМ, другое приложение) и расшифровать в C#.
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#9 Оставлено : 12 августа 2020 г. 14:35:06(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
а этот файл, 200МБ - он из другой ИС?

Предлагаю зашифровать для теста файл (через КриптоАРМ, другое приложение) и расшифровать в C#.


Файл 200 Мб я сам зашифровал в Крипто Арме.
Offline esolomonov  
#10 Оставлено : 12 августа 2020 г. 14:50:46(UTC)
esolomonov

Статус: Участник

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

А может кто подскажет где найти примеры потоковой расшифровки? В SDK нет :(
Offline Андрей *  
#11 Оставлено : 12 августа 2020 г. 14:52:56(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Автор: esolomonov Перейти к цитате
А может кто подскажет где найти примеры потоковой расшифровки? В SDK нет :(


CryptMsgUpdate + еще несколько функций CryptMsg* - это как раз и есть...
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#12 Оставлено : 12 августа 2020 г. 15:04:13(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
Автор: esolomonov Перейти к цитате
А может кто подскажет где найти примеры потоковой расшифровки? В SDK нет :(


CryptMsgUpdate + еще несколько функций CryptMsg* - это как раз и есть...


Я нашел примеры только на Си, не представляю как их адаптировать к C#. В примерах даже нет структур Windows, которые нужны для этого. У вас нет рабочего примера?
Offline Андрей *  
#13 Отправлено: : 12 августа 2020 г. 15:13:01(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Автор: esolomonov Перейти к цитате
Автор: Андрей * Перейти к цитате
Автор: esolomonov Перейти к цитате
А может кто подскажет где найти примеры потоковой расшифровки? В SDK нет :(


CryptMsgUpdate + еще несколько функций CryptMsg* - это как раз и есть...


Я нашел примеры только на Си, не представляю как их адаптировать к C#. В примерах даже нет структур Windows, которые нужны для этого. У вас нет рабочего примера?


у Вас же все под рукой, в том примере largecms - описаны все функции (Win32.cs)
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#14 Оставлено : 12 августа 2020 г. 15:27:27(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате


у Вас же все под рукой, в том примере largecms - описаны все функции (Win32.cs)


Спасибо! Я про largecms успел забыть, увлекся примерами из SDK. Кажется в largecms все есть. Остался вопрос только со скоростью работы, при такой скорости внедрить в продакшн все равно не получится :(
Offline Андрей *  
#15 Оставлено : 12 августа 2020 г. 15:33:00(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
попробовал через largecms - 13с на 10 мб файле + нагружает ЦП
посмотрел вызовы...

Вам понятно, что делает ProcessMessage?

почему потом вызывается CheckEnvelopeAlg?
и... в финале Decrypt?
Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей *  
#16 Оставлено : 12 августа 2020 г. 15:42:07(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
CryptMsgOpenToDecode

выделение памяти под буффер

цикл чтения файла
{
читаем в Buffer

CryptMsgUpdate( ..., isFinal) + проверка что это не финальный блок

CryptMsgGetParam(hMsg, CMSG_ENVELOPE_ALGORITHM_PARAM, 0, nil, szAlgInfo)
GetMem(AlgInfo, szAlgInfo);
CryptMsgGetParam(hMsg, CMSG_ENVELOPE_ALGORITHM_PARAM, 0, AlgInfo, szAlgInfo)
ENVELOPE_ALGORITHM = AlgInfo.pszObjId;

CryptMsgGetParam(hMsg, CMSG_TYPE_PARAM, ..
if iType <> CMSG_ENVELOPED then - какой-то мусор, не CMS Enveloped

CryptMsgControl(hMsg, 0, CMSG_CTRL_DECRYPT, @DecryptParameters)




}


DecryptParameters - содержит информацию о сертификате, для расшифровки,
получаю отдельно (достаточно считать отдельно файл до первого вызова Update и получить информацию о получателях => найти по серийному номеру нужный у себя сертификат)
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#17 Оставлено : 12 августа 2020 г. 15:53:19(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
попробовал через largecms - 13с на 10 мб файле + нагружает ЦП
посмотрел вызовы...

Вам понятно, что делает ProcessMessage?

почему потом вызывается CheckEnvelopeAlg?
и... в финале Decrypt?


Спасибо за эксперимент! В общем, я подготовил зашифрованный файл 10 МБ и проверил. Все четко как у вас, секунд 10 не больше и все работает. Но когда я готовлю файл размером 160 МБ (200 это было в BASE64, в байтах 160 МБ), то все виснет в функции ProcessMessage в цикле do. То есть, CryptMsgUpdate работает, но очень медленно. Да, я понимаю что делает ProcessMessage, эта функция порциями грузит в структуры Windows контейнер CMS. По какой-то причине у меня нелинейная зависимость времени загрузки файлов. 10 МБ грузится 10 секунд, хочется ожидать, что 160 МБ будет грузиться 160 секунд. Но увы, там время стремится к получасу примерно. И почему-то не важно какими порциями я веду обработку, что по 1 МБ, что по 10 МБ, что по 100 МБ (это как в оригинале).
Offline Андрей *  
#18 Оставлено : 12 августа 2020 г. 16:02:31(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
исправляйте...

Я по коду из largecms

сделал DecodeAndDecrypt_NEW
в ней:
Код:

   m_hMsg = Win32.OpenMessageToDecode(StreamInfo); 
            Win32.ProcessMessage_NEW(m_hMsg, encodedFile);

и всё

в ProcessMessage_NEW:

после успешного вызова CryptMsgUpdate добавил
Код:

                    Win32.CheckEnvelopeAlg(hMsg); 
                    Win32.Decrypt(hMsg);


в Decrypt
нужно проанализировать код ошибки (сообщение уже расшифровано (т.е. текущий блок)
или закомментировать:
// throw new Exception("CryptMsgControl error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));

итог: 1.5с на 10 Мб
Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей *  
#19 Оставлено : 12 августа 2020 г. 16:04:46(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
p.s. но это не оптимальный вариант, нужно как в сообщении16 - проанализировать сначала, какие есть серийные, получить нужный сертификат\контейнер\ключ и его использовать в вызовах
Техническую поддержку оказываем тут
Наша база знаний
Offline esolomonov  
#20 Оставлено : 12 августа 2020 г. 16:10:40(UTC)
esolomonov

Статус: Участник

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

Автор: Андрей * Перейти к цитате
p.s. но это не оптимальный вариант, нужно как в сообщении16 - проанализировать сначала, какие есть серийные, получить нужный сертификат\контейнер\ключ и его использовать в вызовах


Не поможет. У меня тормозит CryptMsgUpdate. Я провел четкие измерения, выставил буфер в 100 МБ и загрузил файл 10 МБ — 6 секунда. Файл 37 МБ — 84 секунды. CryptMsgUpdate вызывался один раз и эти 84 секунды все ушли на этот вызов. То есть, не важно что делается после CryptMsgUpdate, тормозит именно CryptMsgUpdate.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
3 Страницы123>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.