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

Уведомление

Icon
Error

5 Страницы123>»
Опции
К последнему сообщению К первому непрочитанному
Offline burning-dragon  
#1 Оставлено : 20 сентября 2013 г. 15:03:43(UTC)
burning-dragon

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

Группы: Участники
Зарегистрирован: 19.09.2013(UTC)
Сообщений: 18

Добрый день, возник вопрос по работе с большими файлами. До сих пор для шифрования и расшифровки использовались высокоуровненые функции CryptEncryptMessage и CryptDecryptMessage, теперь встала задача поблочной обработки файлов и возникли проблемы следующего характера - при потоковой обработке с помощью CryptMsgOpenToEncode после сбора обработанных данных файл оказывается не совместим с форматом CryptEncryptMessage/CryptDecryptMessage. Используется следующий код:

Код:
int ICryptoImpl::encrypt_stream_ex(std::istream& plainStream, std::ostream& cryptoStream, std::vector<std::string>& saRecepientIDs)
{
	if (saRecepientIDs.size() < 2)
		return NoSender;

	std::string strSender = saRecepientIDs.front();

	std::vector<PCCERT_CONTEXT> arrCertRecipient;
	for_each_(itRecipient, std::vector<std::string>, saRecepientIDs)
	{
		PCCERT_CONTEXT pFountCert = CertFindInStore(*itRecipient);
		if(pFountCert == NULL)
			return CantFindCertInStore;
		arrCertRecipient.push_back(pFountCert);
	}

	//Первый сертификат - сертификат отправителя. Убедимся в этом и откроем провайдера
	AUTO_HCRYPTPROV hProv;
	DWORD dwFlag = CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_CACHE_FLAG ;
	if (!m_Settings.bShowUICSP) dwFlag |= CRYPT_ACQUIRE_SILENT_FLAG;
	if (!::CryptAcquireCertificatePrivateKey(arrCertRecipient.front(), dwFlag, NULL, hProv, NULL, NULL))
		return CantFindPrivateKey;

	//Начинаем шифровать --------------------------------------------------------------------
	//соберем информацию по сертификатам шифрования
	AUTO<PCERT_INFO*> pciRecipient = new PCERT_INFO[arrCertRecipient.size()];
	if(pciRecipient == NULL)
		return OutOfMemory;
	//Подготовим массивы ключей и данных сертификатов
	int nCertIdx = 0;
	for_each_(itCert, std::vector<PCCERT_CONTEXT>, arrCertRecipient)
	{
		PCCERT_CONTEXT& pCertContext = *itCert;
		pciRcpnt[nCertIdx++] = pCertContext->pCertInfo;
	}

	//подготовим оболочку PKCS7-ASN
	struct callbackStream
	{
		static BOOL WINAPI CmsgStreamOutputCallback(const void *pvArg, BYTE *pbData, DWORD cbData, BOOL fFinal)
		{
			callbackStream* pcsShell = (callbackStream*)pvArg;
			if(pcsShell->bGotFinal)return TRUE;
			pcsShell->cryptoStream.write(reinterpret_cast<const char*>(pbData), cbData);
			pcsShell->bGotFinal = fFinal;
			return TRUE;
		}
		std::ostream& cryptoStream;
		BOOL bGotFinal;
	} csShell = { cryptoStream, FALSE };
	CMSG_STREAM_INFO msg_si;
	{
		msg_si.cbContent = 64;//CMSG_INDEFINITE_LENGTH;
		msg_si.pfnStreamOutput = &callbackStream::CmsgStreamOutputCallback;
		msg_si.pvArg = &csShell;
	}

	CMSG_ENVELOPED_ENCODE_INFO eeiMsg;
	{
		memset(&eeiMsg, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO));
		eeiMsg.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);
		eeiMsg.hCryptProv = hProv;
		memset(&eeiMsg.ContentEncryptionAlgorithm, 0, sizeof(CRYPT_ALGORITHM_IDENTIFIER));
		eeiMsg.ContentEncryptionAlgorithm.pszObjId = szOID_CP_GOST_28147;
		eeiMsg.cRecipients = arrCertRcpt.size();
		eeiMsg.rgpRecipients = pciRcpnt;
	}

	//Получаем хендл криптографического сообщения
//	AUTO_HCRYPTMSG hMsg = ::CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
//		CPCRYPT_MESSAGE_CADES_DISABLE, CMSG_ENVELOPED, &eeiMsg, NULL, NULL);
	AUTO_HCRYPTMSG hMsg = ::CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
		NULL/*CPCRYPT_MESSAGE_CADES_DISABLE*/, CMSG_ENVELOPED, &eeiMsg, NULL, &msg_si);
	if (hMsg == NULL)
		return CantOpenToEncode;

	DWORD max_buff = macros::calc_read_buffer(plainStream) + 1;
	AUTO<LPBYTE> bData = new BYTE[max_buff];
	if (bData == NULL)
		return OutOfMemory;

	for(plainStream.seekg(0, plainStream.beg); !plainStream.eof();)
	{
		int nread = macros::read_nbyte(bData, max_buff, plainStream);
		if(nread == 0)
			return CantReadStream;
		if (!::CryptMsgUpdate(hCryptMsg, bData, nread, plainStream.eof() != false))
			return CantAddDataToMessage;
	}
/*
	DWORD dwMsgLen = 0;
	if(!::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &dwMsgLen))
		return -1;

	AUTO_CRYPT_DATA_BLOB cmsgcp(dwMsgLen);
	if(!::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, cmsgcp->pbData, &cmsgcp->cbData))
		return -1;

	std::ofstream fout("d:\\encrypt_a.dat");
	fout.write((LPCTSTR)cmsgcp->pbData, cmsgcp->cbData);

*/
	return NoError;
}


Если же потоки не использовать и получать данные через ::CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM...) цельным куском, то все прекрасно работает.
Подскажите, в чем проблема и как обойти?

Отредактировано пользователем 21 сентября 2013 г. 10:04:34(UTC)  | Причина: поправил код

Offline Юрий  
#2 Оставлено : 20 сентября 2013 г. 15:17:02(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 95 раз в 68 постах
И какая ошибка возникает?
И что если использовать CMSG_INDEFINITE_LENGTH?
С уважением,
Юрий Строжевский
Offline burning-dragon  
#3 Оставлено : 20 сентября 2013 г. 15:24:29(UTC)
burning-dragon

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

Группы: Участники
Зарегистрирован: 19.09.2013(UTC)
Сообщений: 18

При расшифровке GetLastError возвращает "Набор ключей не определен. (0x80090019)"
При использовании CMSG_INDEFINITE_LENGTH (как и при больших значениях msg_si.cbConten) при вызове CryptDecryptMessage возвращается ошибка заголовка ASN1. Ну и редактор ASN1 не может открыть файлик.
Offline Юрий  
#4 Оставлено : 20 сентября 2013 г. 15:24:41(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 95 раз в 68 постах
Да и смотрите документацию лучше:
Цитата:
dwMsgType - This must be one of the following values

Так что никаких CMSG_ENVELOPED | CMSG_DATA.
С уважением,
Юрий Строжевский
Offline burning-dragon  
#5 Оставлено : 20 сентября 2013 г. 15:29:41(UTC)
burning-dragon

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

Группы: Участники
Зарегистрирован: 19.09.2013(UTC)
Сообщений: 18

По поводу CMSG_ENVELOPED | CMSG_DATA согласен. Это уже ошметки экспериементов... с единственным флагом CMSG_ENVELOPED получалась та же беда
Offline Юрий  
#6 Оставлено : 20 сентября 2013 г. 15:30:46(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 95 раз в 68 постах
И закрывайте контекст сообщения в конце:
Цитата:
CryptMsgClose(hMsg);
С уважением,
Юрий Строжевский
Offline burning-dragon  
#7 Оставлено : 20 сентября 2013 г. 15:36:13(UTC)
burning-dragon

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

Группы: Участники
Зарегистрирован: 19.09.2013(UTC)
Сообщений: 18

AUTO_HCRYPTMSG - класс-аксессор закрывающий хэндл в деструкторе
Offline Юрий  
#8 Оставлено : 20 сентября 2013 г. 15:41:49(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 95 раз в 68 постах
У входного потока сняты флаги
Цитата:
std::ifstream inFile(inName.c_str(),std::ios_base::binary);
inFile.unsetf(std::ios_base::skipws);

Для выходного потока вызывается "flush()"?
С уважением,
Юрий Строжевский
Offline burning-dragon  
#9 Оставлено : 20 сентября 2013 г. 15:43:46(UTC)
burning-dragon

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

Группы: Участники
Зарегистрирован: 19.09.2013(UTC)
Сообщений: 18

Вне данного метода
Offline Юрий  
#10 Оставлено : 20 сентября 2013 г. 15:44:35(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 95 раз в 68 постах
И ещё: вставьте код нормально, с помощью специальной кнопочки применяющей подсветку кода. Лучше смотреть будет.
С уважением,
Юрий Строжевский
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
5 Страницы123>»
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.