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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Михаил_Dia  
#1 Оставлено : 18 июля 2012 г. 16:28:34(UTC)
Михаил_Dia

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

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

Возникла проблем с формирование CMS сообщения. При вызове метода CryptSignMessage, возникает ошибка:
Код:
Cannot find the certificate and private key for decryption.


Вот собственно как вызываю:
Код:
	//--------------------------------------------------------------------
	// Получение дескриптора контекста криптографического провайдера.
	//--------------------------------------------------------------------
	if (!CryptAcquireContext(
		&hProv, 
		(LPCSTR)pbContainerName, 
		"Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider", 
		PROV_GOST_2001_DH, 
		CRYPT_MACHINE_KEYSET)) 
	{
		char *msg = getErorrMessage("CryptAcquireContext() failed");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
	}

	printf("\nOK1");
	//--------------------------------------------------------------------
	// Получение пользовательского ключа (по двум типам ключей)
	//--------------------------------------------------------------------
	DWORD keyType = AT_SIGNATURE;
	if (!CryptGetUserKey(hProv, keyType, &hKey)) {
		keyType = AT_KEYEXCHANGE;
		if (!CryptGetUserKey(hProv, keyType, &hKey)) {
			char *msg = getErorrMessage("CryptGetUserKey() failed. Tried both key types.");
			throwCryptoException(env, msg);
			Error = true;
			goto Error;
		}
	}
	
	printf("\ngetting key");
	//--------------------------------------------------------------------
	// Определение размера пользовательского сертификата.
	//--------------------------------------------------------------------	
	if (!CryptGetKeyParam (hKey, KP_CERTIFICATE, NULL,&dwUserCertLength, 0)) {
		char *msg = getErorrMessage("GetKeyParam() failed(first).");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
	}

	printf("\nCertLength");

	//--------------------------------------------------------------------
	// Распределение памяти под буфер пользовательского сертификата.
	//--------------------------------------------------------------------
	if (!(pbUserCert = (BYTE *)VirtualAlloc(NULL,dwUserCertLength,MEM_COMMIT,PAGE_READWRITE))){
		char *msg = getErorrMessage("VirtualAlloc() for UserCert failed.");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
	}

	printf("\nUserCertAlloc");
	//--------------------------------------------------------------------
	// Получение пользовательского сертификата.
	//--------------------------------------------------------------------
	if (!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbUserCert,&dwUserCertLength, 0)) {
		char *msg = getErorrMessage("CryptGetKeyParam() failed(second).");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
	}

	printf("\nUserCertGet");
	//--------------------------------------------------------------------
	// Формирование контекста сертификата.
	//--------------------------------------------------------------------
	if (!(pUserCert = CertCreateCertificateContext(X509_ASN_ENCODING, pbUserCert, dwUserCertLength))) {
		char *msg = getErorrMessage("CertCreateCertificateContext() failed.");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
	}

	printf("\nUserCertContext");

	//--------------------------------------------------------------------
	// Инициализация структуры для подписи.
	//--------------------------------------------------------------------
    SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
    SigParams.dwMsgEncodingType = X509_ASN_ENCODING;
    SigParams.pSigningCert = pUserCert;
	SigParams.HashAlgorithm.pszObjId = pUserCert->pCertInfo->SignatureAlgorithm.pszObjId;
	SigParams.HashAlgorithm.Parameters.cbData = 0;//pUserCert->pCertInfo->SignatureAlgorithm.Parameters.cbData;
	SigParams.HashAlgorithm.Parameters.pbData = NULL;
    SigParams.cMsgCert = 1;
    SigParams.rgpMsgCert = &pUserCert;
    SigParams.cAuthAttr = 0;
    SigParams.dwInnerContentType = 0;
    SigParams.cMsgCrl = 0;
    SigParams.cUnauthAttr = 0;
    SigParams.dwFlags = 0;
    SigParams.pvHashAuxInfo = NULL;
    SigParams.rgAuthAttr = NULL;

	printf("\nSigParamsInit");
	
	//--------------------------------------------------------------------
	// Определение размера буфера для CMS сообщения.
	//--------------------------------------------------------------------	
	//pbBuffer - данные для подписыванеия
	const BYTE* MessageArray[] = {pbBuffer};
	DWORD_PTR MessageSizeArray[1];
	MessageSizeArray[0] = dwBufferLen;
	DWORD cbSignedMessageBlob;
	if(!CryptSignMessage(
        &SigParams,
        FALSE,
        1,
        MessageArray,
        MessageSizeArray,
        NULL,
        &cbSignedMessageBlob))
    {
        char *msg = getErorrMessage("CryptSignMessage() failed(first).");
		throwCryptoException(env, msg);
		Error = true;
		goto Error;
    }
	else 
		printf(TEXT("%d bytes needed for the encoded BLOB.\n"), cbSignedMessageBlob);


Подскажите, что делаю не так?
Offline Андрей Писарев  
#2 Оставлено : 18 июля 2012 г. 16:44:44(UTC)
Андрей *

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

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

Сказал «Спасибо»: 555 раз
Поблагодарили: 2252 раз в 1757 постах
Есть поиск... "по тексту проблемы", он не помог?


http://www.cryptopro.ru/....aspx?g=posts&t=1556

Цитата:
Ошибка: Не удается найти сертификат и закрытый ключ для расшифровки.
(0x8009200B)
...
повторно привязал серт к контейнеру - заработало. При этом в папке снова появился файл с именем, равным идентификатору ключа субъекта. Но в этот раз со ссылкой на нужный контейнер.

....

Отредактировано пользователем 18 июля 2012 г. 16:49:21(UTC)  | Причина: Не указана

Техническую поддержку оказываем тут
Наша база знаний
Offline Михаил_Dia  
#3 Оставлено : 18 июля 2012 г. 17:16:34(UTC)
Михаил_Dia

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

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

Андрей * написал:
Есть поиск... "по тексту проблемы", он не помог?


http://www.cryptopro.ru/....aspx?g=posts&t=1556

Цитата:
Ошибка: Не удается найти сертификат и закрытый ключ для расшифровки.
(0x8009200B)
...
повторно привязал серт к контейнеру - заработало. При этом в папке снова появился файл с именем, равным идентификатору ключа субъекта. Но в этот раз со ссылкой на нужный контейнер.

....


Изначально, генерилась ключевая пара на етокене + запрос, затем была получена цепочка сертов и импортирована на етокен, соответственно не понятно что и как повторно привязать?
Ведь в коде, я получаю сертификат через CryptGetKeyParam по ключу и он как раз тот, которым я и собираюсь подписывать.

Отредактировано пользователем 18 июля 2012 г. 17:18:36(UTC)  | Причина: Не указана

Offline Михаил_Dia  
#4 Оставлено : 18 июля 2012 г. 18:04:46(UTC)
Михаил_Dia

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

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

Пробовал вот так привязать:

перед вызовом CryptSignMessage вызываю:
Код:
KeyContext.cbSize = sizeof(CERT_KEY_CONTEXT);
      KeyContext.hCryptProv = hProv;
      KeyContext.dwKeySpec = keyType;

      if(!CertSetCertificateContextProperty(pUserCert, CERT_KEY_CONTEXT_PROP_ID, 0, &KeyContext)){
            char *msg = getErorrMessage("CertSetCertificateContextProperty() failed.");
            throwCryptoException(env, msg);
            Error = true;
            goto Error;
      }

Отрабатывает, но при вызове CryptSignMessage ошибка: The parameter is incorrect.

Так же попробовал:
Код:
CRYPT_KEY_PROV_INFO provInfo;
      provInfo.pwszContainerName = CharToLPWSTR((LPCSTR)pbContainerName);
      provInfo.pwszProvName = CharToLPWSTR("Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider");
      provInfo.dwProvType = PROV_GOST_2001_DH;
      provInfo.cProvParam = 0;
      provInfo.dwFlags = 0;
      provInfo.rgProvParam = 0;
      provInfo.dwKeySpec = keyType;

      if(!CertSetCertificateContextProperty(pUserCert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provInfo)){
            char *msg = getErorrMessage("CertSetCertificateContextProperty() failed.");
            throwCryptoException(env, msg);
            Error = true;
            goto Error;
      }

Отрабатывает, но при вызове CryptSignMessage также ошибка: The parameter is incorrect
Offline Михаил_Dia  
#5 Оставлено : 18 июля 2012 г. 19:03:42(UTC)
Михаил_Dia

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

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

Ошибка заключалась в том, что по ошибке поставил:
Код:
SigParams.dwMsgEncodingType = X509_ASN_ENCODING;


А должно быть:
Код:
SigParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING;


Теперь успешно формируется CMS сообщение:)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.