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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline egera  
#1 Оставлено : 18 августа 2009 г. 19:13:41(UTC)
egera

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

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

Уважаемые, добрый день!
Подскажите, пожалуйста, где может иметь место проблема:
Есть COM-объект, который на входе получает данные для шифрования в Base64 кодировке, шифрует их и возвращает результат опять же в Base64 кодировке. (Аналогично с расшифрованием).
Есть некий класс на .Net, который дёргает методы шифрования и дешифрации из COM-объекта.
Создаю тестовую программу, которая в цикле читает файлы в некой директории и
1. Сначала шифрует файл.
2. Затем расшифроввывает файл.
3. Затем побайтово сравнивает результат расшифрования с входным файлом.

Так вот, где имеет место быть проблема: иногда побайтовое сравнение говорит о том, что исходные данные и расшифрованные не совпадают. Причём происходит это на разных файлах и нечасто. Причём, если тут же попробовать зашифровать и расшифровать ещё раз - бывает, что всё нормально, а бывает, что снова результат сравнения неверный :(
Как такое может быть?
Offline Kirill Sobolev  
#2 Оставлено : 18 августа 2009 г. 20:12:30(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Варианта два - ошибка в COM объекте либо ошибка в классе .NET. Например, в COM неправильно выделяется память и поэтому иногда туда попадает мусор, который и влияет на результат.
Техническую поддержку оказываем тут
Наша база знаний
Offline egera  
#3 Оставлено : 18 августа 2009 г. 21:27:41(UTC)
egera

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

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

В .Net всё просто. Там вряд ли. Вероятнее всего действительно в COM объекте, только вот непонятно, где в этом коде может неправильно выделяться память?
Код:

	DWORD cbContent;// Длина сообщения
	BYTE* pbContent = NULL;
	int icbContent = 0;
	HCRYPTPROV hCryptProv = 0;        // дескриптор CSP 
	HCERTSTORE hStoreHandle = 0;      // дескриптор хранилища сертификатов
	PCCERT_CONTEXT pRecipientCert = NULL;
	CComBSTR tempCComBSTR;
	CComBSTR RetBSTR;
	int tempLen;
	LPSTR tempByte = NULL;
	LPSTR szDest = NULL;
	int pnDestLen;

	try
    {

		CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
		CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;

		BYTE*    pbEncryptedBlob = NULL;
		DWORD    cbEncryptedBlob;

		tempCComBSTR = CComBSTR(ByteArray);
		tempLen = tempCComBSTR.Length();

		tempByte = (LPSTR)malloc(tempLen);

		WideCharToMultiByte(
					CP_ACP, 
					0, 
					(LPCWSTR)CStringW(ByteArray), 
					-1,
					tempByte, 
					(int)tempLen, 
					NULL, 
					NULL);

		Base64Decode(tempByte, tempLen, NULL, &icbContent);

		pbContent = (BYTE*)malloc(icbContent);
		cbContent = icbContent;
		if (Base64Decode(tempByte, tempLen, pbContent, &icbContent) ==  FALSE)
		{
			SetErrorMessage(L"Неверно заданы входные параметры. Невозможно преобразовать входную строку из BASE64.(Код ошибки - 80004)");
			SetErrorCode(80004);
			goto done;
		}

		if (tempByte) free(tempByte);
		if (tempCComBSTR)
		{
			tempCComBSTR.Empty();
			delete tempCComBSTR;
		}

		// Получение дескриптора криптографического провайдера.
		if(!CryptAcquireContext(
			&hCryptProv,         // Адрес возврашаемого дескриптора.
			0,                   // Используется имя текущего зарегестрированного пользователя.
			NULL,                // Используется провайдер по умолчанию.
			PROV_GOST_2001_DH,   // Необходимо для зашифрования и подписи.
			CRYPT_VERIFYCONTEXT))                // Никакие флаги не нужны.
		{
		    SetErrorMessage(L"Невозможно инициализировать контекст криптопровайдера.(Код ошибки - 80005)");
			SetErrorCode(80005);
			return S_FALSE;
		}

		// Открытие системного хранилища сертификатов.
		hStoreHandle = CertOpenSystemStore(hCryptProv, CW2A(p_StoreName));

		if(!hStoreHandle)
		{
		    SetErrorMessage(L"Невозможно открыть системное хранилище сертификатов.(Код ошибки - 80007)");
			SetErrorCode(80007);
			goto done;
		}

		// Получение указателя на сертификат получателя с помощью
		// функции GetRecipientCert. 
		pRecipientCert = GetRecipientCert(hStoreHandle, p_Hash);

		if(!pRecipientCert)
		{
			goto done;
		}

		// Инициализация структуры с нулем.
		memset(&EncryptAlgorithm, 0, sizeof(CRYPT_ALGORITHM_IDENTIFIER));
		EncryptAlgorithm.pszObjId = szOID_CP_GOST_28147;  

		// Инициализация структуры CRYPT_ENCRYPT_MESSAGE_PARA. 
		memset(&EncryptParams, 0, sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
		EncryptParams.cbSize =  sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
		EncryptParams.dwMsgEncodingType = MY_ENCODING_TYPE;
		EncryptParams.hCryptProv = hCryptProv;
		EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm;

		// Вызов функции CryptEncryptMessage.
		if(!CryptEncryptMessage(
			&EncryptParams,
			1,
			&pRecipientCert,
			pbContent,
			cbContent,
			NULL,
			&cbEncryptedBlob))
		{
		    SetErrorMessage(L"Невозможно определить размер данных для шифрования.(Код ошибки - 80009)");
			SetErrorCode(80009);
			goto done;
		}

		// Распределение памяти под возвращаемый BLOB.
		pbEncryptedBlob = (BYTE*)malloc(cbEncryptedBlob);

		if(!pbEncryptedBlob)
		{
		    SetErrorMessage(L"Невозможно выделить память для шифрования.(Код ошибки - 80011)");
			SetErrorCode(80011);
			goto done;
		}
		// Повторный вызов функции CryptEncryptMessage для зашифрования содержимого.
		if(!CryptEncryptMessage(
			&EncryptParams,
			1,
			&pRecipientCert,
			pbContent,
			cbContent,
			pbEncryptedBlob,
			&cbEncryptedBlob))
		{
			BSTR WindErr = SysAllocString(GetLastErrorWind());
			AddToCallback(WindErr);
		    SetErrorMessage(L"Невозможно зашифровать данные.(Код ошибки - 80013)");
			SetErrorCode(80013);
			goto done;
		}

		pnDestLen = Base64EncodeGetRequiredLength(cbEncryptedBlob,										ATL_BASE64_FLAG_NOCRLF );//| ATL_BASE64_FLAG_NOPAD
		szDest = (LPSTR)malloc(pnDestLen);

		if (Base64Encode(
				pbEncryptedBlob,
				cbEncryptedBlob,
				szDest,
				&pnDestLen,
				ATL_BASE64_FLAG_NOCRLF) == FALSE)
		{
			SetErrorMessage(L"Невозможно возвратить зашифрованные данные.(Код ошибки - 80019)");
			SetErrorCode(80019);
			goto done;
		}

		RetBSTR = CComBSTR(pnDestLen,szDest);

		*out_message = RetBSTR.Detach();
		RetBSTR.Empty();
		delete RetBSTR;

done:
			if (pRecipientCert)
				CertFreeCertificateContext(pRecipientCert);
			if(hCryptProv) 
			{
				BOOL Ret;
				Ret = CryptReleaseContext(hCryptProv, 0);
			}
			if(hStoreHandle) {
				CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
			}
		if (pbContent) free(pbContent);
		if(szDest) free(szDest);
		if (pbEncryptedBlob) free(pbEncryptedBlob);
	}
    catch(exception &e)
    {
        AddToCallback(A2BSTR(e.what()));
		SetErrorMessage(L"Не удалось зашифровать данные.(Код ошибки - 80017)");
		SetErrorCode(80017);
      	return S_FALSE;    
    }

	return S_OK;    
Offline Kirill Sobolev  
#4 Оставлено : 19 августа 2009 г. 14:41:44(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Я же не сказал что точно проблема в выделении памяти - это как вариант. Проблема, кстати, может быть и в процедуре расшифрования.
Если в каком-то конкретном файле исходные данные не совпадают с расшифрованными - попробуйте расшифровать его какой-то сторонней утилитой, например csptest.
Техническую поддержку оказываем тут
Наша база знаний
Offline egera  
#5 Оставлено : 19 августа 2009 г. 15:01:38(UTC)
egera

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

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

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