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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline The_Cjay  
#1 Оставлено : 30 августа 2012 г. 16:58:26(UTC)
The_Cjay

Статус: Новичок

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

Всем доброго времени суток!

Я пытаюсь сгенерировать запрос на сертификат посредством WinAPI, на C++. Не суть важно зачем, но все-таки.
Ранее у меня был кусок javascript-кода, выдраный невесть откуда, который генерировал запросы на сертификат в браузере посредством обращения к COM-интерфейсам Windows (соответственно с разделением XEnroll и CertEnroll) и я не мудрствуя лукаво решил передрать вызовы методов и интерфейсов в точности оттуда. Вот какой получился код.

Код:

#define PROV_GOST_2001_DH 75
#define CRYPTOPRO_PROVIDER_NAME "Crypto-Pro"

LPCTSTR ConstructRequest(LPCTSTR commaDelemitedOIDs, LPCTSTR strDN,LPTSTR containerName) const {
	BSTR dn = _bstr_t(strDN).copy();
	BSTR cname = _bstr_t(containerName).copy();	
	BSTR* req = NULL;
	BSTR provName = _bstr_t(CRYPTOPRO_PROVIDER_NAME).copy();

	HR(CoInitialize(NULL));	
	if ((m_hResult!=S_OK)&&(m_hResult!=S_FALSE)){
		m_logger.Error(_T("Не удалось инициализировать COM"));
	}

	CO(X500DistinguishedName,m_pSubjectName);
	ERRCHK("Не удалось создать элемент управления DN");
	
	HR(m_pSubjectName->Encode(dn,XCN_CERT_NAME_STR_FORWARD_FLAG));
	ERRCHK("Не удалось задать DN элемент управления запросом на сертификат");

	CO(X509PrivateKey,m_pPrivateKey);
	ERRCHK("Не удалось создать элемент управления личным ключом");
	
	HR(m_pPrivateKey->put_ProviderType((X509ProviderType)PROV_GOST_2001_DH));
	HR(m_pPrivateKey->put_ExportPolicy(XCN_NCRYPT_ALLOW_EXPORT_FLAG));	
	HR(m_pPrivateKey->put_KeySpec(XCN_AT_KEYEXCHANGE));
	HR(m_pPrivateKey->put_ContainerName(cname));
	
	CO(X509CertificateRequestPkcs10,m_pRequest);
	ERRCHK("Не удалось создать элемент управления запросом на сертификат");
	HR(m_pRequest->put_Subject(m_pSubjectName));

	HR(m_pRequest->InitializeFromPrivateKey(X509CertificateEnrollmentContext::ContextUser,m_pPrivateKey,NULL));

	CO(X509Enrollment,m_pEnroll);
	ERRCHK("Не удалось создать элемент управления сертификатами");

	HR(m_pEnroll->InitializeFromRequest(m_pRequest));
	
	m_pEnroll->CreateRequest(XCN_CRYPT_STRING_BASE64,req); 
	
	return NULL;
}


Макрос ERRCHK - для обработки ошибок, макрос HR - для установки HRESULT, CO - для создания COM-объекта.

Все по идет по плану до вот этой строчки:
HR(m_pRequest->InitializeFromPrivateKey(X509CertificateEnrollmentContext::ContextUser,m_pPrivateKey,NULL));
на которой благополучно падает с Access Violation.

В связи с чем у меня возникает несколько вопросов:

1. Как правильно конструировать из кода запросы на сертификаты? Что обязательно надо указать в ключе и реквесте?
2. Я не специалист в COM - Занимаюсь им по стольку, по скольку. Как в вышеописанных ситуациях определять источник ошибки и ее описание? В HRESULT разумеется ничего не падает.
3. Есть ли какие-либо особенности в работе с CryptoAPI на C++ в отличие, скажем, от .NET?
4. Где лучше всего читать на такие темы?

Заранее спасибо за совет!

Отредактировано пользователем 30 августа 2012 г. 16:59:45(UTC)  | Причина: Не указана

Offline Kirill Sobolev  
#2 Оставлено : 30 августа 2012 г. 17:31:11(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Цитата:
HR(m_pRequest->InitializeFromPrivateKey(X509CertificateEnrollmentContext::ContextUser,m_pPrivateKey,NULL));

В качестве последнего параметра передавайте пустую строку, а не NULL.
Техническую поддержку оказываем тут
Наша база знаний
Offline The_Cjay  
#3 Оставлено : 31 августа 2012 г. 2:53:26(UTC)
The_Cjay

Статус: Новичок

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

Пробовал. Результат тот же, только адреса другие.
Offline Максим Коллегин  
#4 Оставлено : 31 августа 2012 г. 3:24:34(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
так - работает:
Цитата:
HRESULT VistaEnroll::createPKCS10( BSTR rdn, BSTR usage, BSTR *Request)
{
HRESULT hr;
IX509Enrollment* pEnroll = NULL;
IX509CertificateRequestPkcs10* pPkcs10 = NULL;
IX509Extensions* pExtensions = NULL;
IX509ExtensionEnhancedKeyUsage* pExtensionEKU = NULL;
IX509ExtensionKeyUsage * pExtensionKU = NULL;
IObjectId *pEKUObjectId = NULL;
IObjectIds *pEKUObjectIds = NULL;
IObjectId *hashAlg = NULL;
IX500DistinguishedName* provName = NULL;

//Инициализация COM
hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
ENROLL_ERROR(hr);

IX509PrivateKey* pKey = NULL;
// Create IX509PrivateKey
hr = CoCreateInstance(
__uuidof(CX509PrivateKey),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509PrivateKey),
(void **) &pKey);
ENROLL_ERROR(hr);

hr = pKey->put_ProviderType((X509ProviderType)providerType_);
ENROLL_ERROR(hr);

if(providerName_)
hr = pKey->put_ProviderName(providerName_);
ENROLL_ERROR(hr);

if(containerName_)
hr = pKey->put_ContainerName(containerName_);
ENROLL_ERROR(hr);


// Create IX509ExtensionKeyUsage
hr = CoCreateInstance(
__uuidof(CX509ExtensionKeyUsage),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509ExtensionKeyUsage),
(void **) &pExtensionKU);
ENROLL_ERROR(hr);

if(atSignature)
{
hr = pKey->put_KeySpec(XCN_AT_SIGNATURE);
ENROLL_ERROR(hr);
}
else
{
hr = pKey->put_KeySpec(XCN_AT_KEYEXCHANGE);
ENROLL_ERROR(hr);
}

if(LimitExchangeKeyToEncipherment)
{
hr = pExtensionKU->InitializeEncode((X509KeyUsageFlags)
(XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE | XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE));
ENROLL_ERROR(hr);
}
else
{
hr = pExtensionKU->InitializeEncode((X509KeyUsageFlags)
(XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE | XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
| XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE | XCN_CERT_NON_REPUDIATION_KEY_USAGE));
ENROLL_ERROR(hr);
}

hr = pKey->put_MachineContext((provFlags_ & CRYPT_MACHINE_KEYSET) != 0);
ENROLL_ERROR(hr);

hr = pKey->put_Silent((provFlags_ & CRYPT_SILENT) != 0);
ENROLL_ERROR(hr);

if(useExisting_)
hr = pKey->Open();
else
{
if(Exportable)
pKey->put_ExportPolicy(XCN_NCRYPT_ALLOW_EXPORT_FLAG);
hr = pKey->Create();
}
ENROLL_ERROR(hr);
if(!containerName_)
{
hr = pKey->get_ContainerName(&containerName_);
ENROLL_ERROR(hr);
}

// Create IX509Enrollment
hr = CoCreateInstance(
__uuidof(CX509CertificateRequestPkcs10),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509CertificateRequestPkcs10),
(void **) &pPkcs10);
ENROLL_ERROR(hr);

if(provFlags_ & CRYPT_MACHINE_KEYSET)
hr = pPkcs10->InitializeFromPrivateKey(ContextMachine, pKey, NULL);
else
hr = pPkcs10->InitializeFromPrivateKey(ContextUser, pKey, NULL);
ENROLL_ERROR(hr);


}

Отредактировано пользователем 31 августа 2012 г. 3:25:29(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в центре поддержки
Offline The_Cjay  
#5 Оставлено : 31 августа 2012 г. 11:58:42(UTC)
The_Cjay

Статус: Новичок

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

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